@ikon85/agent-workflow-kit 0.37.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/kit-update/SKILL.md +33 -1
- package/.agents/skills/orchestrate-wave/SKILL.md +5 -5
- package/.agents/skills/setup-workflow/SKILL.md +42 -4
- package/.agents/skills/setup-workflow/board-sync.md +6 -2
- package/.agents/skills/setup-workflow/workflow-advisories.md +34 -0
- package/.agents/skills/setup-workflow/worktree-lifecycle.md +47 -1
- package/.agents/skills/wrapup/SKILL.md +46 -0
- package/.claude/hooks/drift-guard.py +212 -21
- package/.claude/skills/kit-update/SKILL.md +33 -1
- package/.claude/skills/orchestrate-wave/SKILL.md +5 -5
- package/.claude/skills/setup-workflow/SKILL.md +42 -4
- package/.claude/skills/setup-workflow/board-sync.md +6 -2
- package/.claude/skills/setup-workflow/workflow-advisories.md +34 -0
- package/.claude/skills/setup-workflow/worktree-lifecycle.md +47 -1
- package/.claude/skills/wrapup/SKILL.md +46 -0
- package/README.md +73 -0
- package/agent-workflow-kit.package.json +49 -25
- package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +88 -0
- package/docs/agents/workflow-capabilities.json +11 -1
- package/package.json +1 -1
- package/scripts/board_bootstrap.py +367 -0
- package/scripts/kit-update-pr.mjs +20 -7
- package/scripts/kit-update-pr.test.mjs +29 -0
- package/scripts/profile_globs.py +347 -0
- package/scripts/test_board_bootstrap.py +348 -0
- package/scripts/test_drift_guard_diagnostics.py +295 -0
- package/scripts/test_orchestrate_wave_contract.py +9 -0
- package/scripts/test_profile_globs.py +280 -0
- package/scripts/test_skill_setup_workflow_seeds.py +87 -0
- package/scripts/test_worktree_wrapup_contract.py +1592 -3
- package/scripts/workflow-advisories/core.py +29 -4
- package/scripts/worktree-lifecycle/README.md +139 -0
- package/scripts/worktree-lifecycle/capabilities.json +9 -1
- package/scripts/worktree-lifecycle/cleanup.py +22 -51
- package/scripts/worktree-lifecycle/core.py +1206 -5
- package/scripts/worktree-lifecycle/profile.py +38 -3
- package/scripts/worktree-lifecycle/session.py +1857 -0
- package/scripts/worktree-lifecycle/setup.py +15 -0
- package/scripts/wrapup-land.py +461 -14
- package/src/cli.mjs +32 -1
- package/src/commands/update.mjs +30 -21
- package/src/consumer-migrations.json +19 -0
- package/src/lib/bundle.mjs +11 -0
- package/src/lib/consumerMigrations.mjs +161 -0
|
@@ -105,6 +105,52 @@ One call covers: push → PR create/reuse (+ drift markers merged into the body)
|
|
|
105
105
|
|
|
106
106
|
STOP → diagnose in the main conversation, fix, re-run `land` (an already-merged PR resumes at teardown).
|
|
107
107
|
|
|
108
|
+
Before merge, the committed worktree policy only nominates exact landing
|
|
109
|
+
evidence. After merge, cleanup reloads `docs/agents/workflow-capabilities.json`
|
|
110
|
+
from canonical `origin/main`; only the identical merged, attempt-bound scratch
|
|
111
|
+
and generator policy authorizes each evidence path and deletion. A mismatch is
|
|
112
|
+
a hard STOP that preserves every file—never bypass it with the unmerged branch
|
|
113
|
+
profile.
|
|
114
|
+
|
|
115
|
+
Landing provenance has one explicit relinquish route. If the STOP names an
|
|
116
|
+
unfinished or drifted landing attempt and the ambiguous files cannot be restored
|
|
117
|
+
to their frozen identities, run:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python3 scripts/wrapup-land.py land --branch "<branch>" --abandon-unfinished-attempt
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
This archives the started or frozen attempt receipt only. It deletes and claims
|
|
124
|
+
no files, works even when the older creation baseline is missing, and returns
|
|
125
|
+
before push, PR, or merge. The next `land` conservatively protects every current
|
|
126
|
+
matching path; classify or move those blockers first. Do not use relinquish for
|
|
127
|
+
an exact unchanged frozen attempt: a normal retry validates that evidence and
|
|
128
|
+
resumes deterministically.
|
|
129
|
+
|
|
130
|
+
An attempt journaled under the superseded v1 contract is **legacy, not
|
|
131
|
+
corruption**. The STOP says so explicitly and names the same
|
|
132
|
+
`--abandon-unfinished-attempt` archive route; archival stays valid for a v1 and
|
|
133
|
+
a v2 receipt even without a creation baseline or a local main profile, and no
|
|
134
|
+
generated or consumer file is deleted or claimed on that route.
|
|
135
|
+
|
|
136
|
+
If canonical `origin/main` changed its scratch or generator policy *after* the
|
|
137
|
+
attempt started, the PR can merge and cleanup then STOPs with `worktree cleanup
|
|
138
|
+
policy differs from merged canonical origin/main`. That STOP stays fail-closed
|
|
139
|
+
and names its one supported route out:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
python3 scripts/wrapup-land.py land --branch "<branch>" --recover-canonical-cleanup
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
This resumes the teardown of an **already-merged** worktree only. It never reads
|
|
146
|
+
the stale worktree candidate policy: it re-reads the merged canonical policy,
|
|
147
|
+
requires the branch to already be an ancestor of canonical `origin/main`, and
|
|
148
|
+
revalidates each frozen landing identity against that canonical policy before
|
|
149
|
+
the ordinary shared assessment and removal run. Evidence the canonical policy no
|
|
150
|
+
longer names, a changed identity, and any pre-existing or foreign file are hard
|
|
151
|
+
STOPs that delete nothing. Re-running after a successful teardown is a no-op.
|
|
152
|
+
The flag is mutually exclusive with `--abandon-unfinished-attempt`.
|
|
153
|
+
|
|
108
154
|
### 6 · Post-merge (agent)
|
|
109
155
|
- **Sibling propagation:** for each `drift_markers` entry in the land report, append the note to the target issue's `vor_bau` section + re-stamp its `plan_revision`. Log-based markers → **write directly, then show what was written where** (mandatory report — visibility moved from a pre-gate into the report, decision 2026-07-06); fallback candidates the user hasn't confirmed yet → confirm first. Program context widens the target set to unbuilt wave-stubs/leaves and the Program-PRD itself — same append-only mechanism. **Exception:** appends to the Program-PRD or unbuilt wave-stubs do **not** re-stamp `plan_revision` — that stays reserved for structural wave-plan edits via the `to-waves` escalation path; a mere drift note must not stale-block published stubs.
|
|
110
156
|
- **Anchor close:** report says `anchor_complete: true` → `gh issue close <anchor> -c "Wave complete — all slices merged via PR #<pr>."` and verify board status Done. The guard keeps anchors away from every auto-close — this verified close is the only close path; without it the anchor stays silently open after the last slice. **Then re-run the upward propagation**: the land-time `program-sync` ran BEFORE this close, so on a wave-completing slice the Wellenplan still shows 🔄 and the Phasen-Gate stays unchecked — after the board shows Done, run `python3 scripts/board-sync.py program-sync <program-prd#>` once more (the report's `program_sync.program` names it; skip when the report says the parent is not a program). Board auto-rules can lag the close (Close→Done race) — verify Done first, that's what the token reads.
|
package/README.md
CHANGED
|
@@ -425,6 +425,21 @@ Explicit fork with its own identity and update line instead.
|
|
|
425
425
|
|
|
426
426
|
## Upgrade notes
|
|
427
427
|
|
|
428
|
+
### 0.38.0 — explicit landing-artifact policy
|
|
429
|
+
|
|
430
|
+
Existing consumers must run `setup-workflow` once after `kit-update`, review
|
|
431
|
+
the generated `wrapup.landingGeneratedArtifactPatterns` decision in
|
|
432
|
+
`docs/agents/workflow-capabilities.json`, and commit that profile change.
|
|
433
|
+
Until the explicit policy is committed, `wrapup-land` fails closed before
|
|
434
|
+
landing instead of assuming that no generated artifact is eligible for
|
|
435
|
+
session-owned cleanup.
|
|
436
|
+
|
|
437
|
+
You do not have to remember this note. `kit-update` carries a versioned
|
|
438
|
+
registry of required consumer migrations and names any outstanding one in its
|
|
439
|
+
preview and in its terminal report — interactively, under `--yes`, as JSON via
|
|
440
|
+
`update --json`, and in the automated update pull request. It reports the
|
|
441
|
+
decision you still owe; it never writes a cleanup policy for you.
|
|
442
|
+
|
|
428
443
|
### 0.33.0 — capability-gated orchestration
|
|
429
444
|
|
|
430
445
|
`kit-update` reconciles this release for you. These notes matter only if you
|
|
@@ -454,6 +469,64 @@ the old way. Decision record:
|
|
|
454
469
|
|
|
455
470
|
## Release notes
|
|
456
471
|
|
|
472
|
+
### 0.39.0 — self-explaining guards, one glob dialect, a board you can create
|
|
473
|
+
|
|
474
|
+
Nothing in this release requires a consumer action. `kit-update` reconciles it.
|
|
475
|
+
|
|
476
|
+
- **`kit-update` tells you what you still owe.** A versioned registry of
|
|
477
|
+
required consumer migrations is evaluated against your repository and named in
|
|
478
|
+
the preview and in the terminal report — interactively, under `--yes`, as JSON
|
|
479
|
+
via `update --json`, and in the automated update pull request. It reports a
|
|
480
|
+
decision you owe; it never writes a cleanup policy for you.
|
|
481
|
+
- **`setup-workflow` can create the GitHub-Projects board.** When your tracker
|
|
482
|
+
is GitHub and no board exists, setup now *offers* to provision one — Status
|
|
483
|
+
with its stage options plus the workflow fields — and writes the board profile
|
|
484
|
+
from a read-back of what was actually created. It asks first, and a decline
|
|
485
|
+
leaves the previous stub path byte-unchanged.
|
|
486
|
+
- **One repository-relative glob dialect.** Worktree Lifecycle and Workflow
|
|
487
|
+
Advisories now match consumer profile globs through the same matcher, so an
|
|
488
|
+
advisory and a deletion decision can never disagree about which paths a
|
|
489
|
+
pattern selects. A review command classifies your installed patterns and
|
|
490
|
+
reports, with a concrete witness path, any whose match set narrows or widens.
|
|
491
|
+
- **A merged worktree is never stranded.** A landing attempt that started before
|
|
492
|
+
canonical cleanup policy changed now has a supported recovery route, and a
|
|
493
|
+
landing journal written by the previous contract version is classified as
|
|
494
|
+
legacy rather than as corruption — with the exact safe command named in the
|
|
495
|
+
stop. Both routes revalidate frozen evidence against canonical policy and
|
|
496
|
+
delete strictly less than the ordinary path.
|
|
497
|
+
- **Guards say what happened and where.** A drift-blocked handoff now names the
|
|
498
|
+
checkout it evaluated (and says so explicitly when your working directory is a
|
|
499
|
+
sibling worktree of the same repository), a census status reports *what*
|
|
500
|
+
drifted rather than only *that* something did, and a handoff anchored on an
|
|
501
|
+
issue link no longer adopts an issue from a foreign repository.
|
|
502
|
+
|
|
503
|
+
### 0.38.0
|
|
504
|
+
|
|
505
|
+
- added: `docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md`
|
|
506
|
+
- added: `scripts/worktree-lifecycle/session.py`
|
|
507
|
+
- changed: `.agents/skills/orchestrate-wave/SKILL.md`
|
|
508
|
+
- changed: `.agents/skills/setup-workflow/SKILL.md`
|
|
509
|
+
- changed: `.agents/skills/setup-workflow/worktree-lifecycle.md`
|
|
510
|
+
- changed: `.agents/skills/wrapup/SKILL.md`
|
|
511
|
+
- changed: `.claude/skills/orchestrate-wave/SKILL.md`
|
|
512
|
+
- changed: `.claude/skills/setup-workflow/SKILL.md`
|
|
513
|
+
- changed: `.claude/skills/setup-workflow/worktree-lifecycle.md`
|
|
514
|
+
- changed: `.claude/skills/wrapup/SKILL.md`
|
|
515
|
+
- changed: `README.md`
|
|
516
|
+
- changed: `agent-workflow-kit.package.json`
|
|
517
|
+
- changed: `docs/agents/workflow-capabilities.json`
|
|
518
|
+
- changed: `package.json`
|
|
519
|
+
- changed: `scripts/test_orchestrate_wave_contract.py`
|
|
520
|
+
- changed: `scripts/test_worktree_wrapup_contract.py`
|
|
521
|
+
- changed: `scripts/worktree-lifecycle/README.md`
|
|
522
|
+
- changed: `scripts/worktree-lifecycle/capabilities.json`
|
|
523
|
+
- changed: `scripts/worktree-lifecycle/cleanup.py`
|
|
524
|
+
- changed: `scripts/worktree-lifecycle/core.py`
|
|
525
|
+
- changed: `scripts/worktree-lifecycle/profile.py`
|
|
526
|
+
- changed: `scripts/worktree-lifecycle/setup.py`
|
|
527
|
+
- changed: `scripts/wrapup-land.py`
|
|
528
|
+
- changed: `src/lib/bundle.mjs`
|
|
529
|
+
|
|
457
530
|
### 0.37.0
|
|
458
531
|
|
|
459
532
|
- added: `scripts/test_anchor_table.py`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"kitVersion": "0.
|
|
2
|
+
"kitVersion": "0.39.0",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": ".agents/skills/ask-matt/SKILL.md",
|
|
@@ -377,7 +377,7 @@
|
|
|
377
377
|
"ownerSkill": "kit-update",
|
|
378
378
|
"surface": "codex",
|
|
379
379
|
"installRole": "consumer",
|
|
380
|
-
"sha256": "
|
|
380
|
+
"sha256": "15d265be0c2b3b73c32f786644d271fffb4b269cf8e3c624c61296fe838dda9e",
|
|
381
381
|
"mode": 420,
|
|
382
382
|
"origin": "kit"
|
|
383
383
|
},
|
|
@@ -447,7 +447,7 @@
|
|
|
447
447
|
"ownerSkill": "orchestrate-wave",
|
|
448
448
|
"surface": "codex",
|
|
449
449
|
"installRole": "consumer",
|
|
450
|
-
"sha256": "
|
|
450
|
+
"sha256": "02862cd5e7e07a5f06dad89792fcebd0a6c17cf2216a27c7e0f724026fdda53a",
|
|
451
451
|
"mode": 420,
|
|
452
452
|
"origin": "kit"
|
|
453
453
|
},
|
|
@@ -587,7 +587,7 @@
|
|
|
587
587
|
"ownerSkill": "setup-workflow",
|
|
588
588
|
"surface": "codex",
|
|
589
589
|
"installRole": "consumer",
|
|
590
|
-
"sha256": "
|
|
590
|
+
"sha256": "c6855a479c030f93be30f6fb65b36b8ca317251f9627fd3f6f0f994d9a8b64fb",
|
|
591
591
|
"mode": 420,
|
|
592
592
|
"origin": "kit"
|
|
593
593
|
},
|
|
@@ -687,7 +687,7 @@
|
|
|
687
687
|
"ownerSkill": "setup-workflow",
|
|
688
688
|
"surface": "codex",
|
|
689
689
|
"installRole": "consumer",
|
|
690
|
-
"sha256": "
|
|
690
|
+
"sha256": "4ef2a06e17e08f0fc0c5cc09e4414af67a186a73ca7634e8c378aab5b5638274",
|
|
691
691
|
"mode": 420,
|
|
692
692
|
"origin": "kit"
|
|
693
693
|
},
|
|
@@ -737,7 +737,7 @@
|
|
|
737
737
|
"ownerSkill": "setup-workflow",
|
|
738
738
|
"surface": "codex",
|
|
739
739
|
"installRole": "consumer",
|
|
740
|
-
"sha256": "
|
|
740
|
+
"sha256": "6ff4ad3980f0802b3b041e051d86fb4df7a65884c7ded98ff878e2cd584d80f1",
|
|
741
741
|
"mode": 420,
|
|
742
742
|
"origin": "kit"
|
|
743
743
|
},
|
|
@@ -757,7 +757,7 @@
|
|
|
757
757
|
"ownerSkill": "setup-workflow",
|
|
758
758
|
"surface": "codex",
|
|
759
759
|
"installRole": "consumer",
|
|
760
|
-
"sha256": "
|
|
760
|
+
"sha256": "bf68e0a80b212159f6838bc2bcd3e85714a70cceeff55ed019f87246175182e7",
|
|
761
761
|
"mode": 420,
|
|
762
762
|
"origin": "kit"
|
|
763
763
|
},
|
|
@@ -997,7 +997,7 @@
|
|
|
997
997
|
"ownerSkill": "wrapup",
|
|
998
998
|
"surface": "codex",
|
|
999
999
|
"installRole": "consumer",
|
|
1000
|
-
"sha256": "
|
|
1000
|
+
"sha256": "de5d451d23b019498104bd8e0ebcbf3385f37aad822496bdb0c47d7021de8761",
|
|
1001
1001
|
"mode": 420,
|
|
1002
1002
|
"origin": "kit"
|
|
1003
1003
|
},
|
|
@@ -1087,7 +1087,7 @@
|
|
|
1087
1087
|
"path": ".claude/hooks/drift-guard.py",
|
|
1088
1088
|
"kind": "hook",
|
|
1089
1089
|
"installRole": "consumer",
|
|
1090
|
-
"sha256": "
|
|
1090
|
+
"sha256": "1480bd322d988a546ed589a2420796b38bbf0f52300598a1dd9aa9ddbeb3ea1d",
|
|
1091
1091
|
"mode": 493,
|
|
1092
1092
|
"origin": "kit"
|
|
1093
1093
|
},
|
|
@@ -1699,7 +1699,7 @@
|
|
|
1699
1699
|
"ownerSkill": "kit-update",
|
|
1700
1700
|
"surface": "claude",
|
|
1701
1701
|
"installRole": "consumer",
|
|
1702
|
-
"sha256": "
|
|
1702
|
+
"sha256": "15d265be0c2b3b73c32f786644d271fffb4b269cf8e3c624c61296fe838dda9e",
|
|
1703
1703
|
"mode": 420,
|
|
1704
1704
|
"origin": "kit"
|
|
1705
1705
|
},
|
|
@@ -1769,7 +1769,7 @@
|
|
|
1769
1769
|
"ownerSkill": "orchestrate-wave",
|
|
1770
1770
|
"surface": "claude",
|
|
1771
1771
|
"installRole": "consumer",
|
|
1772
|
-
"sha256": "
|
|
1772
|
+
"sha256": "02862cd5e7e07a5f06dad89792fcebd0a6c17cf2216a27c7e0f724026fdda53a",
|
|
1773
1773
|
"mode": 420,
|
|
1774
1774
|
"origin": "kit"
|
|
1775
1775
|
},
|
|
@@ -1929,7 +1929,7 @@
|
|
|
1929
1929
|
"ownerSkill": "setup-workflow",
|
|
1930
1930
|
"surface": "claude",
|
|
1931
1931
|
"installRole": "consumer",
|
|
1932
|
-
"sha256": "
|
|
1932
|
+
"sha256": "c6855a479c030f93be30f6fb65b36b8ca317251f9627fd3f6f0f994d9a8b64fb",
|
|
1933
1933
|
"mode": 420,
|
|
1934
1934
|
"origin": "kit"
|
|
1935
1935
|
},
|
|
@@ -2029,7 +2029,7 @@
|
|
|
2029
2029
|
"ownerSkill": "setup-workflow",
|
|
2030
2030
|
"surface": "claude",
|
|
2031
2031
|
"installRole": "consumer",
|
|
2032
|
-
"sha256": "
|
|
2032
|
+
"sha256": "4ef2a06e17e08f0fc0c5cc09e4414af67a186a73ca7634e8c378aab5b5638274",
|
|
2033
2033
|
"mode": 420,
|
|
2034
2034
|
"origin": "kit"
|
|
2035
2035
|
},
|
|
@@ -2079,7 +2079,7 @@
|
|
|
2079
2079
|
"ownerSkill": "setup-workflow",
|
|
2080
2080
|
"surface": "claude",
|
|
2081
2081
|
"installRole": "consumer",
|
|
2082
|
-
"sha256": "
|
|
2082
|
+
"sha256": "6ff4ad3980f0802b3b041e051d86fb4df7a65884c7ded98ff878e2cd584d80f1",
|
|
2083
2083
|
"mode": 420,
|
|
2084
2084
|
"origin": "kit"
|
|
2085
2085
|
},
|
|
@@ -2099,7 +2099,7 @@
|
|
|
2099
2099
|
"ownerSkill": "setup-workflow",
|
|
2100
2100
|
"surface": "claude",
|
|
2101
2101
|
"installRole": "consumer",
|
|
2102
|
-
"sha256": "
|
|
2102
|
+
"sha256": "bf68e0a80b212159f6838bc2bcd3e85714a70cceeff55ed019f87246175182e7",
|
|
2103
2103
|
"mode": 420,
|
|
2104
2104
|
"origin": "kit"
|
|
2105
2105
|
},
|
|
@@ -2347,7 +2347,7 @@
|
|
|
2347
2347
|
"ownerSkill": "wrapup",
|
|
2348
2348
|
"surface": "claude",
|
|
2349
2349
|
"installRole": "consumer",
|
|
2350
|
-
"sha256": "
|
|
2350
|
+
"sha256": "de5d451d23b019498104bd8e0ebcbf3385f37aad822496bdb0c47d7021de8761",
|
|
2351
2351
|
"mode": 420,
|
|
2352
2352
|
"origin": "kit"
|
|
2353
2353
|
},
|
|
@@ -2431,6 +2431,14 @@
|
|
|
2431
2431
|
"mode": 420,
|
|
2432
2432
|
"origin": "kit"
|
|
2433
2433
|
},
|
|
2434
|
+
{
|
|
2435
|
+
"path": "scripts/board_bootstrap.py",
|
|
2436
|
+
"kind": "script",
|
|
2437
|
+
"installRole": "consumer",
|
|
2438
|
+
"sha256": "52f4bc89fb078bb9a8735481488bc60d2be438c5c8175555195ac84775e40bfb",
|
|
2439
|
+
"mode": 493,
|
|
2440
|
+
"origin": "kit"
|
|
2441
|
+
},
|
|
2434
2442
|
{
|
|
2435
2443
|
"path": "scripts/board_config.py",
|
|
2436
2444
|
"kind": "script",
|
|
@@ -2555,7 +2563,7 @@
|
|
|
2555
2563
|
"path": "scripts/kit-update-pr.mjs",
|
|
2556
2564
|
"kind": "script",
|
|
2557
2565
|
"installRole": "consumer",
|
|
2558
|
-
"sha256": "
|
|
2566
|
+
"sha256": "17084eede8601d7cf7dd9da85f7738d618111797933a362c93627058fbd335d4",
|
|
2559
2567
|
"mode": 493,
|
|
2560
2568
|
"origin": "kit"
|
|
2561
2569
|
},
|
|
@@ -2623,6 +2631,14 @@
|
|
|
2623
2631
|
"mode": 493,
|
|
2624
2632
|
"origin": "kit"
|
|
2625
2633
|
},
|
|
2634
|
+
{
|
|
2635
|
+
"path": "scripts/profile_globs.py",
|
|
2636
|
+
"kind": "script",
|
|
2637
|
+
"installRole": "consumer",
|
|
2638
|
+
"sha256": "dd11f6e2513eb43813242ace8f4ea00e10b0fa33f4e13fd125afa4a654d61eff",
|
|
2639
|
+
"mode": 493,
|
|
2640
|
+
"origin": "kit"
|
|
2641
|
+
},
|
|
2626
2642
|
{
|
|
2627
2643
|
"path": "scripts/program_graph_parse.py",
|
|
2628
2644
|
"kind": "script",
|
|
@@ -2771,7 +2787,7 @@
|
|
|
2771
2787
|
"path": "scripts/workflow-advisories/core.py",
|
|
2772
2788
|
"kind": "script",
|
|
2773
2789
|
"installRole": "consumer",
|
|
2774
|
-
"sha256": "
|
|
2790
|
+
"sha256": "fcc13d24944a9b1534529e62cc1437617e394f6fe3402647c17cee4ea96aade5",
|
|
2775
2791
|
"mode": 420,
|
|
2776
2792
|
"origin": "kit"
|
|
2777
2793
|
},
|
|
@@ -2779,7 +2795,7 @@
|
|
|
2779
2795
|
"path": "scripts/worktree-lifecycle/capabilities.json",
|
|
2780
2796
|
"kind": "doc",
|
|
2781
2797
|
"installRole": "consumer",
|
|
2782
|
-
"sha256": "
|
|
2798
|
+
"sha256": "689910f11b51a5f2938989a82378332375e614f2684fe4cc48db7a4ce5c12f4b",
|
|
2783
2799
|
"mode": 420,
|
|
2784
2800
|
"origin": "kit"
|
|
2785
2801
|
},
|
|
@@ -2787,7 +2803,7 @@
|
|
|
2787
2803
|
"path": "scripts/worktree-lifecycle/cleanup.py",
|
|
2788
2804
|
"kind": "script",
|
|
2789
2805
|
"installRole": "consumer",
|
|
2790
|
-
"sha256": "
|
|
2806
|
+
"sha256": "4671aa6d40590abe103509916abda34e1717b43f7f0f521fc7fe90e1e29be50d",
|
|
2791
2807
|
"mode": 493,
|
|
2792
2808
|
"origin": "kit"
|
|
2793
2809
|
},
|
|
@@ -2795,7 +2811,7 @@
|
|
|
2795
2811
|
"path": "scripts/worktree-lifecycle/core.py",
|
|
2796
2812
|
"kind": "script",
|
|
2797
2813
|
"installRole": "consumer",
|
|
2798
|
-
"sha256": "
|
|
2814
|
+
"sha256": "50c60de1e0238fa1f5cd627f67e57ca4f378275136691411487f36d7fda580dd",
|
|
2799
2815
|
"mode": 420,
|
|
2800
2816
|
"origin": "kit"
|
|
2801
2817
|
},
|
|
@@ -2803,7 +2819,7 @@
|
|
|
2803
2819
|
"path": "scripts/worktree-lifecycle/profile.py",
|
|
2804
2820
|
"kind": "script",
|
|
2805
2821
|
"installRole": "consumer",
|
|
2806
|
-
"sha256": "
|
|
2822
|
+
"sha256": "4a76462e4a9f7c4c3fd1b199217f8c68b9946c49bc934eef7bc888244bdbd16f",
|
|
2807
2823
|
"mode": 420,
|
|
2808
2824
|
"origin": "kit"
|
|
2809
2825
|
},
|
|
@@ -2811,15 +2827,23 @@
|
|
|
2811
2827
|
"path": "scripts/worktree-lifecycle/README.md",
|
|
2812
2828
|
"kind": "doc",
|
|
2813
2829
|
"installRole": "consumer",
|
|
2814
|
-
"sha256": "
|
|
2830
|
+
"sha256": "91cfa8ebb74872ccec1160c0a7b28edcfacea3217900805034dca0f0c8f39c05",
|
|
2815
2831
|
"mode": 420,
|
|
2816
2832
|
"origin": "kit"
|
|
2817
2833
|
},
|
|
2834
|
+
{
|
|
2835
|
+
"path": "scripts/worktree-lifecycle/session.py",
|
|
2836
|
+
"kind": "script",
|
|
2837
|
+
"installRole": "consumer",
|
|
2838
|
+
"sha256": "18c2794aaf9fef96a15000c515b600345d3bf1715e23b07d0646156e601ea35a",
|
|
2839
|
+
"mode": 493,
|
|
2840
|
+
"origin": "kit"
|
|
2841
|
+
},
|
|
2818
2842
|
{
|
|
2819
2843
|
"path": "scripts/worktree-lifecycle/setup.py",
|
|
2820
2844
|
"kind": "script",
|
|
2821
2845
|
"installRole": "consumer",
|
|
2822
|
-
"sha256": "
|
|
2846
|
+
"sha256": "fa84d0056b24263389e0d17746abc8dc0afbd0152c323a62a6d7590ca9c62cac",
|
|
2823
2847
|
"mode": 493,
|
|
2824
2848
|
"origin": "kit"
|
|
2825
2849
|
},
|
|
@@ -2827,7 +2851,7 @@
|
|
|
2827
2851
|
"path": "scripts/wrapup-land.py",
|
|
2828
2852
|
"kind": "script",
|
|
2829
2853
|
"installRole": "consumer",
|
|
2830
|
-
"sha256": "
|
|
2854
|
+
"sha256": "476012558bb786070ce47458c6f0734ff110d5d957af72e13b20d49a37a03592",
|
|
2831
2855
|
"mode": 493,
|
|
2832
2856
|
"origin": "kit"
|
|
2833
2857
|
},
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Session teardown requires provenance-bound ownership
|
|
2
|
+
|
|
3
|
+
Status: accepted (2026-07-26, Wave #271)
|
|
4
|
+
|
|
5
|
+
Long agent sessions create branches, linked worktrees, setup outputs, and
|
|
6
|
+
landing-time build artifacts. The desired end state is that every
|
|
7
|
+
provenance-captured target created by that session can be removed, including
|
|
8
|
+
branches whose changes reached
|
|
9
|
+
canonical `main` through patch-equivalent commits rather than ancestry.
|
|
10
|
+
|
|
11
|
+
Repository state alone cannot identify that ownership safely. A foreign branch
|
|
12
|
+
can have the same name or patch, a user file can match a generated-artifact
|
|
13
|
+
pattern, and a path can be replaced between assessment and deletion. Retrying
|
|
14
|
+
after a crash adds a time dimension: a fresh snapshot cannot distinguish an
|
|
15
|
+
earlier generator output from a file created by the user between attempts.
|
|
16
|
+
|
|
17
|
+
We decided that teardown authority must come from **Teardown provenance**, not
|
|
18
|
+
from present-day similarity:
|
|
19
|
+
|
|
20
|
+
1. A session records intent before creation, but receives cleanup authority only
|
|
21
|
+
through an atomic **Ownership proof**. Branch and proof ref are acquired in
|
|
22
|
+
one Git transaction bound to the active wave claim.
|
|
23
|
+
2. Setup, session work, and landing are separate provenance boundaries. Setup
|
|
24
|
+
and session cleanup use the worktree-creation baseline; landing cleanup uses
|
|
25
|
+
a persisted landing-attempt boundary and freezes the exact outputs of its
|
|
26
|
+
generator-capable step.
|
|
27
|
+
3. Paths and patterns select candidates but never prove identity. Cleanup binds
|
|
28
|
+
regular files and worktree roots to no-follow object evidence and revalidates
|
|
29
|
+
that evidence immediately before mutation.
|
|
30
|
+
4. The **Lifecycle receipt** is a durably replaced state-transition journal.
|
|
31
|
+
Prepared Git ref transactions close the worktree-removal race, and committed
|
|
32
|
+
intermediate states make known outcomes resumable. An external SIGKILL may
|
|
33
|
+
still leave Git's own lock files requiring operator recovery.
|
|
34
|
+
5. Lost evidence is not reconstructed from coincidence. An interrupted landing
|
|
35
|
+
attempt without frozen outputs can be archived without claiming or deleting
|
|
36
|
+
its files, after which the ambiguous files must be classified before a new
|
|
37
|
+
attempt proceeds.
|
|
38
|
+
|
|
39
|
+
## Considered options
|
|
40
|
+
|
|
41
|
+
- **Delete branches merged by ancestry:** rejected because squash,
|
|
42
|
+
cherry-pick, and patch-equivalent integration leave session-owned branch refs
|
|
43
|
+
outside ancestry.
|
|
44
|
+
- **Treat a receipt row as ownership:** rejected because another process can
|
|
45
|
+
create the named branch or worktree after the absence check but before the
|
|
46
|
+
attempted creation.
|
|
47
|
+
- **Authorize files by ignored path or generator pattern:** rejected because a
|
|
48
|
+
consumer file can occupy the same path before landing or replace an assessed
|
|
49
|
+
output afterward.
|
|
50
|
+
- **Take a fresh landing snapshot on every retry:** rejected because it protects
|
|
51
|
+
prior generator outputs as if they predated landing, while a persistent start
|
|
52
|
+
snapshot alone incorrectly claims every later matching user file.
|
|
53
|
+
- **Force-remove apparently clean targets:** rejected because force bypasses the
|
|
54
|
+
repository and filesystem evidence that distinguishes owned work from foreign
|
|
55
|
+
work.
|
|
56
|
+
- **Guess ownership after an unjournaled crash window:** rejected because safe
|
|
57
|
+
cleanup and guaranteed automatic liveness cannot both be recovered after the
|
|
58
|
+
distinguishing evidence is lost.
|
|
59
|
+
|
|
60
|
+
## Consequences
|
|
61
|
+
|
|
62
|
+
- A completed session can remove its exact worktrees, branches, proof refs, and
|
|
63
|
+
provenance-captured generated artifacts without hiding history or sweeping
|
|
64
|
+
unrelated repository state.
|
|
65
|
+
- Foreign branches, worktrees, replacement symlinks, replacements, late writes,
|
|
66
|
+
and pre-landing consumer files are hard stops or remain outside cleanup
|
|
67
|
+
authority. Setup recovery may remove only a symlink whose exact no-follow
|
|
68
|
+
identity it captured as setup-created.
|
|
69
|
+
- Exact unchanged frozen evidence is deterministically resumable. Started or
|
|
70
|
+
drifted frozen attempts can be explicitly relinquished by archiving only the
|
|
71
|
+
receipt; every current file then remains protected and must be classified
|
|
72
|
+
before another attempt.
|
|
73
|
+
- Provenance-less legacy worktrees receive only a conservative baseline after
|
|
74
|
+
exact registration, no-follow root, attached branch, and clean tracked/index
|
|
75
|
+
checks. Setup reuse defers backfill while tracked work or current
|
|
76
|
+
landing-generated blockers remain. Landing classifies those blockers before
|
|
77
|
+
writing evidence; after they are moved, all remaining current ignored and
|
|
78
|
+
untracked files become protected. Corrupt evidence and active attempts are
|
|
79
|
+
never backfilled.
|
|
80
|
+
- Before merge, a committed worktree policy may nominate only exact,
|
|
81
|
+
identity-bound cleanup candidates; it authorizes no deletion. After merge,
|
|
82
|
+
the profile is reloaded directly from canonical `origin/main` and must match
|
|
83
|
+
both the candidate and attempt-bound policy digest before any mutation.
|
|
84
|
+
Generator evidence is also reauthorized path-by-path against that canonical
|
|
85
|
+
policy. Missing policy, an unmerged widening, or branch/canonical drift
|
|
86
|
+
preserves every file.
|
|
87
|
+
- The lifecycle implementation is necessarily a small transaction protocol,
|
|
88
|
+
with more states and race tests than a path-based cleanup script.
|
|
@@ -7,12 +7,22 @@
|
|
|
7
7
|
"branchRegex": "^(?:feat|fix|chore|docs)/(?P<issue>\\d+)-",
|
|
8
8
|
"mainBranches": ["main"],
|
|
9
9
|
"protectedBranches": ["main"],
|
|
10
|
-
"scratchPatterns": [
|
|
10
|
+
"scratchPatterns": [
|
|
11
|
+
"PLAN.md",
|
|
12
|
+
"PLAN-REVIEW-LOG.md",
|
|
13
|
+
".claude/logs/**"
|
|
14
|
+
],
|
|
11
15
|
"setupEntry": "python3 scripts/worktree-lifecycle/setup.py",
|
|
12
16
|
"setupSteps": [],
|
|
13
17
|
"riskyCommandPatterns": [
|
|
14
18
|
"\\b(?:npm|pnpm|yarn)\\s+(?:run\\s+)?(?:test|typecheck|build)\\b",
|
|
15
19
|
"\\bgit\\s+(?:commit|push)\\b"
|
|
16
20
|
]
|
|
21
|
+
},
|
|
22
|
+
"wrapup": {
|
|
23
|
+
"landingGeneratedArtifactPatterns": [
|
|
24
|
+
"dist-kit/**",
|
|
25
|
+
"**/__pycache__/**"
|
|
26
|
+
]
|
|
17
27
|
}
|
|
18
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikon85/agent-workflow-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "Portable AI-agent workflow skills (plan → execute → land → learn) for Claude Code & Codex — grilling, TDD, diagnosis, two-axis code review, cross-model Codex review, design & domain-modeling, plus a skill router (ask-matt). npx init/update/diff/uninstall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|