Skip to content

feat(api): expose action summaries across API surfaces - #8693

Closed
hurryup52 wants to merge 4 commits into
JSONbored:mainfrom
hurryup52:feat/8525-api-action-summaries
Closed

feat(api): expose action summaries across API surfaces#8693
hurryup52 wants to merge 4 commits into
JSONbored:mainfrom
hurryup52:feat/8525-api-action-summaries

Conversation

@hurryup52

Copy link
Copy Markdown
Contributor

Summary

  • Serves the deterministic action-sentence summary field (already rendered by the UI) through
    the REST API, GraphQL, and MCP tools — not just apps/ui — by extracting the sentence-template
    logic into a shared package.

What Changed

  • New packages/chain-summaries workspace package (@jsonbored/chain-summaries): the call/event
    sentence templates and their decode helpers, moved out of apps/ui/src/lib/metagraphed/* so both
    apps/ui and workers//src/ can share one implementation. apps/ui's own
    src/lib/metagraphed/* files now re-export from the package (no logic of their own, no import-site
    changes in apps/ui/src/components/** or apps/ui/src/routes/** — this PR carries no visual diff).
  • src/extrinsics.ts: formatExtrinsic now computes summary via summarizeCall(...) from the
    already-decoded call args.
  • workers/data-api.ts: coerceEvent now computes summary via summarizeEvent(...), reusing the
    same decoded args used for the existing args field.
  • REST schemas (schemas-src/routes/extrinsics.ts, account-extrinsics.ts, chain-events.ts,
    block-chain-events.ts) and MCP schemas (schemas-src/mcp-tools/shared.ts,
    account-extrinsics.ts, chain-events.ts, chain-events-activity.ts) each declare the new
    summary field, matching each file's existing nullable/optional convention.
  • src/graphql-sdl.ts / src/graphql.ts: summary: String added to Extrinsic and
    ChainEventRow, resolvers populate it.
  • Root package.json gets a pretypecheck hook so packages/chain-summaries's .d.ts is built
    before root tsc --noEmit runs (mirrors apps/ui's existing pretypecheck: build:client).
  • .github/workflows/validate.yml, root vitest.config.ts/eslint.config.ts: wire up the new
    package the same way packages/client/packages/ui-kit are wired up.
  • Tests added/updated across tests/graphql.test.ts, tests/mcp-server.test.ts,
    tests/zod-schemas.test.ts, tests/data-api.test.ts, and the new package's own unit tests.

Closes #8525

Registry Safety

  • Links a tracked, currently-open issue (Closes #8525).
  • No secrets, PATs, wallet data, private dashboards, private URLs, or validator-local state.
  • Generated artifacts were produced by repo scripts, not hand-edited.
  • R2-only/high-churn detail artifacts are not committed.
  • Public API/OpenAPI/schema changes are intentional and documented (new nullable summary
    field on extrinsics and chain events, REST + GraphQL + MCP).

Validation

  • npm run check
  • npm run validate
  • npm run validate:schemas
  • npm run validate:api
  • npm run validate:openapi
  • npm run validate:types
  • npm run validate:artifact-budgets
  • npm run validate:docs
  • npm run validate:intake
  • npm run validate:workflows
  • npm run worker:test
  • npm run test:coverage (via npm run test:ci, the fileParallelism/coverage-safe CI equivalent)
  • npm run scan:public-safety
  • git diff --check

JSONbored#8371 (Epic T5) shipped human-readable "action sentence" summaries for
extrinsics and chain events, but only client-side: an API or MCP consumer
still received raw call_module/call_function/call_args or pallet/method/args
and would need to reimplement the ~35 templates to get the same legibility.

Extract the template logic (apps/ui/src/lib/metagraphed/chain-summaries.ts,
plus its nested-call decode/SS58/byte-blob helpers) into a new shared
workspace package, packages/chain-summaries, importable identically by
apps/ui and workers/. apps/ui now consumes the package instead of holding its
own copy; the route-matching/display helpers that lived alongside it
(isValidExtrinsicHash, extrinsicCall, proxyRealAccount, multisigCallHash,
etc.) stay in apps/ui since they're app-specific, importing the shared
decode primitives from the package.

Add an optional summary: string | null field to the extrinsic and
chain-event schemas, computed once at the single shared builder each surface
already funnels through (formatExtrinsic in src/extrinsics.ts; coerceEvent in
workers/data-api.ts, reusing its already-decoded args rather than decoding
twice) and exposed at parity on REST, GraphQL, and the 5 relevant MCP tools.
null when no template matches, never a guessed or partially-templated
sentence.

Regenerates openapi.json, the OpenAPI-derived contract types, and the
GraphQL types via `npm run build`.

Closes JSONbored#8525
Root's typecheck never needed to build a packages/* workspace package
first, since nothing under src/workers/tests previously imported one
directly. Now that src/extrinsics.ts and workers/data-api.ts import
@jsonbored/chain-summaries, root tsc needs its dist/index.d.ts to exist --
gitignored by design (matching packages/client's own committed-dist
pattern), so a fresh checkout doesn't have it. Add the same pretypecheck
lifecycle hook apps/ui/package.json already uses for packages/client.
apps/ui/src/routes and apps/ui/src/components/metagraphed continue
importing from @/lib/metagraphed/* unchanged; those files now only
re-export the corresponding symbols from @jsonbored/chain-summaries
instead of importing the package directly, so this PR's diff carries
no visual-code changes.
Its dist/index.js and dist/index.cjs are compiled tsup build output
(committed the same way packages/client and packages/ui-kit already
are), not hand-written JS, so validate:no-hand-written-mjs should not
flag them.
@hurryup52
hurryup52 requested a review from JSONbored as a code owner July 29, 2026 15:40
@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-29 16:22:05 UTC

57 files · no blockers · CI failing · unstable

🛑 Suggested Action - Fix Blockers

  • AI review already in progress for this PR head: Another LoopOver pass is already running the AI review for this exact PR head. This pass is skipping to avoid a duplicate LLM call.

Review summary
AI review is already running for this PR head in another LoopOver pass. LoopOver is holding this PR for manual review until that pass completes.

Nits — 1 non-blocking
  • AI review already in progress for this PR head — The gate is held for a human reviewer rather than passed automatically; it re-evaluates once the in-flight review completes or on the next update.

CI checks failing

  • test
  • codecov/patch — 85.71% of diff hit (target 99.00%)

Decision drivers

  • ✅ Code review — No blockers (No AI review summary)
  • ⚠️ Gate result — Not blocking (Advisory; not blocking this PR.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8525
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ❌ 5/25 Preflight is holding this PR: the review lane is unavailable, so it is not ready for automated review.
Contributor workload ✅ 10/10 Author activity: 26 registered-repo PR(s), 5 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor hurryup52; Gittensor profile; 26 PR(s), 0 issue(s).
Linked issue satisfaction

Addressed
The diff extracts the template logic into a new shared `packages/chain-summaries` workspace consumed by both apps/ui (re-export) and workers/src, adds `summary: string|null` to REST/MCP schemas and regenerated openapi.json, populates it in extrinsics/data-api handlers, adds GraphQL fields/resolvers, and preserves the positional-array event handling (WeightsSet, StakeAdded/Removed, NeuronRegistered

Manifest validation
  • blockedPaths is retired; use settings.hardGuardrailGlobs for path holds.
Review context
  • Author: hurryup52
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: JavaScript, TypeScript, Dart, MDX, Rust
  • Official Gittensor activity: 26 PR(s), 0 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Await review-lane availability.
  • Then work through the remaining 1 step in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. gittensor:priority Maintainer-selected Gittensor priority — scores a 1.5x multiplier. Reserved for outstanding work. labels Jul 29, 2026
@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

LoopOver is closing this pull request on the maintainer's behalf (CI is failing (test, codecov/patch)). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed.

@loopover-orb loopover-orb Bot closed this Jul 29, 2026
JSONbored added a commit to JSONbored/loopover that referenced this pull request Jul 29, 2026
…ock (#9868)

* fix(selfhost): re-drive the review a restart orphaned, not just its lock

#9802 heals the active_review_tracking row at boot so the next pass cannot bounce
off a stale lock. That is only half the failure: the interrupted pass had ALREADY
published the "LoopOver is reviewing..." placeholder comment, and terminalizing
the row does not replace it. Nothing else re-drives the PR either -- the head has
not moved so no webhook fires, and the review cache is empty because the pass
never finished. The PR sits claiming a review is in progress, forever.

Observed on JSONbored/metagraphed#8693: three container recreates in one
afternoon -- two of them routine config reloads -- each killed a mid-flight
review. That PR showed "reviewing..." for 25+ minutes with zero published reviews
and zero queued work until a human noticed. Every deploy during a review does
this, which is why it has recurred.

So the boot sweep now enqueues an agent-regate-pr for each row it heals. `force`
bypasses the AI-review cache and reuse cooldown, which is right here: the
interrupted pass produced nothing to reuse, and the one-shot cadence would
otherwise replay a stale review or none at all.

prCreatedAt is carried deliberately (#9499): omitting it INVERTS the queue order
-- jobClaimSortKey would fall back to a ~9.5e11 base that sorts ahead of every
real 2026 PR, so an orphan re-queue would jump the whole contributor backlog. The
repo's regate-sort-key check caught exactly that on the first attempt.

Fail-safe throughout: a lookup or enqueue failure logs and continues, because a
healed row with no re-queue is still strictly better than a wedged one, and the
remaining rows still need healing. An unregistered repo logs a named skip rather
than enqueueing a job that cannot act.

* docs: cite the real issue number — #9866 is an unrelated open issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. gittensor:priority Maintainer-selected Gittensor priority — scores a 1.5x multiplier. Reserved for outstanding work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(api): serve the action-sentence summary field from the API, not just the UI (#8371 follow-up)

1 participant