Skip to content

[GEN-E6] every curated description cites the upstream declaration it states, proven against the pinned tree (PR 2a) - #445

Merged
Blind-Striker merged 1 commit into
masterfrom
docs/gen-e6-pr2a
Oct 17, 2026
Merged

Blind-Striker merged 1 commit into
masterfrom
docs/gen-e6-pr2a

Conversation

@Blind-Striker

@Blind-Striker Blind-Striker commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Every curated descriptions row now cites the upstream declaration it states, and a Tools test proves each citation against the pinned upstream tree. This is how Deniz's D2 evidence rule is enforced.

Part of: GEN-E6 PR 2, split into 2a, this PR: direct rows and the evidence contract, and 2b: rows that need inherited documentation. Plan amendments 11–16.

What changes

  • A required sources list on every row: 1–4 entries, each { "location": "packages/<path>:<line>", "excerpt": "<one verbatim line, 12–200 chars>" }.
    • The validator (DescriptionCurationBinder) checks only the shape: the list's size, a well-formed location, the excerpt bounds, and no location repeated within a row. A missing or null field is refused by name (description sources[index] …, naming the row), not as a JSON error. It never reads the upstream tree, so generate gains no new input (ADR-0013).
    • DescriptionSourceTests proves every entry against the pinned external/opencode. The cited file must exist, and the excerpt must appear within ±5 lines of its location after whitespace is collapsed. A pin refresh that moves or drops a declaration fails closed.
  • The evidence rule: a unit, default, sentinel or format that a row states must appear in its excerpts, taken together. A fact inferred only from implementation goes to the upstream report, which is held internally; filing anything upstream is the maintainer's call.
    • Role rows cite the route groups they describe. A member list in a role summary is checked against the generated client's own sub-clients (amendment 14).
  • Rows:
    • 52 new semantic rows, citing upstream's own declarations: provider timeout units and defaults, epoch-millisecond timestamps, durable-log provenance, configuration defaults.
    • 52 family role rows.
    • 8 rows deferred to 2b, because they reach a destination only through inherited documentation.
  • Canon: one sentence beside the descriptions bullet in protocol-and-generation.md. The CHANGELOG gets a line under Unreleased.
  • Generated output: 69 files, documentation only. Every changed line is a /// line, and the changed members are exactly the curation targets.

The 35 earlier rows

2 kept with sources; 33 moved. A row moved whole when any one of its qualifications was declared nowhere upstream. Narrowing is allowed from 2b on (amendment 16), so these 33 are revisited there under that rule. Each move gives its reason and the implementation path:line where the fact actually lives:

