Repository navigation
[GEN-E6] every curated description cites the upstream declaration it states, proven against the pinned tree (PR 2a) - #445
Merged
Conversation
…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.
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every curated
descriptionsrow 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
sourceslist on every row: 1–4 entries, each{ "location": "packages/<path>:<line>", "excerpt": "<one verbatim line, 12–200 chars>" }.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, sogenerategains no new input (ADR-0013).DescriptionSourceTestsproves every entry against the pinnedexternal/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.protocol-and-generation.md. The CHANGELOG gets a line under Unreleased.///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:linewhere the fact actually lives:042d0832)SessionMessageAssistantpackages/core/src/session/runner/publish-llm-event.ts:129.SessionMessageAssistant.Finishpackages/core/src/session/message-updater.ts:225,266,277.SessionMessageAssistant.RawFinishpackages/core/src/session/message-updater.ts:267,278.SessionMessageAssistant.Errorpackages/core/src/session/message-updater.ts:222-241,275-284.SessionMessageAssistant.Retrypackages/core/src/session/runner/retry.ts:79-94; packages/core/src/session/message-updater.ts:404-410.SessionMessageAssistant.Contentpackages/core/src/session/message-updater.ts:289-329.SessionMessageAssistant.Costpackages/core/src/session/runner/step.ts:245-256; packages/core/src/session/message-updater.ts:269,282-284.SessionMessageAssistant.Tokenspackages/core/src/session/message-updater.ts:270,282-284.SessionTextDeltapackages/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.Deltapackages/core/src/session/runner/publish-llm-event.ts:106,177-185.SessionTextDeltaData.Ordinalpackages/core/src/session/runner/publish-llm-event.ts:168-175,238-280.SessionTextEndedpackages/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.Textpackages/core/src/session/message-updater.ts:295-303.SessionTextEndedData.Statepackages/core/src/session/message-updater.ts:300; packages/core/src/session/runner/publish-llm-event.ts:241-249.SessionPromptRequestpackages/core/src/session/session.ts:145-175.SessionPromptRequest.Idpackages/core/src/session/inbox.ts:154-166; packages/protocol/src/groups/session.ts:396-407.SessionPromptRequest.Filespackages/core/src/session/prompt.ts:97-110,157-203.SessionPromptRequest.Skillspackages/core/src/session/prompt.ts:56-71.SessionPromptRequest.Deliverypackages/core/src/session/session.ts:155; packages/core/src/session/inbox.ts:43-46,505-525.SessionPromptRequest.Resumepackages/core/src/session/session.ts:174.SessionCreateRequestpackages/core/src/session.ts:259-315.SessionCreateRequest.Idpackages/core/src/session.ts:259-315.SessionCreateRequest.ParentIdpackages/core/src/session.ts:266-293; packages/server/src/handlers/session.ts:137-139.SessionCreateRequest.Agentpackages/core/src/session/context.ts:122-129.SessionCreateRequest.Modelpackages/core/src/session/runner/model.ts:75-90.SessionCreateRequest.Locationpackages/server/src/handlers/session.ts:137-139.SessionCreateRequest.Permissionspackages/core/src/permission.ts:87-96,158-162.SessionExecutionStartedpackages/core/src/session/execution.ts:76-80,115-139.SessionExecutionSucceededpackages/core/src/session/execution.ts:118-125; packages/core/src/session/inbox.ts:505-525.SessionExecutionFailedpackages/core/src/session/execution/restart.ts:80-90.SessionExecutionInterruptedpackages/core/src/session/execution.ts:129-137; packages/core/src/session/execution/restart.ts:78-90.PtyCreateRequest.Commandpackages/core/src/pty.ts:168-169; packages/core/src/shell/select.ts:94-138,171-182.PtyCreateRequest.Argspackages/core/src/pty.ts:168-184.ExperimentalSessionStatsRequest.Frompackages/core/src/session/stats.ts:87-100,145-146.ExperimentalSessionStatsRequest.Topackages/core/src/session/stats.ts:87,145-146.Review: the evidence was challenged, not trusted
packages/schema,packages/protocol,packages/coreandpackages/aifor a declaration that would have supported it. 0 reversed.protocol/src/groups/session.ts:413gives Resume's "unless resume is false", andschema/src/session.ts:56gives Permissions' last-match-wins. Each row also carries implementation-only facts.schema/src/schema.ts:39(DateTime.toEpochMillis). That puts the epoch reference, not only the unit, in their excerpts.EventLogSynced.Seqgainedevent.ts:17for its durable-log provenance.DescriptionSourceTestsmoved toBinding/Modelsfor the mirror guard.Tests
Red then green: 11 validator refusals, all with exact full messages:
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.
CheckOnlyFirstSourcesurvived on the base and is killed by the second-entry row.SkipNullSourceFieldsis killed by four rows.Existing-test edits: synthetic description fixtures gained the minimal
sources; the twoGeneratedDocumentationTestsceilings were lowered to the measured direct set. No assertion was weakened.Budget (against the merge-base)
tools/curation.jsonrows 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-clonespassing (0 new; tests 5.41%);--help;generate --verifycurrent; 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.
Need help on this PR? Tag
@codesmith-botwith what you need.