Repository navigation
S2.3 — Execution skills - #313
Draft
dev-pmallapp wants to merge 22 commits into
Draft
dev-pmallapp wants to merge 22 commits into
dev-pmallapp wants to merge 22 commits into
Conversation
… as written Writes docs/design/stories/47.md: ten-section spine, twelve claims, ten build targets, six decisions and four open gate questions. The issue seeds SIX claims, not five. No prior summary of this Story has counted CLAIM-47.6. Measured at d59a958, verdicts: - CLAIM-47.1 UNIMPLEMENTABLE. binding.unitOfWork is UnitSpec -- one object of five prose strings, validated with isPlainObject, declared singular. There is no item to iterate. Four sources name the Design's ## Build Targets table as the real enumeration, including the issue body eleven lines below the claim that contradicts it. - CLAIM-47.2 UNIMPLEMENTABLE. Zero cycle-detection code exists anywhere, and Blocked by: is emit-only with no parser -- though the sibling Parent: line has both. The plural "lines" contradicts NEVER-21.7 and Decision 8 of stories/21.md. Only the ordering clause is real, and it is already enforced by a comment that named this claim two milestones early. - CLAIM-47.3 PARTIALLY SUPPORTED, and widened. The default-branch refusal shipped in S1.3 citing M2.md:126-128 by line -- the first seeded clause in M2 built before its Story existed. But "cut from the story branch" forbids the stacking shape branch-and-pr-model.md:15 mandates. - CLAIM-47.4 inherits CLAIM-41.8's restatement per stories/41.md:564-565. - CLAIM-47.5 PARTIALLY SUPPORTED. evidence/template.ts refuses {n} at construction and its runtime error names M2.md:132 -- this claim's first line -- as defective. S1.4 predicted this Story's defect two milestones in advance and left the message as the warning. - CLAIM-47.6 PARTIALLY SUPPORTED. Doctrine exists; no reader does. An unrecorded live defect, found by implementing: planSubIssueAttach passes the checklist as the whole --body, replacing the parent Story's entire body. No withTasksChecklist merger exists though withParentLine is the exact analogue one file over. The test asserts four argv elements and never checks the body survives -- a passing test that is wrong, which mutation testing cannot find because there is no logic to delete. Finding 18 is DISCHARGED: #287 raised the budget to 3 baseline free plus 5 discretionary. story-design sits exactly at 5. "iAI never merges" is at CONTRIBUTING.md:416 -- the fifth distinct number. Two stale citations are live in tracked files, one of them a Reconciliation row announcing it had corrected that very citation. #293's Design is cited by issue number, never by path: the two Stories are independent and may merge in either order. Citing it by path made this file fail path-dangling on main and cascaded to 11 test failures. Finding 38's precedent -- de-path the name in the prose. Chain re-derived on main + this file: 903 tests / 889 pass / 0 fail / 14 skip / 3170 expect() at 5884a40 plus this commit, lint 0 across 95 files, typecheck clean, skill-lint 0 errors, claim-lint 113 files 0 errors 1 warning (the expected 9.md one). design-spine scans 11 Designs / 114 sections. Refs #47
Ruled by the repository owner on 2026-09-07. iAI did not author the decision and did not choose between the shapes (docs/design/03-workflow.md:271); this commit relays it with attribution. | G1 | restate CLAIM-47.1 to the Design's ## Build Targets table | YES | | G2 | drop the plural Blocked by: lines; cycles out of scope with an owner | YES to both | | G3 | close the task issue at verify time, not after merge | VERIFY TIME | | G4 | git/argv layer shared with #293's adapter port | SHARED | G3 was the one question measurement could not settle, and it was ruled deliberately rather than by default. The cost is accepted and stated: a task issue closes while its PR is still unmerged, because a human merges and task-verify cannot wait on a human and still complete its own claim. G3 GENERATED WORK THIS DESIGN DID NOT HAVE A ROW FOR. gh-operations.md:56 and branch-and-pr-model.md:53 both say "close after merge, citing the merge commit". The ruling contradicts both, so both must be restated. Added as Build Target 11 -- the sixth consecutive Story to under-count enforcement, and the first where a GATE RULING generated the uncounted work rather than the milestone's indicative table. Worth naming as a new instance of the pattern: a ruling is an edit to the repository, not only to the Design. CLAIM-47.5 now states the ruled closure timing. Decision 5 is retitled -- the contradiction no longer "goes to" the gate, it was answered there. Chain unchanged: 903 tests / 889 pass / 0 fail / 14 skip / 3170 expect(), lint 0 across 95 files, typecheck clean, skill-lint 0 errors, claim-lint 113 files 0 errors 1 warning (the expected 9.md one). Refs #47
Writes docs/test-plans/47-plan.md against the RULED Design at 8039d53. 20 cases / 18 P0 / 2 P1 / 0 P2, in seven tables. Coverage verified in BOTH directions: 12 claims defined, 12 anchored, 0 uncovered, 0 dangling. Corpus: 11 real / 8 synthetic / 1 none. The real majority is possible because this Story's subject already exists on disk -- eleven Designs to parse, twelve references, seven skill bodies, and an argv layer whose refusals shipped two milestones early. Five cases carry the weight: - Case 1 parses ## Build Targets over every Design on disk. CLAIM-47.1 was a TYPE ERROR, not a phrasing problem: binding.unitOfWork is a UnitSpec, five readonly string fields, declared singular. - Case 2 asserts the Story body SURVIVES the checklist merge. At HEAD it does not. Case 12 is its mutation, and it KILLS NOTHING until Build Target 1 lands -- there is no body-preservation logic to delete. Recorded as a forward-dated kill with the pre-landing run stated as a measured gap, per the S2.1 taxonomy, never as a pass. Amendment 1 records it. - Case 5 asserts {n} is refused AND that the message still names it. evidence/template.ts aimed that warning two milestones forward at whoever implemented CLAIM-47.5; a generic error would decay it to nothing. - Case 10 asserts the label transition emits exactly one command in all three branches, including ZERO on a no-op. Second occurrence of a defect labels.ts:16-26 already restated for CLAIM-21.3, in that file's own comment. - Case 14 is the #307 partition at SEVEN. The three new verbs must each be classified deliberately or the equality fails -- by design. Case 20 covers Build Target 11, which gate ruling G3 GENERATED: both references still say "close after merge, citing the merge commit" and the ruling contradicts them. Case 13 records the trap that will bite the author: `## iai-evidence` written literally is an instant duplicate-contract error, because it contains SENTINEL_NAMESPACE_PREFIX. CLAIM-47.5 quotes it; the body may not. Denominators: testplan-corpus 9 -> 10 plans, 49 -> 56 case tables, 220 -> 240 cases. claim-lint 113 -> 114 files, 0 errors, 1 warning (the expected 9.md). expect() UNCHANGED at 3170, confirming the +0 prediction for a plan a second time. #293 is cited by issue number, never by path -- the two Stories are independent and may merge in either order. Refs #47
This was referenced Sep 12, 2026
The Story body was replaced by the checklist, not merged with it: planSubIssueAttach passed tasksChecklist's output as the whole --body of a gh issue edit on the parent. The shipped test asserted the first four argv elements and that the last contained the heading, both of which are true of a body that had destroyed everything else. withTasksChecklist(body, items) is the merger, modelled on withParentLine: it rewrites the ## Tasks section in place, preserves everything around it, inherits a tick the caller is silent about, and refuses a body carrying two ## Tasks sections rather than guessing which one is the checklist. parentBody is required on both paths and has no default, because a default of "" would make the destructive behaviour the fallback for a caller who simply forgot. The checklist edit is now emitted on the GraphQL path too, where CLAIM-47.1's clause was previously unreachable. Refs #315, #47
…t it Mutation M11 survived the first round: widening the section boundary to H3 changed no assertion. Chasing it down found that every real Story body puts load-bearing prose INSIDE ## Tasks, after the entries — #47's dependency ordering and its "must not be built twice" ruling, #293's sequencing rulings — and that on #293 the section runs to the end of the body, so a section-wide rewrite deletes all of it with no following heading to stop it. The merger rewrote the whole section. That is the defect this task exists to remove, reproduced one level down inside the fix for it. The rewrite now covers the leading run of entry lines and nothing else, and the structure is asserted rather than assumed: entries split by prose are refused with the line named, because taking "the first contiguous run" on trust is how #323's audit parser read the right rows by accident. Refs #315, #47
dev-pmallapp
force-pushed
the
story/47-s2-3-execution-skills
branch
from
September 20, 2026 11:40
b63258c to
a6ce084
Compare
S2.3.5 — `withTasksChecklist` merger, and the checklist on both capability paths
The block at docs/design/02-roles.md:276-282 had five copies in the tree — four prose bodies and a private hardFailure() in risk-mandate.ts — and a rule too loose to police any of them: /(?:- .+\n?)+/ accepts any bullets in any order, which is why the subject-line divergence went unnoticed. packages/core/src/guards/hard-failure.ts holds the spec once. A TypeScript renderer produces conformant blocks; skill-lint's new hard-failure-block rule validates prose against the same exported constants. One contract, two enforcement directions. risk-mandate.ts's private copy is deleted and rewired. Its test is UNTOUCHED and still green — it pins the output string verbatim, so it is the regression guard that the swap is behaviour-preserving. The subject line is an open slot keyed Milestone/Story/Goal per gate ruling G-a on #47: the fixed '- Story: #{story}' was unsatisfiable for goal-create, which runs before any Story exists. All four shipped bodies pass the new rule unchanged. Refs #316, #47
…rule fires checkEvidenceMandate is the reader the doctrine at references/evidence-artifacts.md:140-144 never had. It RESOLVES NOTHING: it takes an already-determined resolution and decides what to do about it, and a static assertion pins that its own source imports no fs and no path. That seam is what makes the task shippable. Build target 4's resolver cannot be built as specified (#341): 21 of 54 artifacts carry no Claims row and the other 33 use five incompatible notations, over an immutable corpus. Only one direction is sound — a claim id in ZERO artifacts is certainly uncovered — and a refusal needs only that one. Case 8 is recorded PARTIALLY discharged per gate ruling G-b, carrying the positive direction to BT4. The negative fixtures each assert TWO things: the old loose regex ACCEPTED the malformation, and the new rule rejects it. Without the first, they would only show that some rule fires on some garbage; with it, each one names a defect that would have shipped green — a missing Action-line prefix, a subject key outside the vocabulary, transposed Expected/Found. docs/design/02-roles.md's template restated per G-a: the subject is an open slot keyed Milestone/Story/Goal, and {remedy} is the trailing imperative only. Refs #316, #47, #341
Mutation M5 deleted the Action line's invariant-prefix check entirely --
startsWith(HARD_FAILURE_ACTION_PREFIX) became startsWith("- Action:") --
and the suite stayed green. The negative fixture meant to pin that check
still failed the mutant, but by accident: its Action line is SHORTER than
the 36-character prefix, so the surviving .slice(PREFIX.length) ran off the
end and yielded "", which the blank-remainder branch rejected regardless.
A length accident was standing in for a content comparison.
The added fixture miscases one word and keeps the line long enough that the
slice yields a non-blank remainder either way, so the only thing that can
reject it is a real comparison against the invariant. It is asserted to be
longer than the prefix, and its remainder asserted non-blank, so the
accident cannot come back silently.
Round: 12 mutations, 12 killed -- 11 on the first pass, M5 after this fix.
Refs #316
Verdict PASS. 963 tests / 949 pass / 0 fail / 14 skip, measured at the parent commit b0616b9; the +2 expect() and +1 claim-lint file this artifact itself adds are stated rather than measured, per #299, and both predictions were confirmed after it landed. 12 mutations, 12 killed. M5 is the round's return: it deleted the Action line's invariant check and the suite stayed green, because the fixture pinning that check was shorter than the prefix and was being rejected by a length accident instead of a content comparison. Case 8 is PARTIALLY discharged per gate ruling G-b, carrying the positive direction to build target 4 and #341. Refs #316
…-emitter S2.3.6 — The hard-failure block emitter
…rulings
BT4's row said 'map a task's anchored CLAIM-{story}.{n} to a Design claim
and to an artifact on disk'. The second half cannot be built: 21 of 54
artifacts carry no Claims row, the other 33 use five incompatible
notations, and docs/evidence/ is immutable, so neither gap can ever close.
Restated to what is buildable — reconstruct the EXPECTED artifact from the
Design and test plan, then check for its existence. It never parses
docs/evidence/ to discover what a claim covers.
That inversion is the point, not a detail. Reading coverage out of the
artifacts means a heterogeneous corpus yields confident wrong answers.
Reconstructing the expectation and checking for it means an unexpected
corpus yields a miss, which is a refusal, which is the safe direction for
CLAIM-47.6.
Also records G-a, G-b and G-c in a second Gate section, with the trigger:
#316's issue body was false in two of three clauses, and resolving each
against the tree before believing it is what surfaced G-a.
Refs #341, #47, #316
…ment #341 — Build target 4 resolves from the Design side, not from the artifacts
…e seam job S2.6 landed on main at dab09cc. story/47 was 39 commits behind and, more importantly, had no packages/exec — which is the port gate ruling G4 binds #49 task-do to. #49 could not have been built on this branch without it, and the alternative is the second git layer G4 and G3 both forbid. It also brings packages/harness and the seam CI job, so this branch's PRs now report 8 checks rather than 7. That is the second precondition #334 needs before seam can be promoted to a required context.
Build target 3. CLAIM-47.1's real input is the Design's ## Build Targets table, not binding.unitOfWork — the seeded wording is a type error, since UnitSpec is five readonly string fields declared singular and validated with isPlainObject. Restated at the gate as G1. THE COLUMN IS FOUND BY NAME. Measured over the 12 Designs on disk, the table ships in three header shapes; 41.md, 293.md and 47.md lead with a # column, putting Target in position 2. A positional reader returns '1', '2', '3' for a third of the corpus — row numbers plausible enough to survive review. The test asserts both shapes are really present, or the by-name lookup would be untested in practice. The parser refuses rather than copes: missing section, renamed column, ragged row, absent separator, header with no rows. #323's M5 is the precedent — a parser that tolerates the structure it depends on cannot report a violation of it. Blocked by: was already rendered inside renderPrBody. CLAIM-47.2 puts the same directive on task issue bodies, so the FORM is extracted to gh/blocked-by.ts on first reuse rather than on the third. pr.ts's tests are untouched and green — the regression guard that the move is behaviour-preserving — and a new test asserts both consumers emit the same line rather than merely similar ones. Refs #48, #47
…ut to cost Build target 8a. The body passes all 18 skill-lint rules first time and cites 4 discretionary references, inside the cap of 5. THE REST OF THIS COMMIT IS THE POINT OF #344. Adding one SKILL.md turned 20 tests red across the harness: PINNED_SKILL_COUNT in two places, two hardcoded 4s in transcription-gap, case 6's threshold, the DOMAIN_RESOLVING_SKILLS partition, the scenario roster's uncovered-skills assertion, two roster-length pins, case 8's identity-key mapping, and the transcription audit's denominator. None of it is named by S2.3's Design or by #48, because #293 owned the harness and this Story was told not to pre-empt it — a deferral that expired when #293 closed. The transcription is written but NOT claimed faithful. It and the body come from the same task, so a faithfulness verdict here is self-attestation, which is exactly what #322 declined to do. Its five audit rows are recorded UNAUDITED and the independent audit is tracked by #344. Case 8's ROW_CLASS keys on the verbatim cell text and caught a real drift: the map said 'Does the Story already carry' where the body says 'Does the Story body already carry'. A looser key would have classified the wrong row and stayed green. Refs #48, #47, #344
M3 — the H2 section bound was never the binding one: in every fixture the leading-contiguous-run scan stopped at the same place. The two diverge only where a Build Targets section carries NO table and a later section does, and there the unbounded parser returns another section's table as the build targets. Confident, wrong, plausible. Now pinned. M5 — the rows.length === 0 guard was unreachable: table.length < 3 already rejects a header and separator with nothing after. Removed, with a note, rather than left as a comment that reads like a check. M8 and M11 — both in the transcription, both surviving the full suite AND a green skill-harness, because the roster scenario always supplies the domain label and never asserts the seeded body survives. M11 IS THE ONE THAT MATTERS: it reproduces, inside this transcription, the exact defect #315 existed to fix — building the ## Tasks section and sending it as the whole body. Against the roster's one-line seed nothing observable changed, which is how the original shipped. The new test uses a body carrying a ruling INSIDE ## Tasks, which is what every real Story has. The harness proves the transcription is idempotent. It does not prove it is correct, and those are different claims. Round: 11 mutations, 7 killed on the first pass, 4 chased down. Refs #48
Three of the five Done-when bullets were not satisfied against the tree. Bullet 5 asked for a `## Re-entry` table whose every mutating step is preceded by its read. Parenting is a mutating step and its path is chosen by `subIssueCapabilityProbe` -- a read that appeared nowhere in the body. The probe is now Phase 0 item 6 and Re-entry row 3, the transcription reads it before the create loop, and the fake forge MODELS it rather than answering `unmodelled`: that exit code is documented as "a gap in the double, never a forge refusal" and reading it as "absent" would be exactly the silent-permanent-fallback failure sub-issues.ts:15-27 names. The fake honours the feature header too, so the hazard is tested, not just stated. Bullet 3 asked that the checklist MERGE. The transcription skipped: once `## Tasks` existed it wrote nothing, under a comment claiming "MERGED" and crediting #315's merger it never called. On the re-run the body itself names -- "after a gate ruling adds a row" -- the new task opened and its checklist entry never arrived, on every subsequent run. Both paths now go through `withTasksChecklist`, guarded so a no-op merge issues no write. Bullet 2's body promised that an invented claim anchor "fails claim-lint". It cannot: `anchor-dangling` is scoped to `anchors_to` cells in docs/test-plans/*.md and claim-lint never reads an issue body. The bullet now says model-judged, and says where the anchor IS checked. Also: the row-1 gate was a substring check that 47.md's own prose would have passed; it is the parser's verdict now. Eight mutations run, four survived -- the parser gate, the absent-capability branch, the header hazard and the graphql classifier were all unpinned -- and eight tests close them. 47.md's "11 of 11 Designs" was stale at 12. Refs #47
S2.3.1 — `task-create`
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.
S2.3 — the three execution verbs (
task-create,task-do,task-verify). Design only so far; the gate is open and blocking.docs/design/stories/47.md: ten-section spine, twelve claims, ten build targets, six decisions, four open gate questions.Do not merge, and do not write skill bodies, until the gate is ruled
Four questions on the
## iai-gatecomment of #47. G1 and G4 are load-bearing.docs/design/03-workflow.md:271— an agent may never author a decision.The Story seeds SIX claims, not five
CLAIM-47.6is in the issue body and atdocs/milestones/M2.md:136-137. No prior summary has counted it.Verdicts
CLAIM-47.1binding.unitOfWorkis not a listCLAIM-47.2CLAIM-47.3CLAIM-47.4CLAIM-41.8until #293 landsCLAIM-47.5CLAIM-47.6binding.unitOfWorkisUnitSpec— fivereadonly stringfields, declared singular, validated withisPlainObject.for (const item of …)throws. Four sources name the Design's## Build Targetstable instead, including the issue body eleven lines below the claim.packages/core/src/evidence/template.ts:16-26says CLAIM-47.5 "will not work as literally written" and its runtime error namesdocs/milestones/M2.md:132— this claim's first line — as defective. S1.4 left that message as a warning two milestones in advance.planSubIssueAttachreplaces the parent Story's whole body with the checklist. Its test passes because it asserts the wrong thing, and mutation testing cannot find it — there is no logic to delete.story-designsits exactly at 5).CONTRIBUTING.md:416— fifth distinct number, with two stale citations live in tracked files.Chain
903 tests / 889 pass / 0 fail / 14 skip / 3170
expect()measured at5884a40plus this branch's commit · lint 0 across 95 files · typecheck clean · skill-lint 0 errors · claim-lint 113 files, 0 errors, 1 warning (the expecteddocs/design/stories/9.mdone).#293's Design is cited by issue number, never by path — the two Stories are independent and may merge in either order.
Refs #47