Existing row Disposition Reason (pin 042d0832)
SessionMessageAssistant Moved The Assistant schema declares fields, not the one-message-per-step/failure lifecycle in this summary. Implementation: packages/core/src/session/runner/publish-llm-event.ts:129.
SessionMessageAssistant.Finish Moved FinishReason declares the value set, but running-null and failure normalization are implementation-only. Implementation: packages/core/src/session/message-updater.ts:225,266,277.
SessionMessageAssistant.RawFinish Moved The schema declares an optional string, not its diagnostic/verbatim-copy semantics. Implementation: packages/core/src/session/message-updater.ts:267,278.
SessionMessageAssistant.Error Moved Clearing on restart, retaining partial content and continuation ownership are not declared by the optional error field. Implementation: packages/core/src/session/message-updater.ts:222-241,275-284.
SessionMessageAssistant.Retry Moved The first-retry value 2 and clearing lifecycle are not stated in AssistantRetry or RetryScheduled declarations. Implementation: packages/core/src/session/runner/retry.ts:79-94; packages/core/src/session/message-updater.ts:404-410.
SessionMessageAssistant.Content Moved AssistantContent declares the alternatives, but recording them in stream order is inferred from projection mutations. Implementation: packages/core/src/session/message-updater.ts:289-329.
SessionMessageAssistant.Cost Moved Money.USD declares currency, but computation, per-step scope and completion/failure absence lifecycle are implementation-only. Implementation: packages/core/src/session/runner/step.ts:245-256; packages/core/src/session/message-updater.ts:269,282-284.
SessionMessageAssistant.Tokens Moved The optional usage field does not declare the per-step and completion/failure lifecycle stated here. Implementation: packages/core/src/session/message-updater.ts:270,282-284.
SessionTextDelta Sourced packages/schema/src/session-event.ts:403 — // Stream fragments are live-only; Text.Ended is the replayable full-value boundary.
packages/schema/src/session-event.ts:408 — assistantMessageID: SessionMessage.ID,
packages/schema/src/session-event.ts:409 — ordinal: NonNegativeInt,
packages/schema/src/session-event.ts:410 — delta: Schema.String,
SessionTextDeltaData.Delta Moved The delta declaration does not state batching; batching is implemented by the publisher. Implementation: packages/core/src/session/runner/publish-llm-event.ts:106,177-185.
SessionTextDeltaData.Ordinal Moved NonNegativeInt does not declare a zero-based index or independent text/reasoning numbering. Implementation: packages/core/src/session/runner/publish-llm-event.ts:168-175,238-280.
SessionTextEnded Sourced packages/schema/src/session-event.ts:403 — // Stream fragments are live-only; Text.Ended is the replayable full-value boundary.
packages/schema/src/session-event.ts:415 — export const Ended = Event.durable({
packages/schema/src/session-event.ts:422 — text: Schema.String,
SessionTextEndedData.Text Moved The replayable full-value boundary is declared, but replacing accumulated deltas is projection behavior. Implementation: packages/core/src/session/message-updater.ts:295-303.
SessionTextEndedData.State Moved ProviderState declares an opaque record, not this future-request reuse policy. Implementation: packages/core/src/session/message-updater.ts:300; packages/core/src/session/runner/publish-llm-event.ts:241-249.
SessionPromptRequest Moved The route declares durable admission and scheduling, not the exact return-before-model-run timing. Implementation: packages/core/src/session/session.ts:145-175.
SessionPromptRequest.Id Moved The schema declares the msg_ prefix, and reconcile has a first-admission JSDoc, but ignoring content and cross-kind/session 409 behavior are not declared together. Implementation: packages/core/src/session/inbox.ts:154-166; packages/protocol/src/groups/session.ts:396-407.
SessionPromptRequest.Files Moved PromptInput declares URI attachments; the 20 MiB limit and server-side file-reading policy come from implementation. Implementation: packages/core/src/session/prompt.ts:97-110,157-203.
SessionPromptRequest.Skills Moved Skill attachments are declared, but prepending their text and the unknown-id 400 behavior are inferred from implementation. Implementation: packages/core/src/session/prompt.ts:56-71.
SessionPromptRequest.Delivery Moved The two delivery names are declared, and promotion has JSDoc, but the steer default is implementation-only. Implementation: packages/core/src/session/session.ts:155; packages/core/src/session/inbox.ts:43-46,505-525.
SessionPromptRequest.Resume Moved The route documents unless-resume-is-false scheduling, not the true default and full pending/boundary lifecycle. Implementation: packages/core/src/session/session.ts:174.
SessionCreateRequest Moved The create route declares location and parent linking, not existing-id adoption. Implementation: packages/core/src/session.ts:259-315.
SessionCreateRequest.Id Moved Returning an existing session and ignoring the other members is implementation behavior, not field documentation. Implementation: packages/core/src/session.ts:259-315.
SessionCreateRequest.ParentId Moved The route declares parent location; metadata/permission inheritance and noninheritance of agent/model are not declared together. Implementation: packages/core/src/session.ts:266-293; packages/server/src/handlers/session.ts:137-139.
SessionCreateRequest.Agent Moved The optional agent field does not declare default resolution on every step. Implementation: packages/core/src/session/context.ts:122-129.
SessionCreateRequest.Model Moved The optional model field does not declare per-step default resolution or deferred unavailable-model errors. Implementation: packages/core/src/session/runner/model.ts:75-90.
SessionCreateRequest.Location Moved The route declares parent location but the process-working-directory default is implementation-only. Implementation: packages/server/src/handlers/session.ts:137-139.
SessionCreateRequest.Permissions Moved Session.Info JSDoc declares evaluation order and last-match wins, but the unmatched-asks default is implementation-only. Implementation: packages/core/src/permission.ts:87-96,158-162.
SessionExecutionStarted Moved The durable event declaration does not declare one terminal per busy period, coalescing, or crash absence. Implementation: packages/core/src/session/execution.ts:76-80,115-139.
SessionExecutionSucceeded Moved The event declares a terminal observation, not the pending queued-input qualification. Implementation: packages/core/src/session/execution.ts:118-125; packages/core/src/session/inbox.ts:505-525.
SessionExecutionFailed Moved The event declares Error, but publication after exhausted restart attempts is implementation-only. Implementation: packages/core/src/session/execution/restart.ts:80-90.
SessionExecutionInterrupted Moved The reason set is declared; preservation, resumption and eventual exhausted-restart failure are implementation behavior. Implementation: packages/core/src/session/execution.ts:129-137; packages/core/src/session/execution/restart.ts:78-90.
PtyCreateRequest.Command Moved CreateInput does not document the config/SHELL/platform fallback defaults or PowerShell argument/profile policy. Implementation: packages/core/src/pty.ts:168-169; packages/core/src/shell/select.ts:94-138,171-182.
PtyCreateRequest.Args Moved CreateInput declares an array; raw argument passing, login flag insertion and $0 effects are implementation-only. Implementation: packages/core/src/pty.ts:168-184.
ExperimentalSessionStatsRequest.From Moved The request declaration is NumberFromString; epoch-ms, inclusive lower bound and earliest-message default are not explicitly declared on it. Implementation: packages/core/src/session/stats.ts:87-100,145-146.
ExperimentalSessionStatsRequest.To Moved The request declaration is NumberFromString; epoch-ms, exclusive upper bound and now default are not explicitly declared on it. Implementation: packages/core/src/session/stats.ts:87,145-146.

Review: the evidence was challenged, not trusted

  • All 106 rows and 205 excerpts, after the fix-up, were checked by script against the pinned tree. Every excerpt sits at its exact cited line; none needed the ±5 window.
  • Rows opened semantically: 78 by the coordinator's Claude review. The cross-family review (Sol) did a broad spot-check covering every provider timeout row, the MCP timeouts, the timestamp rows, the configuration defaults and the role pairs.
  • Moves challenged: 44 in total (Claude 28, Sol 16). Each was searched in packages/schema, packages/protocol, packages/core and packages/ai for a declaration that would have supported it. 0 reversed.
    • Two have partial declarations. protocol/src/groups/session.ts:413 gives Resume's "unless resume is false", and schema/src/session.ts:56 gives Permissions' last-match-wins. Each row also carries implementation-only facts.
    • Every §5 "Keep" decision was honoured.
  • Fixed after review:
    • 26 timestamp rows gained schema/src/schema.ts:39 (DateTime.toEpochMillis). That puts the epoch reference, not only the unit, in their excerpts.
    • EventLogSynced.Seq gained event.ts:17 for its durable-log provenance.
    • The Config role summary now covers both of its operations.
    • Malformed source fields are refused by name.
    • A second-entry oracle row was added (below).
    • DescriptionSourceTests moved to Binding/Models for the mirror guard.

Tests

  • Red then green: 11 validator refusals, all with exact full messages:

    • missing, empty or five-entry lists;
    • a repeated location;
    • a bad location;
    • an empty, multi-line, too-short or too-long excerpt;
    • missing or null fields.

    The oracle's three failures run over a synthetic in-test file: file absent, excerpt outside ±5, excerpt absent.

  • Mutation: 13 compiling mutants, all killed. CheckOnlyFirstSource survived on the base and is killed by the second-entry row. SkipNullSourceFields is killed by four rows.

  • Existing-test edits: synthetic description fixtures gained the minimal sources; the two GeneratedDocumentationTests ceilings were lowered to the measured direct set. No assertion was weakened.

Budget (against the merge-base)

  • Hand-written tools: +74 net, against a cap of +80 (amendment 15).
  • Tests: 195 added. The PR's own work is 150 of 170; the review fix-up adds 55 of its own cap of 60, and the spec exempts review fixes.
  • Not counted: tools/curation.json rows and generated output are data.

Local check

At this head, on dev-01, after a root Release build: slopwatch 0 issues; the Release build with 0 warnings; both format passes; verify-clones passing (0 new; tests 5.41%); --help; generate --verify current; the whole Tools.Tests project (guards included) at 2057/0. Bun 1.4.3, off the 1.4.2 pin. CI is the full gate.

Provenance: Generator lane / opencode dispatch harness (openai/gpt-6.1-sol-1m), the first task run under the Sol guide pilot template. Coordinated, reviewed and finished in Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…tion it states, proven against the pinned tree

Every documentation-only descriptions row in tools/curation.json now carries a required
`sources` list: one to four verbatim upstream lines, each with its packages/path:line location.
The curation validator checks their shape (and never reads the upstream tree), and a Tools test
proves each excerpt within five lines of its location in the pinned external/opencode tree, so
a pin refresh that moves or drops a declaration fails closed. A unit, default, sentinel or
format a row states must appear in its excerpts; a fact inferred only from implementation goes
to the upstream report instead.

The 35 earlier rows were audited: 2 keep their text with sources, and 33 whose summaries rested
on implementation behaviour leave the curation. 52 new semantic rows (timeout units and
defaults, epoch-millisecond timestamps, durable-log provenance, configuration defaults) and 52
family role rows reach their destinations directly; rows that need inherited documentation
follow separately. Generated XML documentation changes only on the targeted members.
@Blind-Striker Blind-Striker added this to the 1.0 milestone Oct 17, 2026
@Blind-Striker
Blind-Striker added this pull request to the merge queue Oct 17, 2026
Merged via the queue into master with commit ce59cf5 Oct 17, 2026
12 checks passed
@Blind-Striker
Blind-Striker deleted the docs/gen-e6-pr2a branch October 17, 2026 14:04
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.

1 participant