Repository navigation
E09: slice-to-scenario traceability in planning artifacts - #438
Merged
Merged
Conversation
The engineering record (E01) refuses a slice that proves no scenario. The
artifacts that feed planning -- both reimplementation specs and the project
plan -- had no such structure: scenarios were a numbered table with no
stable handle, scope tiers were prose, and nothing said which scenario
proved which promise. E04 left that seam open ("deriving a plan from an
existing analysis artifact is deliberately NOT implemented"). This closes it.
Templates: scenarios gain a stable Scenario ID and a Tier; a Slices table
carries Slice ID, deliverable, modules, proved scenario ids, dependencies
and tier, in the record's own vocabulary so a plan lifts without
translation. The language-agnostic spec states obligations as what must be
observed, never as a command; the opinionated variant may carry a Proof
command column because its stack is known. Validation rows and pipeline
completion criteria were changed together in all five pipelines that carry
these phases, and both producing SKILLs now instruct the session, including
the rule that an empty proof list is not a plan.
core/engineering/lift.ts reads those tables into the record vocabulary and
refuses on exactly the grounds buildChangePlan refuses: empty proof list,
unknown or self dependency, unknown scenario, an unowned minimum-viable
scenario, duplicate ids, and a row with content but no id (a silently
dropped row would count ownership against a table the author never saw).
Errors are a complete list rather than a first failure; lifting the
repository's own pre-E09 self-audit specs is what showed an early return was
hiding the second missing structure. The lifter imports nothing and sits in
the pure layer.
Tests: seven pipeline invariants (the carrying pipelines are enumerated, not
assumed), nineteen lifter tests including four that hand the same slices to
E04 and assert the two halves agree, the shipped templates lifting clean,
and a compatibility test against a real shipped self-audit artifact. Fifteen
mutations; fourteen bite. The one survivor (loosening the table-separator
regex) is documented untested-by-construction: it is an equivalent mutant on
every observable, and the tight form exists to make the blank-row branch
reachable, not because the loose one misbehaved.
Dogfood: two modules of the v0.25.0 self-audit spec converted by hand, lifted
and planned clean, then each slice inspected for whether its scenarios prove
its promise. Five of eight do; two make universal promises with instance
proofs. The structure catches proof existence, not proof strength -- that
stays with the reviewer, and the dogfood note is the evidence that step is
load-bearing. Running a real phase end to end with a session filling the new
table is recorded as the unfinished half of the issue's step 5.
Scaffold version follows the release marker, not this PR, per the marker's
own policy; existing workspaces receive the standard refresh warning.
Closes #407.
Found while trying to break the agreement claim myself, ahead of review. buildChangePlan does not check id grammar; only the store does. So a scenario id like "S 01" lifted clean, planned clean, and would have been refused three steps later with invalid-local-id, for a reason invisible in the document. The lifter now applies isLocalId to every scenario and slice id and names the grammar in the refusal. A new test proves both directions: five bad ids refused here, and every id the clean fixture uses accepted by validateRecordOfKind. Both grammar checks bite when removed. 1233/1233.
…(E09) Adversarial review (deleg_1ebf14c6) broke both headline claims of the first lifter with live reproductions. Seven real defects; this closes all of them and replaces the reader rather than patching it. Rows the author wrote were dropped silently. The reader ended the table at the first line without a leading pipe, so a GFM-legal row written without one, or a blank line used to group rows, lost that row and every row after it with errors: [] -- the exact outcome the commit message said was prevented. The reader now follows GFM: leading pipe optional, `\|` a literal, blank lines do not end a table, prose between rows is refused as interrupted-table, a row whose cell count differs from the header is refused as ragged-row, the delimiter row is the line after the header and nothing else, fenced code is invisible, and a heading that appears twice is refused rather than picked. "Refuses on exactly the grounds buildChangePlan refuses" was false three ways: a dependency cycle, an empty deliverable, and an empty scenario description all lifted clean and E04 refused them. The agreement tests could not see any of it because the planFromLift helper REPAIRED the lifted values before E04 saw them (`deliverable || id`, `description || "(from artifact)"`, `depends_on: []`). The helper now carries values verbatim, and the lifter walks dependencies the way planning.ts does. A misspelled column suppressed every row-level check. Only the id column gates the row loop now. The "equivalent mutant" claim on the old separator regex was wrong (`| - | | - |` distinguished them); that regex is gone. The shipped templates' blank example rows were themselves refused by E04 for an empty description; they carry parenthesised placeholders now and the SKILLs say to replace them. The E09 invariants also pin the validation rows and completion criteria as the same sentences, word for word, on both sides -- the earlier tests checked each half loosely. Mutation: 25 operators, 24 bite. The survivor (CRLF normalization in the fence pass) is documented equivalent: every consumer is anchored or trimmed, and the CRLF test passes either way. Confirmed sound by the same review and left alone: no author text is used as an object key, no ReDoS at 25KB, the language-agnostic spec carries no proof commands.
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.
feat: slice-to-scenario traceability in planning artifacts (E09)
The engineering record (E01) refuses a slice that proves no scenario. The
artifacts that feed planning -- both reimplementation specs and the project
plan -- had no such structure: scenarios were a numbered table with no
stable handle, scope tiers were prose, and nothing said which scenario
proved which promise. E04 left that seam open ("deriving a plan from an
existing analysis artifact is deliberately NOT implemented"). This closes it.
Templates: scenarios gain a stable Scenario ID and a Tier; a Slices table
carries Slice ID, deliverable, modules, proved scenario ids, dependencies
and tier, in the record's own vocabulary so a plan lifts without
translation. The language-agnostic spec states obligations as what must be
observed, never as a command; the opinionated variant may carry a Proof
command column because its stack is known. Validation rows and pipeline
completion criteria were changed together in all five pipelines that carry
these phases, and both producing SKILLs now instruct the session, including
the rule that an empty proof list is not a plan.
core/engineering/lift.ts reads those tables into the record vocabulary and
refuses on exactly the grounds buildChangePlan refuses: empty proof list,
unknown or self dependency, unknown scenario, an unowned minimum-viable
scenario, duplicate ids, and a row with content but no id (a silently
dropped row would count ownership against a table the author never saw).
Errors are a complete list rather than a first failure; lifting the
repository's own pre-E09 self-audit specs is what showed an early return was
hiding the second missing structure. The lifter imports nothing and sits in
the pure layer.
Tests: seven pipeline invariants (the carrying pipelines are enumerated, not
assumed), nineteen lifter tests including four that hand the same slices to
E04 and assert the two halves agree, the shipped templates lifting clean,
and a compatibility test against a real shipped self-audit artifact. Fifteen
mutations; fourteen bite. The one survivor (loosening the table-separator
regex) is documented untested-by-construction: it is an equivalent mutant on
every observable, and the tight form exists to make the blank-row branch
reachable, not because the loose one misbehaved.
Dogfood: two modules of the v0.25.0 self-audit spec converted by hand, lifted
and planned clean, then each slice inspected for whether its scenarios prove
its promise. Five of eight do; two make universal promises with instance
proofs. The structure catches proof existence, not proof strength -- that
stays with the reviewer, and the dogfood note is the evidence that step is
load-bearing. Running a real phase end to end with a session filling the new
table is recorded as the unfinished half of the issue's step 5.
Scaffold version follows the release marker, not this PR, per the marker's
own policy; existing workspaces receive the standard refresh warning.
Closes #407.