Skip to content

docs: document exports 47%→95%, trim app-specific root exports, adopt agent-docs#245

Merged
drewstone merged 3 commits into
mainfrom
chore/trim-root-barrel-dogfood
Jul 24, 2026
Merged

docs: document exports 47%→95%, trim app-specific root exports, adopt agent-docs#245
drewstone merged 3 commits into
mainfrom
chore/trim-root-barrel-dogfood

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

The full documentation-surface overhaul (supersedes #244). Three coherent parts:

1. Document the exports (47% → 95%)

978 one-line JSDoc summaries across 168 source files, drafted by @tangle-network/agent-docs suggest (a cheap model — gpt-4.1-mini via the Tangle router — writes a summary from each undocumented export's signature + source; inserted above the declaration). Additive comments only; pnpm typecheck green; no raw model text in generated output.

2. Trim the root barrel (are they all needed? — no)

/sequences and /design-canvas are app-specific feature surfaces (timeline editing, a design canvas), not shell mechanism every product wants — removed from the root barrel. They stay importable as subpaths (@tangle-network/agent-app/sequences, /design-canvas). /studio was already subpath-only. This keeps the root entry to shared mechanism; before this, the root barrel re-exported 982 symbols (~42% of the real subpath surface).

Breaking only for a root import of those symbols — switch to the subpath (the documented convention). No internal code or test imports them from root.

3. Dogfood agent-docs

agent-app now generates its docs with @tangle-network/agent-docs (devDep) instead of the bespoke scripts/gen-codemap.mjs (deleted — the first fleet copy gone). docs:genagent-docs; the freshness gate runs agent-docs --check; docs/ now also carries llms.txt + llms-full.txt + codemap.json — the agent-readable surface, type-derived and drift-gated.

Verified

  • pnpm typecheck ✅ · pnpm test3143 pass (193 files) · agent-docs --check fresh ✅

🤖 Generated with Claude Code

…cs suggest

Fills the public-API JSDoc gap so the generated agent-readable docs (llms.txt,
API pages) carry real summaries. Drafted by @tangle-network/agent-docs suggest —
a cheap model (gpt-4.1-mini via the Tangle router) writes a one-line summary
from each undocumented export's signature + source, inserted above the
declaration. Then the deterministic doc pass (scripts/gen-codemap.mjs) picks
them up, so the committed docs stay type-derived.

- 978 JSDoc comments across 168 source files; documented coverage 47%→95%
  (3146/3318 exports).
- Additive comments only — `pnpm typecheck` stays green; behavior unchanged.
- docs/ regenerated so the codemap staleness gate passes.

These are model-drafted summaries for human review — accurate on spot-check
(e.g. AuthorizeResult → "Resolve authorization status and context for a chat
turn…"), and improvable in place; NO raw model text enters the gated output.
The generator's --check spawns a full source walk; with the JSDoc pass it now
exceeds the 5000ms default in CI. Bump to 60s (it's a subprocess, not hot code).
…d agent-docs

1. Trim — `/sequences` and `/design-canvas` are app-specific FEATURE surfaces
   (timeline editing, a design canvas), not shell mechanism every product wants.
   Removed from the root barrel; they stay importable as subpaths
   (`@tangle-network/agent-app/sequences`, `/design-canvas`). Keeps the root
   entry to shared mechanism instead of every product's features. `/studio` was
   already subpath-only. (Breaking only for a ROOT import of those symbols —
   switch to the subpath, which is the documented convention.)

2. Dogfood — agent-app now generates its docs with `@tangle-network/agent-docs`
   instead of the bespoke `scripts/gen-codemap.mjs` (deleted). `docs:gen` →
   `agent-docs`; the freshness gate runs `agent-docs --check`; docs/ now also
   carries `llms.txt` + `llms-full.txt` + `codemap.json` (the agent-readable
   surface). Deletes the first fleet copy of the generator.

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved drewstone PR — 10bdc01c

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-24T20:04:43Z

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 2 (2 weak-concern)
Heuristic 0.1s
Duplication 0.0s
Interrogation 157.3s (2 bridge agents)
Total 157.4s

💰 Value — sound-with-nits

Documentation overhaul — 978 additive JSDoc summaries, root barrel trimmed of two app-specific feature surfaces, and the bespoke gen-codemap.mjs replaced by the shared @tangle-network/agent-docs tool; coherent and in-grain.

  • What it does: Three changes: (1) adds 978 one-line JSDoc summaries above previously-undocumented exports across 168 source files, raising documented-export coverage from 47% to 95%; (2) removes /sequences and /design-canvas from the root barrel in src/index.ts (they remain valid subpaths via tsup.config.ts + package.json exports); (3) deletes scripts/gen-codemap.mjs (282 LOC) and replaces it with the @Tangl
  • Goals it achieves: (1) Make the public surface legible — IDE hovers and generated reference docs now cover 95% of exports instead of 47%. (2) Keep the root barrel to shared shell mechanism, not product-specific feature surfaces — a consumer importing @tangle-network/agent-app no longer pays for timeline/canvas symbols it may not want. (3) Kill the first bespoke fleet copy of a codemap generator by dogfooding the c
  • Assessment: All three parts are coherent and in the grain of the codebase. The JSDoc additions are purely additive comments (verified in src/chat-routes/wire.ts and src/tools/types.ts) — zero behavior risk, typecheck stays green. The barrel trim is well-justified: ARCHITECTURE.md:19-22,100-101 classifies sequences and design-canvas as L2/L3 app-specific feature surfaces (timeline editor, canvas editor), expli
  • Better / existing approach: Searched for any pre-existing JSDoc/codemap tool in the repo (find for *.mjs, grep for 'agent-docs', 'codemap', 'gen-codemap'). The only existing generator is the one being deleted — there is nothing else to extend. The @tangle-network/agent-docs devDep is the canonical fleet tool, so adopting it is the right move rather than reinventing. None — this is the right approach.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 2
  • Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content

🎯 Usefulness — sound-with-nits

A coherent docs+barrel-hygiene change that trims genuinely app-specific surfaces from the root barrel (verified safe), dogfoods the shared agent-docs tool (removing a bespoke fleet copy), and adds ~978 additive JSDoc summaries — all wired into package.json scripts and a real freshness gate.

  • Integration: All three parts are reachable and used: docs:gen→agent-docs (package.json:410), devDep pinned (package.json:416), freshness gate spawns agent-docs --check (tests/codemap-fresh.test.ts:24), trimmed subpaths remain importable + documented (docs/codemap.json ./sequences, ./design-canvas entries). No internal caller imported the trimmed symbols from root (greps of src/ + tests/ for root-barrel imports
  • Fit with existing patterns: Matches the repo's stated grain precisely: AGENTS.md's module map and the engine/shell rule treat /sequences and /design-canvas as app-specific feature surfaces (timeline editing, design canvas), not shell mechanism — demoting them keeps the root entry to shared mechanism. Dogfooding agent-docs is the literal 'extend, never duplicate' rule (deletes the first bespoke fleet generator).
  • Real-world viability: Holds up: additive comments can't break behavior; the barrel trim is a narrow, documented breaking change only for external ROOT importers (0.x package, migration is one subpath swap); the freshness gate is a real subprocess diff check, not a stub. Sole fragility is the hardcoded node_modules/dist/cli.js path in the gate test.
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 Freshness gate hardcodes the tool's dist path [robustness] ``

tests/codemap-fresh.test.ts:18 resolves the CLI via join(repoRoot,'node_modules','@tangle-network','agent-docs','dist','cli.js'). This breaks if agent-docs changes its dist layout. The exact 0.2.0 pin prevents silent drift today, but resolving via the package's declared bin entry (or importing its programmatic API) would be more robust. Note only — not blocking.

💰 Value Audit

🟡 Generated codemap.json still lists trimmed subpaths as root dependsOn [maintenance] ``

After this PR, src/index.ts no longer re-exports sequences or design-canvas, and docs/CODEMAP.md correctly drops the root export count from 982 to 766. However docs/codemap.json still lists sequences, sequences-react, design-canvas, design-canvas-react in the root entry's dependsOn array (verified: grep -A 60 '"id": "."' docs/codemap.json). This appears to be how @tangle-network/agent-docs computes dependsOn (from tsup.config.ts entry siblings, not from actual src/index.ts reachability


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260724T200911Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — 10bdc01c

Review health 100/100 · Reviewer score 44/100 · Confidence 95/100 · 17 findings (17 low)

glm: Correctness 44 · Security 44 · Testing 44 · Architecture 44

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 8/8 planned shots over 249 changed files. Global verifier still owns final merge decision.

🟡 LOW No migration note in docs/api/index.md for the root-export removal — docs/api/index.md

index.md loses ~216 entries (design-canvas, sequences, caption helpers) because src/index.ts stopped re-exporting /sequences and /design-canvas from the root barrel — a breaking change for any consumer importing e.g. applySequenceOperation from '@tangle-network/agent-app'. The src change ships a clear comment telling maintainers why, but the generated docs offer no equivalent migration note telling consumers to switch to @tangle-network/agent-app/sequences. The docs are accurate for the new state; the missing migration callout is a docs-discoverability nit, not a correctness defect. Out-of-scope for this shot's verdict (the actual break is in src/index.ts) but noted here so it isn't lost.

🟡 LOW Auto-generated summaries use awkward leading verb ('Resolve' overused) — docs/api/sandbox.md

Many function summaries start with 'Resolve' even when the function builds, extracts, or encodes (e.g. 'Resolve a sandbox prompt by streaming and aggregating…' for runSandboxPrompt at sandbox.md:486; 'Resolve a SecretStore interface…' for secretStoreFromClient). Cosmetic only — descriptions are semantically correct, just stylistically inconsistent with the verb's plain meaning. No action required for merge; flagged for the agent-docs generator's prompt future-tuning.

🟡 LOW Auto-generated doc comments use repetitive, generic verb stems — src/chat-routes/wire.ts

All 54 added JSDoc summaries across the 13 files cycle through a small set of generic verbs ('Resolve', 'Define', 'Represent', 'Describe', 'Build') regardless of whether the symbol is a type, interface, const, or function — e.g. 'Define the maximum byte size allowed for inline parts in data processing' on a numeric const (wire.ts:202), 'Resolve input as either a text part or a file part of a chat turn' on a union alias (wire.ts). The phrasing reads as machine-generated and several summaries are vaguer than the symbol's existing block comments beneath them (e.g. INLINE_PARTS_MAX_BYTES already has a richer 3-line comment block immediately below at wire.ts:205-210). Impact: none functional — comments are accurate and harmless; this is a style/maintainability observation only. Fix: optional pa

🟡 LOW Most added comments are restatement slop that contradict the file's existing WHY-style convention — src/design-canvas/model.ts

The 83 added comments overwhelmingly restate the next identifier in sentence form, e.g. model.ts:17 /** Define the current version number of the scene schema */ on SCENE_SCHEMA_VERSION; model.ts:172 /** Define all valid kinds of scene elements used in the application */ on SCENE_ELEMENT_KINDS; operations.ts:112 /** Represent a delete page operation with a specified page identifier */ on DeletePageOperation; export-presets.ts:17 /** Define size presets with identifiers, labels, categories, and dimensions for various media types */ on SizePreset (the fields already say exactly that). This directly contradicts the repo's AGENTS.md ('Do not add narrative comments ... that restate the next line of code') AND the files' own pre-existing header docstrings (model.ts:1-13, operation

🟡 LOW Doc comments use wrong verbs on type aliases and interfaces — src/design-canvas/schema.ts

The added comments use verbs that don't match the construct. On type aliases (schema.ts:93 DesignCanvasTables, :96 DesignDocumentRow, :98 DesignDecisionRow, :100 DesignExportRow), the verb 'Resolve' is misleading — a type alias does not resolve anything at runtime; it just names a type. Same pattern in operations.ts:60 /** Resolve an operation to reorder ... */ on the ReorderElementOperation INTERFACE (:69 DeleteElementOperation, :87 UngroupElementOperation, :137 SetPageGuidesOperation) and model.ts:169 /** Extract the type property ... */ on SceneElementKind. Impact: misleads readers about whether these are runtime functions; degrades the otherwise-precise doc style the file establishes. Fix: use 'Type alias for...' / 'Shape of the ... operation' phrasing, or drop th

🟡 LOW Type-declaration comments use function verbs ('Resolve'/'Define') that mislabel types as operations — src/sandbox/binary-read.ts

'Resolve the outcome of a sandbox file size check...' on a type union. A type does not 'resolve' anything. Same pattern at binary-read.ts:37 (SandboxFileBytesOutcome), workspace-terminal.ts SandboxTerminalTokenSubject ('Resolve the identity type...'), and several interfaces in index.ts prefixed with 'Define'. Reads as if a function exists. Cosmetic, but degrades the signal value of the new docs. Prefer 'Represents' or drop the leading verb for type/interface/type-alias comments.

🟡 LOW mergeExtraMcp doc comment is misleading — says it resolves collisions, but it throws — src/sandbox/index.ts

Added comment: 'Resolve conflicts and merge extra MCP profiles into the app tool MCP without overwriting existing keys'. The function (lines 1824-1835) does NOT resolve conflicts and does NOT silently skip — it THROWS extraMcp key '${key}' collides with an existing profile MCP server on any key present in appToolMcp or baseProfileMcp. 'Without overwriting existing keys' implies silent skip; the real contract is fail-loud. This is a public export, so a caller reading the doc will reason incorrectly about error behavior. Fix: 'Merge extra MCP servers into the app-tool map; throws on any key that already exists in appToolMcp or baseProfileMcp.'

🟡 LOW syncSandboxMemberAdd comment uses awkward 'Resolve adding a user' phrasing — src/sandbox/index.ts

Comment reads 'Resolve adding a user with a specific role to a sandbox and return the operation outcome'. 'Resolve adding' is not idiomatic; the function adds a member (box.permissions.add) and wraps the result in Outcome. Prefer 'Add a user with the given workspace role (mapped via seam) to the sandbox; returns ok/fail rather than throwing.' Same family of awkward 'Resolve ' phrasing appears on syncSandboxMemberRemove ('...and handle the outcome') and secretStoreFromClient.

🟡 LOW 'asynchronously' wording on applySequenceOperation implies fire-and-forget — src/sequences/apply.ts

Added comment reads 'Apply a sequence operation to update the store and timeline asynchronously'. The function is async (returns a Promise the caller must await), not asynchronous in the fire-and-forget sense — the existing callers in applySequenceOperations await it sequentially. 'asynchronously' could be read as 'the caller does not need to await', which would be a data-loss footgun. Fix: drop 'asynchronously' or reword to 'awaitable'.

🟡 LOW 'Resolve' misused on type aliases and static literals — factually misleading docs — src/sequences/schema.ts

Several JSDoc summaries use the verb 'Resolve' for declarations that do not resolve anything at runtime: schema.ts:147 /** Resolve sequence tables by invoking the createSequenceTables factory function */ above type SequenceTables = ReturnType<typeof createSequenceTables> (nothing is invoked — it's a static ReturnType derivation); schema.ts:150-155 the SequenceRow/SequenceTrackRow/SequenceClipRow/SequenceDecisionRow/SequenceExportRow Drizzle $inferSelect aliases each described as 'Resolve a ... row'; mcp-tools.ts:368 /** Resolve an array of immutable sequence MCP tool definitions... */ above the static SEQUENCE_MCP_TOOLS = [...] literal; operations.ts:61 /** Resolve an operation to move a clip... */ above the MoveClipOperation interface. A reader will hunt for a reso

🟡 LOW JSDoc comments restate the declaration directly below, violating repo comment doctrine — src/sequences/store.ts

AGENTS.md is explicit: 'Do not add narrative comments... that restate the next line of code. Comments should explain non-obvious technical decisions, invariants, constraints, or risk boundaries.' The bulk of this shot's 85 added lines are pure restatements, e.g. /** Define properties for a new sequence track including kind, name, and optional sort order */ directly above interface NewSequenceTrack { kind; name; sortOrder? } (store.ts:27), /** Define the start frame and duration in frames for a timeline clip's bounds */ above TimelineClipBounds { startFrame; durationFrames } (model.ts:170), /** Convert seconds to the nearest whole number of frames based on frames per second */ above secondsToFrames(seconds, fps) (model.ts:140). Pattern repeats across captions.ts, drizzle-store.t

🟡 LOW New JSDoc comments misdescribe TS constructs and restate code, violating repo comment doctrine — src/teams/roles.ts

Across the shot, type aliases are documented as 'Resolve the union type...' (roles.ts:19, 24, 29; schema.ts:92, 95, 97), interfaces as 'Resolve sending an invitation email and return the result asynchronously' (invitations-api.ts:58 on SendInvitationEmailSeam — an interface is a contract, it neither resolves nor returns), and creator functions as 'Resolve organization access API...' (access.ts:189 on createOrganizationAccess — the function CREATES, the existing sibling createWorkspaceAccess at access.ts:65 is correctly commented 'Create workspace access API'). A type alias does not 'resolve'; it declares a name. These read as auto-generated and are actively wrong about what the construct does. Separately, most comments restate the next line verbatim: `/** Define the number of days before a

🟡 LOW Auto-generated JSDoc enumerates a partial field list, inviting staleness — src/tools/mcp.ts

Comment lists 'tool, baseUrl, token, and context' but the interface (lines 135-145) also has description, headerNames?, paths?. Same pattern in BuildHttpMcpServerOptions (mcp.ts:27), DispatchOptions (dispatch.ts:12), CreateMcpToolHandlerOptions (mcp-rpc.ts:43). Partial enumeration in prose will drift silently when fields are added. Prefer describing the interface's purpose without naming fields, or keep the list in sync. Cosmetic only.

🟡 LOW Comment style conflicts with repo's 'no narrative comments' rule — src/tools/openai.ts

Added comments like 'Resolve a valid application tool name from the predefined list of tool names' (openai.ts:6), 'Determine if a string matches a valid application tool name' (openai.ts:12), and the 'Define ...' / 'Describe ...' / 'Represent ...' pattern across all 10 files restate the symbol name verbatim. AGENTS.md states comments should 'explain non-obvious technical decisions, invariants, constraints, or risk boundaries' and not restate the next line. Acceptable as a one-off docs-coverage sweep, but flagging so the convention isn't taken as precedent for hand-written comments elsewhere. No functional impact.

🟡 LOW JSDoc on SubmitProposalArgs mislabels regulated as caller-supplied 'approval status' — src/tools/types.ts

New comment reads 'Define the arguments required to submit a proposal including type, title, description, and approval status'. The inline doc on the regulated? field at line 63-65 explicitly states it is 'Stamped by dispatch from the approval policy... Products don't set this; dispatch owns it — fail-closed.' Calling it an 'argument required to submit a proposal' / 'approval status' contradicts the existing invariant and could mislead a reader into setting regulated from tool args (which dispatch owns). Suggest rewording to omit 'approval status' or note regulated is dispatch-stamped, e.g. 'Arguments for submit_proposal; regulated is stamped by dispatch, not supp

🟡 LOW Several new JSDoc comments restate the identifier rather than explain non-obvious semantics — src/web-react/chat-stream.ts

e.g. /** Define the structure for a chat tool call including optional ID, name, and arguments object */ above interface ChatStreamToolCall { toolCallId?: string; toolName: string; args: Record<string, unknown> } adds no information beyond the field names. Same pattern in durable-plan-flow.ts:4 (DurablePlanDecision), interaction-card-support.ts:199 (InteractionAnswerSubmitterOptions), sandbox-terminal.ts:3 (SandboxTerminalConnection), use-composer-attachments.ts:67 (UseComposerAttachmentsOptions). Repo AGENTS.md is explicit: 'Comments should explain non-obvious technical decisions, invariants, constraints, or risk boundaries' and 'Do not add narrative comments ... that restate the next line of code.' Impact is purely cosmetic — no functional risk. Fix: either drop the tautologic

🟡 LOW Comment verb form is inconsistent across the new docstrings — src/web-react/index.tsx

Lead verbs mix 'Define' / 'Describe' / 'Resolve' / 'Provide' / 'Manage' / 'Handle' / 'Represent' across the 10 files with no discernible rule (interfaces get 'Define' or 'Describe', hooks get 'Manage' or 'Resolve', functions get 'Resolve' or 'Provide'). Purely a style nit; consider standardizing on JSDoc convention (@interface/@typedef tags or a single voice) for tooling that consumes these. No functional impact.


tangletools · 2026-07-24T20:21:48Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 17 non-blocking findings — 10bdc01c

Full multi-shot audit completed 8/8 planned shots over 249 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-24T20:21:48Z · immutable trace

@drewstone
drewstone merged commit 8492ead into main Jul 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants