@deftai/directive-runtime 0.129.5 → 0.129.7
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/Taskfile.yml +316 -0
- package/UPGRADING.md +1 -0
- package/commands.md +5 -3
- package/contracts/design-critique.md +1 -1
- package/contracts/path-write-fence.md +6 -0
- package/dist/applying-host-release.d.ts +16 -0
- package/dist/applying-host-release.js +98 -0
- package/dist/authz.d.ts +1 -1
- package/dist/authz.js +1 -1
- package/dist/check.d.ts +1 -0
- package/dist/check.js +27 -4
- package/dist/design-critique-ensure-arc-dest.d.ts +16 -0
- package/dist/design-critique-ensure-arc-dest.js +168 -0
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +8 -0
- package/dist/hook-dispatch.js +3 -2
- package/dist/human-presence-mint.d.ts +6 -1
- package/dist/human-presence-mint.js +20 -6
- package/dist/session-start.d.ts +8 -2
- package/dist/session-start.js +70 -15
- package/dist/setup-wiring.d.ts +36 -0
- package/dist/setup-wiring.js +169 -14
- package/dist/vbrief-preflight.d.ts +4 -0
- package/dist/vbrief-preflight.js +34 -0
- package/dist/verify-scope-provenance.d.ts +13 -1
- package/dist/verify-scope-provenance.js +44 -1
- package/dist/verify-source-cli/verify-deposit-closure.js +5 -5
- package/dist/windows-bin-ps1.d.ts +2 -2
- package/dist/windows-bin-ps1.js +5 -11
- package/docs/deft-directive-disable.md +3 -3
- package/docs/getting-started.md +2 -0
- package/docs/scope-provenance.md +15 -1
- package/package.json +2 -3
- package/packs/lessons/lessons-pack-0.1.json +15 -0
- package/packs/skills/skills-pack-0.1.json +3 -3
- package/skills/deft-directive-design-critique/SKILL.md +1 -1
- package/skills/deft-directive-release/SKILL.md +31 -1
- package/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-content/Taskfile.yml +316 -0
- package/vendor/directive-content/UPGRADING.md +1 -0
- package/vendor/directive-content/commands.md +5 -3
- package/vendor/directive-content/contracts/design-critique.md +1 -1
- package/vendor/directive-content/contracts/path-write-fence.md +6 -0
- package/vendor/directive-content/docs/deft-directive-disable.md +3 -3
- package/vendor/directive-content/docs/getting-started.md +2 -0
- package/vendor/directive-content/docs/scope-provenance.md +15 -1
- package/vendor/directive-content/packs/lessons/lessons-pack-0.1.json +15 -0
- package/vendor/directive-content/packs/skills/skills-pack-0.1.json +3 -3
- package/vendor/directive-content/skills/deft-directive-design-critique/SKILL.md +1 -1
- package/vendor/directive-content/skills/deft-directive-release/SKILL.md +31 -1
- package/vendor/directive-content/skills/deft-directive-review-cycle/SKILL.md +15 -6
- package/vendor/directive-content/skills/deft-directive-swarm/references/host-grok-build.md +3 -2
- package/vendor/directive-core/dist/.tsbuildinfo +1 -1
- package/vendor/directive-core/dist/authz/classify.d.ts +12 -0
- package/vendor/directive-core/dist/authz/classify.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/classify.js +40 -12
- package/vendor/directive-core/dist/authz/classify.js.map +1 -1
- package/vendor/directive-core/dist/authz/templates.d.ts +2 -2
- package/vendor/directive-core/dist/authz/templates.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/templates.js +1 -0
- package/vendor/directive-core/dist/authz/templates.js.map +1 -1
- package/vendor/directive-core/dist/authz/types.d.ts +1 -1
- package/vendor/directive-core/dist/authz/types.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/types.js +2 -0
- package/vendor/directive-core/dist/authz/types.js.map +1 -1
- package/vendor/directive-core/dist/authz/verb-classification.d.ts.map +1 -1
- package/vendor/directive-core/dist/authz/verb-classification.js +30 -3
- package/vendor/directive-core/dist/authz/verb-classification.js.map +1 -1
- package/vendor/directive-core/dist/cache/fetch.d.ts.map +1 -1
- package/vendor/directive-core/dist/cache/fetch.js +50 -4
- package/vendor/directive-core/dist/cache/fetch.js.map +1 -1
- package/vendor/directive-core/dist/design-critique/arc-dest.d.ts +22 -5
- package/vendor/directive-core/dist/design-critique/arc-dest.d.ts.map +1 -1
- package/vendor/directive-core/dist/design-critique/arc-dest.js +61 -0
- package/vendor/directive-core/dist/design-critique/arc-dest.js.map +1 -1
- package/vendor/directive-core/dist/design-critique/run-posture.d.ts +7 -2
- package/vendor/directive-core/dist/design-critique/run-posture.d.ts.map +1 -1
- package/vendor/directive-core/dist/design-critique/run-posture.js +6 -1
- package/vendor/directive-core/dist/design-critique/run-posture.js.map +1 -1
- package/vendor/directive-core/dist/fs/contained-write.d.ts +8 -2
- package/vendor/directive-core/dist/fs/contained-write.d.ts.map +1 -1
- package/vendor/directive-core/dist/fs/contained-write.js +22 -6
- package/vendor/directive-core/dist/fs/contained-write.js.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/dispatcher.js +290 -16
- package/vendor/directive-core/dist/hooks/dispatcher.js.map +1 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.d.ts +5 -0
- package/vendor/directive-core/dist/hooks/shell-write-targets.d.ts.map +1 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.js +18 -1
- package/vendor/directive-core/dist/hooks/shell-write-targets.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts +26 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js +52 -3
- package/vendor/directive-core/dist/init-deposit/agent-hooks.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts +48 -0
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js +170 -9
- package/vendor/directive-core/dist/init-deposit/host-hook-outer.js.map +1 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.d.ts +8 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.d.ts.map +1 -1
- package/vendor/directive-core/dist/init-deposit/scaffold.js +38 -4
- package/vendor/directive-core/dist/init-deposit/scaffold.js.map +1 -1
- package/vendor/directive-core/dist/install-health/cheap.d.ts +2 -1
- package/vendor/directive-core/dist/install-health/cheap.d.ts.map +1 -1
- package/vendor/directive-core/dist/install-health/cheap.js +4 -3
- package/vendor/directive-core/dist/install-health/cheap.js.map +1 -1
- package/vendor/directive-core/dist/install-health/constants.d.ts +18 -2
- package/vendor/directive-core/dist/install-health/constants.d.ts.map +1 -1
- package/vendor/directive-core/dist/install-health/constants.js +18 -2
- package/vendor/directive-core/dist/install-health/constants.js.map +1 -1
- package/vendor/directive-core/dist/policy/deft-directive-disable.d.ts +42 -5
- package/vendor/directive-core/dist/policy/deft-directive-disable.d.ts.map +1 -1
- package/vendor/directive-core/dist/policy/deft-directive-disable.js +71 -41
- package/vendor/directive-core/dist/policy/deft-directive-disable.js.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.d.ts +6 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.js +24 -12
- package/vendor/directive-core/dist/pr-closeout-attestable/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.d.ts +68 -14
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.js +278 -47
- package/vendor/directive-core/dist/pr-closeout-attestable/pr-head-assert.js.map +1 -1
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts +10 -5
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.d.ts.map +1 -1
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js +41 -18
- package/vendor/directive-core/dist/pr-merge-readiness/slizard-gate.js.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts +3 -2
- package/vendor/directive-core/dist/preflight-gh/pre-push.d.ts.map +1 -1
- package/vendor/directive-core/dist/preflight-gh/pre-push.js +19 -18
- package/vendor/directive-core/dist/preflight-gh/pre-push.js.map +1 -1
- package/vendor/directive-core/dist/release/gh.d.ts.map +1 -1
- package/vendor/directive-core/dist/release/gh.js +2 -1
- package/vendor/directive-core/dist/release/gh.js.map +1 -1
- package/vendor/directive-core/dist/release/version.d.ts +4 -2
- package/vendor/directive-core/dist/release/version.d.ts.map +1 -1
- package/vendor/directive-core/dist/release/version.js +4 -2
- package/vendor/directive-core/dist/release/version.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/gh-api.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/gh-api.js +4 -2
- package/vendor/directive-core/dist/release-publish/gh-api.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/main.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/main.js +15 -4
- package/vendor/directive-core/dist/release-publish/main.js.map +1 -1
- package/vendor/directive-core/dist/release-publish/pipeline.d.ts +11 -0
- package/vendor/directive-core/dist/release-publish/pipeline.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-publish/pipeline.js +143 -2
- package/vendor/directive-core/dist/release-publish/pipeline.js.map +1 -1
- package/vendor/directive-core/dist/release-rollback/gh.d.ts.map +1 -1
- package/vendor/directive-core/dist/release-rollback/gh.js +2 -1
- package/vendor/directive-core/dist/release-rollback/gh.js.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts +202 -19
- package/vendor/directive-core/dist/scope/delivery-evidence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/delivery-evidence.js +948 -107
- package/vendor/directive-core/dist/scope/delivery-evidence.js.map +1 -1
- package/vendor/directive-core/dist/scope/transition.d.ts +4 -1
- package/vendor/directive-core/dist/scope/transition.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope/transition.js +2 -2
- package/vendor/directive-core/dist/scope/transition.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts +11 -2
- package/vendor/directive-core/dist/scope-provenance/base-fence.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.js +16 -1
- package/vendor/directive-core/dist/scope-provenance/base-fence.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts +12 -0
- package/vendor/directive-core/dist/scope-provenance/evaluate.d.ts.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/evaluate.js +41 -5
- package/vendor/directive-core/dist/scope-provenance/evaluate.js.map +1 -1
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts +106 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.d.ts.map +1 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js +382 -0
- package/vendor/directive-core/dist/scope-provenance/forge-approval.js.map +1 -0
- package/vendor/directive-core/dist/session/git.d.ts +21 -2
- package/vendor/directive-core/dist/session/git.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/git.js +21 -4
- package/vendor/directive-core/dist/session/git.js.map +1 -1
- package/vendor/directive-core/dist/session/occupancy.d.ts +93 -6
- package/vendor/directive-core/dist/session/occupancy.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/occupancy.js +215 -52
- package/vendor/directive-core/dist/session/occupancy.js.map +1 -1
- package/vendor/directive-core/dist/session/orientation-compression.d.ts +18 -2
- package/vendor/directive-core/dist/session/orientation-compression.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/orientation-compression.js +38 -5
- package/vendor/directive-core/dist/session/orientation-compression.js.map +1 -1
- package/vendor/directive-core/dist/session/session-start.d.ts +47 -2
- package/vendor/directive-core/dist/session/session-start.d.ts.map +1 -1
- package/vendor/directive-core/dist/session/session-start.js +154 -3
- package/vendor/directive-core/dist/session/session-start.js.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts +18 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js +28 -4
- package/vendor/directive-core/dist/swarm/approach1-babysitter.js.map +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.d.ts +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/dest-place.js +36 -41
- package/vendor/directive-core/dist/swarm/dest-place.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts +29 -0
- package/vendor/directive-core/dist/swarm/finalize-cohort.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-cohort.js +122 -11
- package/vendor/directive-core/dist/swarm/finalize-cohort.js.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts +14 -0
- package/vendor/directive-core/dist/swarm/finalize-owed.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/finalize-owed.js +214 -48
- package/vendor/directive-core/dist/swarm/finalize-owed.js.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/launch.js +15 -4
- package/vendor/directive-core/dist/swarm/launch.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktree-pm-install.d.ts +49 -2
- package/vendor/directive-core/dist/swarm/worktree-pm-install.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktree-pm-install.js +207 -12
- package/vendor/directive-core/dist/swarm/worktree-pm-install.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees-cli.d.ts +6 -0
- package/vendor/directive-core/dist/swarm/worktrees-cli.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees-cli.js +79 -2
- package/vendor/directive-core/dist/swarm/worktrees-cli.js.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees.d.ts +12 -1
- package/vendor/directive-core/dist/swarm/worktrees.d.ts.map +1 -1
- package/vendor/directive-core/dist/swarm/worktrees.js +34 -26
- package/vendor/directive-core/dist/swarm/worktrees.js.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.d.ts.map +1 -1
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js +219 -60
- package/vendor/directive-core/dist/triage/evaluate/worktrees.js.map +1 -1
|
@@ -53,7 +53,7 @@ Yolo first-lean cites: Yolo leftover-pain. Honest pain cites. Not operator next-
|
|
|
53
53
|
Walk / walk all. Auto-stamp when agents agree: Operator verbs.
|
|
54
54
|
Parent chip write: scm:issue:design-critique-chip. Stale ingest-ready query: scm:issue:design-critique-stale-ready.
|
|
55
55
|
Chip apply miss is non-blocking convenience; do not halt. On missing-repo-label chip miss, follow contract ensure-or-doctor recovery. Ingest waits on the completed-arc record, not a catalog chip.
|
|
56
|
-
Run posture: missing defaults to no-ingest via resolveArcRunPostureForHost; ingest resolves checkout; closed collisions ask. Field lives in the contract.
|
|
56
|
+
Run posture: missing defaults to no-ingest via resolveArcRunPostureForHost; ingest resolves checkout; closed collisions ask. Field lives in the contract. Arc dest: `deft design-critique:ensure-arc-dest` (guarded-prep default; `--install-mode process-only-no-install` for pin-read); fail closed if pin missing after guarded-prep. ⊗ gitignored `packages/core/dist` as SoT for ensureArcDest.
|
|
57
57
|
Spend: closed n= wins for `spend:` (does not invent `spend-recommend:`); else call `deft design-critique:spend-resolve --utterance <text> --recommend` then resolve. Open with `--open-gate` at arc start before any structured ask (session-scoped state); `--clear` when the arc ends; `--unclosable-recommend` for parent-declared unclosable. Bare-arc missing recommend is a parent defect (record then resolve), not ask. Ask only for ambiguous mixes, bare panel, or unclosable recommend. Call spend-resolve before any operator surface. Field lives in the contract. Consume parseOperatorSpend / resolveDesignCritiqueSpend. ⊗ ask_user_question for spend on bare arc before spend-resolve / open-gate.
|
|
58
58
|
Yolo standing: default on; noyolo clears; yolo affirms. Confirm conjunct only. Not ingest.
|
|
59
59
|
Widget apply-set lives in the contract. Consume parseOperatorRunPosture / parseOperatorYoloStanding.
|
|
@@ -17,7 +17,7 @@ description: >-
|
|
|
17
17
|
|
|
18
18
|
# Deft Directive Release
|
|
19
19
|
|
|
20
|
-
Structured 8-phase workflow for cutting a v0.X.Y release of the deft framework. Operationalizes the `task release` / `task release:publish` / `task release:rollback` / `task release:e2e` / `task release:wait-npm` surface introduced in #716 (safety hardening of #74; Phase 7 wait #4267).
|
|
20
|
+
Structured 8-phase workflow for cutting a v0.X.Y release of the deft framework. Operationalizes the `task release` / `task release:publish` / `task release:rollback` / `task release:e2e` / `task release:wait-npm` / `task release:local-update` surface introduced in #716 (safety hardening of #74; Phase 7 wait #4267; maintainer checkout closeout #5953).
|
|
21
21
|
|
|
22
22
|
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
23
23
|
|
|
@@ -373,6 +373,10 @@ Race-condition mitigation: `download_count` is double-read with a 5s sleep betwe
|
|
|
373
373
|
|
|
374
374
|
! Only enter Phase 7 if Phase 6 took the Publish branch (rollback branch ends here with the unwind log).
|
|
375
375
|
|
|
376
|
+
! **Stable cut: decide npm latest explicitly (#5852).** A stable `X.Y.Z` publishes to the `maintainer` dist-tag and a prerelease to its id (`beta`, `rc`, ...); the publish never moves `latest` and the GitHub release is not marked Latest. For a stable cut, ask the operator: **promote now** or **record an explicit decline**. Promote is the separate `release-promote-latest` closed verb (mint `deft authz:grant -- --template release-promote-latest --target <version> --confirm` or set `DEFT_ALLOW_RELEASE_PROMOTE_LATEST=1`; a release-publish grant does not cover it). Run the gated command `deft release-publish --promote-latest <version>` (optional `--dry-run`); it evaluates the closed-verb gate and only then dispatches `gh workflow run npm-publish.yml --ref master -f action=promote-latest -f tag=v<version>`. That job (environment `npm`, concurrency `npm-promote-latest`) preflights both packages then moves `latest` for both and marks the GitHub release Latest. A decline is recorded in the release notes or record as "latest stays at <prior version>". Non-latest announcements give `npm i -g @deftai/directive@<dist-tag>`, not `@latest`.
|
|
377
|
+
|
|
378
|
+
! Do not move `latest` with a bare shell `npm dist-tag add` or a bare `gh workflow run` for promote; use `deft release-publish --promote-latest`.
|
|
379
|
+
|
|
376
380
|
1. ! **Wait until both public packages list the cut version (#4267, #1910, #3753).** Run `task release:wait-npm -- <version>`. That caller polls `npm view <pkg> versions` (prefer-online, doctor temp-cwd isolation) until both `@deftai/directive` and `@deftai/directive-runtime` list `<version>`, or 10 minutes. Partial visibility is **still-propagating** (wait before `npm i -g`); none visible after the wait is **publish-incomplete**. Report-only: must not fail the GitHub release. Confirm provenance on the npm page after the wait. ⊗ Treat a green `npm-publish.yml` job plus one visible sibling as registry truth. ⊗ Run `npm i -g`. `task release` Step 13 stays a single probe (timeout 0).
|
|
377
381
|
2. ! **Report local-vs-released CLI drift (#3753).** `task release:wait-npm` already prints the local global CLI version, the released version, whether they match, and the exact remediation `npm i -g @deftai/directive@<version> --prefer-online`. Compare versions with `checkActiveCliAgainstTarget` (not bare `deft --version`) so a PATH-shadowed install cannot report success (#3233). The report must not fail the release.
|
|
378
382
|
3. ! Verify GitHub auto-closed the discrete-task issue(s) referenced via `Closes #N` in the release notes (mirrors `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 2)
|
|
@@ -381,6 +385,27 @@ Race-condition mitigation: `download_count` is double-read with a 5s sleep betwe
|
|
|
381
385
|
6. ! Verify binaries are downloadable from the public release URL: `gh release view v<version> --json assets --jq '.assets[].url'` and curl one to confirm 200 OK
|
|
382
386
|
7. ! For any umbrella / staying-OPEN issue (`Refs #N`) referenced in the release notes, run the Layer 3 reopen sweep from `skills/deft-directive-swarm/SKILL.md` Phase 6 Step 1: any protected issue that auto-closed MUST be reopened with a comment citing #701
|
|
383
387
|
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
8. ! **Update the maintainer's local checkout (#5953 Prefer-A Bound 6430511888).** Required for every release; **required especially for maintainer (non-`latest`) cuts** where npm `latest` will not advance the checkout by accident. Anchor on the **tip-pin-equals-released** observable (tip `package.json` / lockfile pin equals released `<version>`), not a phantom pin-PR step.
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
task release:local-update -- <version> --checkout <maintainer-primary-occupancy-root>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The task fails closed and never resets, force-pushes, commits, or runs `npm i -g`:
|
|
397
|
+
1. Require `--checkout <path>` naming the maintainer primary occupancy root; refuse ambient release-worktree-only success (running only in the release worktree without naming the primary).
|
|
398
|
+
2. Refuse when the target checkout holds a live foreign occupancy lease before any write.
|
|
399
|
+
3. On the checkout default branch: dirty-tree refuse; `git pull --ff-only` (never reset).
|
|
400
|
+
4. When `pnpm-workspace.yaml` carries `minimumReleaseAgeExclude`, assert it already includes `@deftai/directive-runtime@<version>`; then `pnpm install --frozen-lockfile`.
|
|
401
|
+
5. Assert tip-pin-equals-released: installed `node_modules/@deftai/directive-runtime` version equals `<version>` and matches the `package.json` pin.
|
|
402
|
+
6. Require the version-matched agent-hook deposit already merged on tip (inspect against the post-install payload via the checkout runtime). Keep Phase 7 local closeout **incomplete** until that deposit evidence exists; print deposit-merge recovery paths.
|
|
403
|
+
7. Re-resolve the upgrade binary from the checkout post-install tree and run `directive upgrade --target-version <version> --yes` (never registry-latest). `release:local-update` is inline Taskfile `cmds:` without `engine:invoke` or `deps: [ts:build]`.
|
|
404
|
+
8. After upgrade, any tracked-file diff keeps closeout non-zero/incomplete with deposit-merge recovery paths for expected managed deposit files (`.grok/hooks/`, `.cursor/hooks.json`, `.claude/settings.json`, `.codex/` managed paths, and related deposit files).
|
|
405
|
+
9. Run `deft verify:hooks-installed --project-root <checkout> --scope=all` from the checkout post-install runtime (⊗ bare `task verify:hooks-installed`) and re-assert installed runtime equals `<version>`.
|
|
406
|
+
|
|
407
|
+
Report the local-update result (version now installed, hooks status) beside the existing global CLI drift report in Skill Completion.
|
|
408
|
+
|
|
384
409
|
⊗ Skip the post-publish verification. The closing-keyword false-positive (Layer 1 / Layer 2 / Layer 3) and the incremental-renderer-drift (#641, #614) are exactly the kind of issues that surface only AFTER a release is public.
|
|
385
410
|
|
|
386
411
|
## Phase 8 — Slack announcement
|
|
@@ -421,10 +446,15 @@ Where `<one-line guidance>` is one of:
|
|
|
421
446
|
- "release v<version> rolled back -- the underlying defect needs a hot-fix in the next CHANGELOG entry"
|
|
422
447
|
- "release deferred -- resume by running `task release:publish -- <version>` (GitHub only; npm already shipped at tag push) or `task release:rollback -- <version>` (GitHub unwind only; npm is forward-recovery) when ready"
|
|
423
448
|
|
|
449
|
+
! On the Publish/live path, Skill Completion MUST also print the Phase 7 local-update result beside the global CLI drift report: checkout path, installed runtime version, hooks status (`verify:hooks-installed --scope=all`), and whether closeout is complete or incomplete (deposit-merge recovery). ⊗ Claim Phase 7 local closeout complete while `release:local-update` exited non-zero or was skipped on a maintainer non-latest cut (#5953).
|
|
450
|
+
|
|
424
451
|
⊗ Exit silently without confirming completion or providing next-step guidance.
|
|
425
452
|
|
|
426
453
|
## Anti-Patterns
|
|
427
454
|
|
|
455
|
+
- ⊗ End the release with the maintainer's checkout still on the previous pin (#5953) — run `task release:local-update -- <version> --checkout <primary>` after tip-pin-equals-released
|
|
456
|
+
- ⊗ Run `release:local-update` without `--checkout` naming the maintainer primary occupancy root, or claim success from the release worktree alone while primary stays stale (#5953)
|
|
457
|
+
- ⊗ Soft/warn-only checkout lag; non-fatal green on post-upgrade tracked diffs; auto-commit of upgrade deposit inside release; `directive upgrade` without `--target-version` (registry latest); bare `task verify:hooks-installed` without `--project-root` / `--scope=all`; local-update via pin-exclusive `engine:invoke` on the N-1 runtime (#5953 Prefer-A Bound 6430511888)
|
|
428
458
|
- ⊗ Foreground-block the operator chat on Phase 1 long prep (`reconcile:issues`, cache refresh) or Phase 3 `release:e2e` when background / subagent dispatch is available (#1880 Gap D / #2692) — the interactive channel must stay free for version confirmation, `--summary`, and the Phase 2 dry-run gate
|
|
429
459
|
- ⊗ Proceed to `task release` on orientation-dirty `cache_fresh` or check-class stale-by-drift, or treat skip-drift ritual green / ritual-stale as that bar (#4399) — fetch-all first
|
|
430
460
|
|
|
@@ -536,13 +536,21 @@ REDISPATCH_OK: yes|no
|
|
|
536
536
|
⊗ Treat `ci_never_scheduled` as ordinary Greptile latency (`sha_match` / `terminal_check_run` only).
|
|
537
537
|
⊗ Silent `--skip-ci` / admin merge without the outage playbook audit trail below.
|
|
538
538
|
|
|
539
|
-
### SLizard advisory-only for merge-ready wait (#3167)
|
|
539
|
+
### SLizard advisory-only for merge-ready wait (#3167) — weather vs residual (#5102 / #4387)
|
|
540
540
|
|
|
541
|
-
!
|
|
541
|
+
! SLizard is advisory only for the Greptile merge-ready confidence floor; parseable blocking tip fingerprints are unfinished residual (#5102 / #3167).
|
|
542
542
|
|
|
543
|
-
!
|
|
543
|
+
! Required bot for **merge-ready wait** / Step 6 exit ownership is **Greptile**. SLizard is **advisory only** for weather (timeout / cancelled / unparseable / zero-finding / missing-check): those MUST NOT gate the review-cycle wait loop (#3167). Parseable blocking tip fingerprints are unfinished residual (#5102).
|
|
544
544
|
|
|
545
|
-
|
|
545
|
+
! When `pr:merge-ready` / wait-mergeable reports **SLizard blocked** (parseable `request_changes` or `merge_impact=blocking` with non-zero findings) — especially Greptile CLEAN + SLizard blocked — before re-arming merge-ready wait or `pr:wait-mergeable-and-merge` the owner MUST read the tip SLizard **review body** in full, enumerate new and Previously mentioned fingerprints / deterministic tool names, and for each open P0/P1 falsify with `git show <head>:<path>` (slizard#2694) or fix in one residual batch. Do not idle-poll. Keep `pr:watch` Greptile ownership unchanged (#5102 / #2189 / #4387).
|
|
546
|
+
|
|
547
|
+
! Compose existing head-blob check, same-fingerprint stop (#3448), and `--skip-slizard` override. Do not invent a third poller. `--skip-slizard` is explicit override only — not the default babysit escape.
|
|
548
|
+
|
|
549
|
+
! Parseable blocking findings with open tip fingerprints are **unfinished residual**, not weather. Cross-link: `packages/core/src/pr-merge-readiness/slizard-gate.ts` (`evaluateSlizardGate`).
|
|
550
|
+
|
|
551
|
+
⊗ Re-arm wait-mergeable / idle-poll while SLizard still has parseable blocking findings with open tip fingerprints (#5102).
|
|
552
|
+
⊗ Treat parseable blocking SLizard findings as #3167 weather when Greptile Step 6 is clean (#5102 / #4387).
|
|
553
|
+
⊗ Default to `--skip-slizard` to clear a merge-ready SLizard block (#5102).
|
|
546
554
|
|
|
547
555
|
### Outage admin-merge playbook (opt-in / human, #3167)
|
|
548
556
|
|
|
@@ -725,7 +733,7 @@ Cross-links: swarm decision tree `skills/deft-directive-swarm/references/core-ph
|
|
|
725
733
|
|
|
726
734
|
! When the platform descriptor indicates Tier 1 (sub-agent support) **and this agent owns the primitive as parent/orchestrator**, spawn a review-monitor sub-agent using the primitive matching the descriptor. ⊗ A grok-build / grok-bot / Cursor / Claude Code implementation leaf MUST NOT run these spawn steps.
|
|
727
735
|
|
|
728
|
-
1. ! Launch via the matching primitive: `start_agent` (Warp), `spawn_subagent` (grok-build / TUI / non-Warp **parent**), the Cursor `Task` tool with `run_in_background: true` (`cursor-composer` / `cursor-cloud-agent`, #1877), the Claude Code `Agent` tool with `run_in_background: true` (`claude-code` / register `claude-agent`, #3134), OpenClaw `sessions_spawn` (`openclaw`, #2876), **or Grok Bot Task/executor/CloudAgent (`grok-bot` / register `grok-bot-executor`, #4201)** with a prompt that instructs it to poll for Greptile completion. For `spawn_subagent`, Cursor `Task`, Claude Code `Agent`, OpenClaw `sessions_spawn`, and Grok Bot executor the prompt MUST reference the canonical poller template `templates/swarm-greptile-poller-prompt.md` (with placeholders filled) plus the agent preamble; the working directory / context must be the PR branch (worktree or equivalent for hybrid).
|
|
736
|
+
1. ! Launch via the matching primitive: `start_agent` (Warp), `spawn_subagent` (grok-build / TUI / non-Warp **parent**), the Cursor `Task` tool with `run_in_background: true` (`cursor-composer` / `cursor-cloud-agent`, #1877), the Claude Code `Agent` tool with `run_in_background: true` (`claude-code` / register `claude-agent`, #3134), OpenClaw `sessions_spawn` (`openclaw`, #2876), **or Grok Bot Task/executor/CloudAgent (`grok-bot` / register `grok-bot-executor`, #4201)** with a prompt that instructs it to poll for Greptile completion. For `spawn_subagent`, Cursor `Task`, Claude Code `Agent`, OpenClaw `sessions_spawn`, and Grok Bot executor the prompt MUST reference the canonical poller template `templates/swarm-greptile-poller-prompt.md` (with placeholders filled) plus the agent preamble; the working directory / context must be the PR branch (worktree or equivalent for hybrid). **Grok Approach 1 watch/report (#4781):** before `review-monitor:register` / child `pr:watch`, spawn with advertised `process_only: true` + dest `cwd` for `stop-at: pr-open` + `worker_role: review-monitor` seats only (`formatApproach1ProcessOnlySpawnShape` / `approach1BabysitterCommands`). Implement-class never sets `process_only`; dest-path is not the skip class; do not blanket-flag the fix-capable greptile poller.
|
|
729
737
|
2. ! The sub-agent polls using the mechanism for its primitive: for `spawn_subagent` the **child** owns `pr:watch` / gh poll in its own process (adaptive cadence: ~20-30s first check after push, ~60s second, ~90s thereafter; Greptile typically lands in 3-7 min) — the user-facing parent MUST NOT enter `get_command_or_subagent_output`; a named durable-owner session MAY pull-wait (`host-grok-build.md` Gap D); for `start_agent` the native messaging path; for the Cursor `Task` tool the backgrounded-task completion-notification path; for Claude Code `Agent` the backgrounded-agent completion-notification path; for OpenClaw `sessions_spawn` the host session completion / messaging channel (prefer `task pr:watch` inside the child when available). Front-load the first check to catch fast reviews.
|
|
730
738
|
3. ! When the exit condition is met (Greptile review current on the HEAD commit SHA, confidence meets resolved min (policy/dogfood/default; see Step 6 #3095), no P0/P1 remaining), the sub-agent reports completion back to the parent (via `send_message_to_agent`, the spawn_subagent result channel, or the OpenClaw sessions completion channel).
|
|
731
739
|
4. ! The main conversation pane stays fully interactive during monitoring -- the user (or parent monitor) can continue other work. On Grok Build this is conditional until a measured completion-notify exists: it holds when the parent returns the turn after background spawn, not when the parent pull-waits (`host-grok-build.md` Gap D / #4796).
|
|
@@ -1029,7 +1037,8 @@ task lifecycle:event -- emit plan:approved \
|
|
|
1029
1037
|
- ⊗ Workflow thrash or empty-commit spam during attributed platform outage without status-page probe (#3180)
|
|
1030
1038
|
- ⊗ Tight forge-outage retry / empty-commit thrash without a one-shot human report (#3422)
|
|
1031
1039
|
- ⊗ Merge or `--skip-ci` solely because a status page is red without check-run evidence (#3180)
|
|
1032
|
-
- ⊗
|
|
1040
|
+
- ⊗ Re-arm wait-mergeable or treat parseable blocking SLizard tip fingerprints as #3167 weather when Greptile Step 6 is clean (#5102 / #3167)
|
|
1041
|
+
- ⊗ Idle-poll / skip reading tip SLizard review body while open Previously mentioned fingerprints remain (#5102)
|
|
1033
1042
|
- ⊗ Silent admin / `--skip-ci` merge under Actions outage without audit comment and opt-in authority (#3167)
|
|
1034
1043
|
- ⊗ Leave a deliberate `stop-at: pr-open` (or thin-DONE recovery) open PR without spawning/retaining one review-cycle babysit owner + lease continuity and post-merge `scope:complete` plan (#3153)
|
|
1035
1044
|
- ⊗ Stand down at CLEAN under human-merge policy without a durable owner (sticky lease + live parent/monitor/Phase 6 closer) **and** a post-CLEAN observe path (poller / parent wake / Phase 6 re-poll) for post-merge `scope:complete` (#3153 / #1193 / #2321)
|
|
@@ -92,14 +92,15 @@ Until a measured callback exists, Grok wording is conditional: background `spawn
|
|
|
92
92
|
|
|
93
93
|
! **Grok through-merge (#4529 / #4821 / #5219):** implement MUST use (b) `stop-at: pr-open`. Path (a) is for non-through-merge Grok leaves only. Named leftover (class A) requires a dest-cwd one-shot residual, stop-at after the push; then Approach 1 wait owner is a **`spawn_subagent` review-monitor sibling** whose `monitor_agent_id` is registered (`review-monitor:register --platform-primitive spawn_subagent`) and whose child-bound `pr:watch --monitor-agent-id <id>` satisfies `verify:review-monitor --merge-path-arm --live-wait`; then Phase 6 / parent-retained squash-merges via `pr:wait-mergeable-and-merge` only after CLEAN. Pass a declared wait budget when the envelope states one (#3984). Parent-retained is the **closer after CLEAN**, not the pre-CLEAN poller/fixer. Dest spawn deny is `BLOCKED` or dest-cwd residual via native implementation-capable spawn (#4215) — not parent-primary. ⊗ Send class-A residual through process-only CLI `grok --cwd`. ⊗ Choose Approach 1 sibling or parent-retained as the first partner without dest residual. ⊗ Dispatch a Grok through-merge implement as (a). ⊗ Harvest a Grok `drive-to: merge-ready` continuation as this closer. ⊗ Treat a parent-owned shell/`bash` `pr:watch` (heartbeat `parent_id=pr-watch`) as Approach 1 babysit when `spawn_subagent` is available (#5219).
|
|
94
94
|
|
|
95
|
-
! **Exclusive lawful waits / cheapest admitted Approach 1 (#5219 P3 / #5229 / #5727):** after `pr-open`, when Tier-1 `spawn_subagent` is available, the **only lawful** pre-CLEAN wait is Approach 1 child `pr:watch --monitor-agent-id` after `review-monitor:register --platform-primitive spawn_subagent` with `verify:review-monitor --merge-path-arm --live-wait` green; after CLEAN, parent-retained `pr:wait-mergeable-and-merge`. Approach 1 is also the **cheapest admitted** path vs parent shell `pr:watch`, host `monitor`, forge-poll, or bespoke `%TEMP%` pollers. Prefer one background `spawn_subagent` babysitter that owns watch → class A residual handoff → re-watch until CLEAN, then hand CLEAN to the parent closer. Child register + watch first (heartbeat live); parent verify after:
|
|
95
|
+
! **Exclusive lawful waits / cheapest admitted Approach 1 (#5219 P3 / #5229 / #5727 / #4781):** after `pr-open`, when Tier-1 `spawn_subagent` is available, the **only lawful** pre-CLEAN wait is Approach 1 child `pr:watch --monitor-agent-id` after `review-monitor:register --platform-primitive spawn_subagent` with `verify:review-monitor --merge-path-arm --live-wait` green; after CLEAN, parent-retained `pr:wait-mergeable-and-merge`. Approach 1 is also the **cheapest admitted** path vs parent shell `pr:watch`, host `monitor`, forge-poll, or bespoke `%TEMP%` pollers. Prefer one background `spawn_subagent` babysitter that owns watch → class A residual handoff → re-watch until CLEAN, then hand CLEAN to the parent closer. **Spawn shape before register/pr:watch (#4781):** for monitor-only seats (`stop-at: pr-open` + `worker_role: review-monitor` watch/report), pass advertised `process_only: true` with dest `cwd` (`formatApproach1ProcessOnlySpawnShape` / `approach1BabysitterCommands`). Implement-class never sets `process_only`; dest-path is not the skip class; do not blanket-flag the fix-capable greptile poller. Dest convention by write need: shared cwd-without-occupy for non-writing monitor/critic seats; one dest per validation seat that writes a report root. Specs/report writes stay on requirements posture (#4444) — do not fold report roots into the spawn skip class. Child register + watch first (heartbeat live); parent verify after:
|
|
96
96
|
```
|
|
97
|
+
# process_only+cwd spawn (monitor-only), then:
|
|
97
98
|
task review-monitor:register -- --pr <N> --monitor-agent-id <id> --platform-primitive spawn_subagent
|
|
98
99
|
DEFT_MONITOR_AGENT_ID=<id> task pr:watch -- <N> --monitor-agent-id <id>
|
|
99
100
|
# parent after child watch is live:
|
|
100
101
|
task verify:review-monitor -- --pr <N> --merge-path-arm --live-wait
|
|
101
102
|
```
|
|
102
|
-
Core helper: `formatApproach1BabysitterOneLiner` / `formatApproach1CheapestAdmissionCard` / `admitClaimedBabysitPath` (`packages/core/src/swarm/approach1-babysitter.ts`). Bounded-form deny: `evaluateBoundedPrWatchDeny` refuses Directive `pr:watch` / `task deft:pr:watch` without `--monitor-agent-id` when Tier 1 is provable. Claimed-wait deny: `evaluateClaimedBabysitPathDeny` / `admitClaimedBabysitPath` refuse `BabysitPathKind` forge-poll / bespoke-temp-poller / host-monitor / directive-pr-watch-bare and Approach 1 without bound evidence / different-PR arm. ⊗ Parent forge-poll / `gh` check-runs+mergeable_state sleep / bespoke `%TEMP%` PowerShell watchers as pre-CLEAN babysit (#5727). ⊗ Parent-shell `pr:watch --monitor-agent-id <leased id>` without spawn-injected `DEFT_MONITOR_AGENT_ID` (or CLI matching `GROK_SESSION_ID`) — that impersonation does not arm. ⊗ Start `pr:wait-mergeable-and-merge` before CLEAN (#4822). ⊗ Treat host `monitor` or bare shell `pr:watch` as the sole babysit when `spawn_subagent` is available (#5229).
|
|
103
|
+
Core helper: `formatApproach1BabysitterOneLiner` / `formatApproach1CheapestAdmissionCard` / `formatApproach1ProcessOnlySpawnShape` / `admitClaimedBabysitPath` (`packages/core/src/swarm/approach1-babysitter.ts`). Bounded-form deny: `evaluateBoundedPrWatchDeny` refuses Directive `pr:watch` / `task deft:pr:watch` without `--monitor-agent-id` when Tier 1 is provable. Claimed-wait deny: `evaluateClaimedBabysitPathDeny` / `admitClaimedBabysitPath` refuse `BabysitPathKind` forge-poll / bespoke-temp-poller / host-monitor / directive-pr-watch-bare and Approach 1 without bound evidence / different-PR arm. ⊗ Parent forge-poll / `gh` check-runs+mergeable_state sleep / bespoke `%TEMP%` PowerShell watchers as pre-CLEAN babysit (#5727). ⊗ Parent-shell `pr:watch --monitor-agent-id <leased id>` without spawn-injected `DEFT_MONITOR_AGENT_ID` (or CLI matching `GROK_SESSION_ID`) — that impersonation does not arm. ⊗ Start `pr:wait-mergeable-and-merge` before CLEAN (#4822). ⊗ Treat host `monitor` or bare shell `pr:watch` as the sole babysit when `spawn_subagent` is available (#5229).
|
|
103
104
|
|
|
104
105
|
! **Durable host→CLI capability stamp (#5229):** Before any CLI `verify:review-monitor` / `pr:watch` subprocess, write `.deft-scratch/host-capability-stamp.json` via `writeHostCapabilityStamp(projectRoot)` / `ensureHostCapabilityStampForBabysit` (and prefer exporting `GROK_BUILD=1` / `DEFT_HAS_SPAWN_SUBAGENT=1` into that subprocess). `review-monitor:register` also writes the stamp on successful claim/renew. Stamps older than 8h or bound to a different `host_session_id` are ignored so a later plain-terminal session cannot inherit Tier 1. Without a fresh stamp, bare `node … verify:review-monitor` can mis-detect Tier 3 / `generic-terminal` and fail-open with "no active review-monitor required" even though this parent owns `spawn_subagent`. `probeMonitoringTier` merges the stamp; `DEFT_MONITOR_TIER=3` is labeled `override-tier3` (not honest `generic-terminal`) and refused when stamp/env already proves Tier 1. `evaluateReviewMonitorGate` consults sticky lease `platform_primitive` before Approach 3 READY and before `!isTier1` READY. Bounded `pr:watch` without `--monitor-agent-id` is refused at the watch entry when Tier 1 is provable.
|
|
105
106
|
|
|
@@ -845,6 +845,322 @@ tasks:
|
|
|
845
845
|
vars:
|
|
846
846
|
ENGINE_CMD: 'release-wait-npm {{.CLI_ARGS}}'
|
|
847
847
|
|
|
848
|
+
# Phase 7 maintainer primary checkout closeout (#5953 Prefer-A Bound 6430511888).
|
|
849
|
+
# Inline cmds only — no engine:invoke / no deps:[ts:build] so the post-install
|
|
850
|
+
# payload can replace the N-1 runtime the cut was using. Never reset/force-push/
|
|
851
|
+
# commit / npm i -g.
|
|
852
|
+
release:local-update:
|
|
853
|
+
desc: "Phase 7 fail-closed maintainer checkout update (#5953) -- task release:local-update -- <version> --checkout <primary-occupancy-root>"
|
|
854
|
+
dir: '{{.USER_WORKING_DIR}}'
|
|
855
|
+
env:
|
|
856
|
+
PYTHONUTF8: "1"
|
|
857
|
+
cmds:
|
|
858
|
+
- |
|
|
859
|
+
set -e
|
|
860
|
+
# node -e bodies use shell single quotes + JS double quotes only (no apostrophes).
|
|
861
|
+
PARSE_OUT="$(node -e '
|
|
862
|
+
const raw = process.argv[1] || "";
|
|
863
|
+
const tokens = [];
|
|
864
|
+
let cur = "";
|
|
865
|
+
let q = null;
|
|
866
|
+
const DQ = String.fromCharCode(34);
|
|
867
|
+
const SQ = String.fromCharCode(39);
|
|
868
|
+
for (let i = 0; i < raw.length; i++) {
|
|
869
|
+
const ch = raw[i];
|
|
870
|
+
if (q) {
|
|
871
|
+
if (ch === q) { q = null; continue; }
|
|
872
|
+
cur += ch;
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
if (ch === DQ || ch === SQ) { q = ch; continue; }
|
|
876
|
+
if (/\s/.test(ch)) {
|
|
877
|
+
if (cur.length) { tokens.push(cur); cur = ""; }
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
cur += ch;
|
|
881
|
+
}
|
|
882
|
+
if (q) { console.error("release:local-update: unmatched quote in args"); process.exit(2); }
|
|
883
|
+
if (cur.length) tokens.push(cur);
|
|
884
|
+
let version = "";
|
|
885
|
+
let checkout = "";
|
|
886
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
887
|
+
const t = tokens[i];
|
|
888
|
+
if (t === "--checkout") {
|
|
889
|
+
const v = tokens[++i];
|
|
890
|
+
if (!v) { console.error("release:local-update: --checkout requires a path"); process.exit(2); }
|
|
891
|
+
checkout = v;
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
if (t.startsWith("--")) {
|
|
895
|
+
console.error("release:local-update: unknown flag " + t);
|
|
896
|
+
console.error("Usage: task release:local-update -- <version> --checkout <maintainer-primary-occupancy-root>");
|
|
897
|
+
process.exit(2);
|
|
898
|
+
}
|
|
899
|
+
if (!version) { version = t; continue; }
|
|
900
|
+
console.error("release:local-update: unexpected arg " + t);
|
|
901
|
+
process.exit(2);
|
|
902
|
+
}
|
|
903
|
+
if (!version) {
|
|
904
|
+
console.error("release:local-update: missing <version>");
|
|
905
|
+
console.error("Usage: task release:local-update -- <version> --checkout <maintainer-primary-occupancy-root>");
|
|
906
|
+
process.exit(2);
|
|
907
|
+
}
|
|
908
|
+
if (!checkout) {
|
|
909
|
+
console.error("release:local-update: refuse ambient release-worktree-only success; require --checkout naming the maintainer primary occupancy root (#5953)");
|
|
910
|
+
process.exit(1);
|
|
911
|
+
}
|
|
912
|
+
process.stdout.write(JSON.stringify({ version, checkout }));
|
|
913
|
+
' "{{.CLI_ARGS}}")"
|
|
914
|
+
VERSION="$(node -e 'const j=JSON.parse(process.argv[1]); process.stdout.write(j.version);' "$PARSE_OUT")"
|
|
915
|
+
CHECKOUT="$(node -e 'const j=JSON.parse(process.argv[1]); process.stdout.write(j.checkout);' "$PARSE_OUT")"
|
|
916
|
+
case "$CHECKOUT" in
|
|
917
|
+
/*|[A-Za-z]:*) ;;
|
|
918
|
+
*) CHECKOUT="$(pwd)/$CHECKOUT" ;;
|
|
919
|
+
esac
|
|
920
|
+
CHECKOUT="$(node -e 'const fs=require("fs"); const path=require("path"); const inPath=process.argv[1]; try { process.stdout.write(fs.realpathSync(inPath)); } catch { process.stdout.write(path.resolve(inPath)); }' "$CHECKOUT")"
|
|
921
|
+
if [ ! -d "$CHECKOUT/.git" ] && [ ! -f "$CHECKOUT/.git" ]; then
|
|
922
|
+
echo "release:local-update: --checkout is not a git checkout: $CHECKOUT" >&2
|
|
923
|
+
exit 1
|
|
924
|
+
fi
|
|
925
|
+
COMMON_DIR="$(git -C "$CHECKOUT" rev-parse --git-common-dir 2>/dev/null || true)"
|
|
926
|
+
if [ -z "$COMMON_DIR" ]; then
|
|
927
|
+
echo "release:local-update: cannot resolve git-common-dir for $CHECKOUT" >&2
|
|
928
|
+
exit 1
|
|
929
|
+
fi
|
|
930
|
+
case "$COMMON_DIR" in
|
|
931
|
+
/*|[A-Za-z]:*) ;;
|
|
932
|
+
*) COMMON_DIR="$CHECKOUT/$COMMON_DIR" ;;
|
|
933
|
+
esac
|
|
934
|
+
MAIN_ROOT="$(node -e 'const path=require("path"); process.stdout.write(path.resolve(path.dirname(process.argv[1])));' "$COMMON_DIR")"
|
|
935
|
+
SAME_MAIN="$(node -e 'const a=process.argv[1]; const b=process.argv[2]; const norm=s => process.platform==="win32" ? s.split(String.fromCharCode(92)).join("/").toLowerCase() : s.split(String.fromCharCode(92)).join("/"); process.stdout.write(norm(a)===norm(b)?"1":"0");' "$CHECKOUT" "$MAIN_ROOT")"
|
|
936
|
+
if [ "$SAME_MAIN" != "1" ]; then
|
|
937
|
+
echo "release:local-update: refuse ambient release-worktree-only success; --checkout must name the maintainer primary occupancy root (dirname git-common-dir=$MAIN_ROOT), not $CHECKOUT (#5953)" >&2
|
|
938
|
+
exit 1
|
|
939
|
+
fi
|
|
940
|
+
CHECKOUT_NORM="$(node -e 'process.stdout.write(String(process.argv[1]||"").split(String.fromCharCode(92)).join("/"));' "$CHECKOUT")"
|
|
941
|
+
case "$CHECKOUT_NORM" in
|
|
942
|
+
*/.deft-scratch/worktrees/*)
|
|
943
|
+
echo "release:local-update: refuse ambient release-worktree-only success; --checkout must name the maintainer primary occupancy root, not $CHECKOUT (#5953)" >&2
|
|
944
|
+
exit 1
|
|
945
|
+
;;
|
|
946
|
+
esac
|
|
947
|
+
print_deposit_recovery() {
|
|
948
|
+
echo "Phase 7 local closeout INCOMPLETE (#5953 / #6163 Prefer-A Bound 6772886751)." >&2
|
|
949
|
+
echo "Recovery: on the pin candidate, repair/write agent-hook deposit then force-add tip-required Cursor paths (.cursor/hooks.json + .cursor/hooks/deft-hook-<sha8>.mjs) so they co-travel with the pin (preparePinCandidateCursorDeposit / git add -f bounded set); merge that pin+deposit tip, then re-run:" >&2
|
|
950
|
+
echo " task release:local-update -- $VERSION --checkout $CHECKOUT" >&2
|
|
951
|
+
echo "Expected managed deposit paths include: .grok/hooks/ .cursor/hooks.json .cursor/hooks/deft-hook-<sha8>.mjs .claude/settings.json .codex/ (and related deposit files)." >&2
|
|
952
|
+
echo "Do not auto-commit deposit bytes inside the release flow; do not npm i -g." >&2
|
|
953
|
+
}
|
|
954
|
+
OCC_FILE="$CHECKOUT/.deft/occupancy.json"
|
|
955
|
+
if [ -f "$OCC_FILE" ]; then
|
|
956
|
+
node -e '
|
|
957
|
+
const fs = require("fs");
|
|
958
|
+
const path = process.argv[1];
|
|
959
|
+
const checkout = process.argv[2];
|
|
960
|
+
const raw = fs.readFileSync(path, "utf8");
|
|
961
|
+
let rec;
|
|
962
|
+
try { rec = JSON.parse(raw); } catch { process.exit(0); }
|
|
963
|
+
const sid = String(rec.session_id || rec.sessionId || "");
|
|
964
|
+
const hb = Date.parse(rec.heartbeat_at || rec.heartbeatAt || "");
|
|
965
|
+
const claimed = Date.parse(rec.claimed_at || rec.claimedAt || "");
|
|
966
|
+
const now = Date.now();
|
|
967
|
+
const TTL = 20 * 60 * 1000;
|
|
968
|
+
const MAX = 24 * 60 * 60 * 1000;
|
|
969
|
+
if (!Number.isFinite(hb) || !Number.isFinite(claimed)) process.exit(0);
|
|
970
|
+
if (now - claimed > MAX || now - hb > TTL) process.exit(0);
|
|
971
|
+
const providers = ["grok", "claude", "cursor", "codex", "openclaw"];
|
|
972
|
+
const rawPresenters = [
|
|
973
|
+
process.env.DEFT_SESSION_ID,
|
|
974
|
+
process.env.GROK_SESSION_ID,
|
|
975
|
+
process.env.CLAUDE_SESSION_ID,
|
|
976
|
+
process.env.CURSOR_SESSION_ID,
|
|
977
|
+
process.env.CODEX_SESSION_ID,
|
|
978
|
+
].filter((v) => typeof v === "string" && v.trim().length > 0).map((v) => v.trim());
|
|
979
|
+
const presenters = new Set(rawPresenters);
|
|
980
|
+
for (const p of rawPresenters) {
|
|
981
|
+
if (p.startsWith("host:")) continue;
|
|
982
|
+
for (const provider of providers) {
|
|
983
|
+
presenters.add("host:" + provider + ":v1:" + Buffer.from(p, "utf8").toString("base64url"));
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
let sidRaw = null;
|
|
987
|
+
const m = /^host:([a-z]+):v1:([A-Za-z0-9_-]+)$/.exec(sid);
|
|
988
|
+
if (m) {
|
|
989
|
+
try { sidRaw = Buffer.from(m[2], "base64url").toString("utf8"); } catch { sidRaw = null; }
|
|
990
|
+
}
|
|
991
|
+
const grants = Array.isArray(rec.grants) ? rec.grants : [];
|
|
992
|
+
const grantIds = grants
|
|
993
|
+
.filter((g) => Date.parse(g.expires_at || g.expiresAt || 0) > now)
|
|
994
|
+
.map((g) => g.session_id || g.sessionId || g.child_session_id || g.childSessionId)
|
|
995
|
+
.filter(Boolean)
|
|
996
|
+
.map(String);
|
|
997
|
+
const admitted = [...presenters].some((p) => p === sid || grantIds.includes(p) || (sidRaw && p === sidRaw));
|
|
998
|
+
if (!admitted && presenters.size > 0) {
|
|
999
|
+
console.error("release:local-update: refuse live foreign occupancy lease on " + checkout + " (occupant=" + sid + ") before any write (#5953)");
|
|
1000
|
+
process.exit(1);
|
|
1001
|
+
}
|
|
1002
|
+
if (!admitted && presenters.size === 0 && sid) {
|
|
1003
|
+
console.error("release:local-update: refuse live occupancy lease on " + checkout + " (occupant=" + sid + "); no presenter session id in env (#5953)");
|
|
1004
|
+
process.exit(1);
|
|
1005
|
+
}
|
|
1006
|
+
' "$OCC_FILE" "$CHECKOUT"
|
|
1007
|
+
fi
|
|
1008
|
+
cd "$CHECKOUT"
|
|
1009
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
1010
|
+
echo "release:local-update: not a git work tree: $CHECKOUT" >&2
|
|
1011
|
+
exit 1
|
|
1012
|
+
fi
|
|
1013
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
1014
|
+
echo "release:local-update: refuse dirty tree at $CHECKOUT" >&2
|
|
1015
|
+
git status --short >&2
|
|
1016
|
+
exit 1
|
|
1017
|
+
fi
|
|
1018
|
+
# #6164: shell parameter expansion strip (zero sed/awk/cut/grep); then git verify.
|
|
1019
|
+
ORIGIN_HEAD="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || true)"
|
|
1020
|
+
DEFAULT_BRANCH="${ORIGIN_HEAD#refs/remotes/origin/}"
|
|
1021
|
+
if [ -z "$DEFAULT_BRANCH" ] || [ "$DEFAULT_BRANCH" = "$ORIGIN_HEAD" ]; then
|
|
1022
|
+
DEFAULT_BRANCH=master
|
|
1023
|
+
fi
|
|
1024
|
+
if ! git rev-parse --verify --quiet "refs/remotes/origin/$DEFAULT_BRANCH" >/dev/null; then
|
|
1025
|
+
echo "release:local-update: refuse; cannot verify refs/remotes/origin/$DEFAULT_BRANCH; run: git remote set-head origin -a" >&2
|
|
1026
|
+
exit 1
|
|
1027
|
+
fi
|
|
1028
|
+
CURRENT="$(git rev-parse --abbrev-ref HEAD)"
|
|
1029
|
+
if [ "$CURRENT" != "$DEFAULT_BRANCH" ]; then
|
|
1030
|
+
echo "release:local-update: refuse; checkout must be on default branch $DEFAULT_BRANCH (on $CURRENT)" >&2
|
|
1031
|
+
exit 1
|
|
1032
|
+
fi
|
|
1033
|
+
echo "release:local-update: ff-only pull on $DEFAULT_BRANCH at $CHECKOUT"
|
|
1034
|
+
git pull --ff-only
|
|
1035
|
+
# #6164: unconditional dependency-free AgeExclude gate (exact list-item; fail closed; no soft-skip).
|
|
1036
|
+
node -e '
|
|
1037
|
+
const fs = require("fs");
|
|
1038
|
+
const version = process.argv[1] || "";
|
|
1039
|
+
const want = "@deftai/directive-runtime@" + version;
|
|
1040
|
+
let text;
|
|
1041
|
+
try {
|
|
1042
|
+
text = fs.readFileSync("pnpm-workspace.yaml", "utf8");
|
|
1043
|
+
} catch (err) {
|
|
1044
|
+
const detail = err && err.message ? err.message : String(err);
|
|
1045
|
+
console.error("release:local-update: AgeExclude cannot read pnpm-workspace.yaml before frozen install (#6164): " + detail);
|
|
1046
|
+
process.exit(1);
|
|
1047
|
+
}
|
|
1048
|
+
const lines = text.split(/\r?\n/);
|
|
1049
|
+
const KEY_RE = /^(\s*)minimumReleaseAgeExclude:\s*(#.*)?$/;
|
|
1050
|
+
const ITEM_RE = /^(\s*)-\s+(.*)$/;
|
|
1051
|
+
const keyIdx = lines.findIndex((l) => KEY_RE.test(l));
|
|
1052
|
+
if (keyIdx < 0) process.exit(0);
|
|
1053
|
+
const keyLine = lines[keyIdx];
|
|
1054
|
+
const keyIndent = keyLine.length - keyLine.trimStart().length;
|
|
1055
|
+
const itemValue = (raw) => {
|
|
1056
|
+
let v = String(raw || "").trim();
|
|
1057
|
+
const SQ = String.fromCharCode(39);
|
|
1058
|
+
const DQ = String.fromCharCode(34);
|
|
1059
|
+
if (v.startsWith(SQ) || v.startsWith(DQ)) {
|
|
1060
|
+
const q = v[0];
|
|
1061
|
+
const end = v.indexOf(q, 1);
|
|
1062
|
+
return end > 0 ? v.slice(1, end) : v;
|
|
1063
|
+
}
|
|
1064
|
+
const hash = v.search(/\s#/);
|
|
1065
|
+
if (hash >= 0) v = v.slice(0, hash);
|
|
1066
|
+
return v.trim();
|
|
1067
|
+
};
|
|
1068
|
+
let found = false;
|
|
1069
|
+
for (let i = keyIdx + 1; i < lines.length; i++) {
|
|
1070
|
+
const line = lines[i];
|
|
1071
|
+
const trimmed = line.trim();
|
|
1072
|
+
if (trimmed === "" || trimmed.startsWith("#")) continue;
|
|
1073
|
+
const m = ITEM_RE.exec(line);
|
|
1074
|
+
const indent = line.length - line.trimStart().length;
|
|
1075
|
+
if (m === null || indent < keyIndent) break;
|
|
1076
|
+
if (itemValue(m[2]) === want) { found = true; break; }
|
|
1077
|
+
}
|
|
1078
|
+
if (!found) {
|
|
1079
|
+
console.error("release:local-update: AgeExclude missing " + want + " before frozen install (#5953 footnote / #6164)");
|
|
1080
|
+
process.exit(1);
|
|
1081
|
+
}
|
|
1082
|
+
' "$VERSION"
|
|
1083
|
+
echo "release:local-update: pnpm install --frozen-lockfile"
|
|
1084
|
+
pnpm install --frozen-lockfile
|
|
1085
|
+
PIN_PKG="$(node -e 'const fs=require("fs"); const p=JSON.parse(fs.readFileSync("package.json","utf8")); const v=(p.dependencies||{})["@deftai/directive-runtime"]||(p.devDependencies||{})["@deftai/directive-runtime"]||""; console.log(String(v).replace(/^[^0-9]*/, ""));')"
|
|
1086
|
+
INST_PKG="$(node -e 'const fs=require("fs"); const p=JSON.parse(fs.readFileSync("node_modules/@deftai/directive-runtime/package.json","utf8")); console.log(p.version);')"
|
|
1087
|
+
if [ "$PIN_PKG" != "$VERSION" ] || [ "$INST_PKG" != "$VERSION" ]; then
|
|
1088
|
+
echo "release:local-update: tip-pin-equals-released FAILED; want $VERSION; package.json pin=$PIN_PKG installed=$INST_PKG" >&2
|
|
1089
|
+
exit 1
|
|
1090
|
+
fi
|
|
1091
|
+
echo "release:local-update: tip-pin-equals-released ok ($VERSION)"
|
|
1092
|
+
RUNTIME_BIN="node_modules/@deftai/directive-runtime/dist/bin.js"
|
|
1093
|
+
if [ ! -f "$RUNTIME_BIN" ]; then
|
|
1094
|
+
echo "release:local-update: missing checkout runtime bin $RUNTIME_BIN" >&2
|
|
1095
|
+
exit 1
|
|
1096
|
+
fi
|
|
1097
|
+
echo "release:local-update: require version-matched agent-hook deposit already on tip"
|
|
1098
|
+
if ! DEFT_DOCTOR_HOOK_DIAGNOSTIC=1 node "$RUNTIME_BIN" verify:hooks-installed --project-root "$CHECKOUT" --scope=agent; then
|
|
1099
|
+
print_deposit_recovery
|
|
1100
|
+
exit 1
|
|
1101
|
+
fi
|
|
1102
|
+
# #6163 Prefer-A Bound 6772886751: committed-byte HEAD association (no repair/staging).
|
|
1103
|
+
echo "release:local-update: require committed Cursor deposit association on HEAD"
|
|
1104
|
+
if ! node --input-type=module -e '
|
|
1105
|
+
import { pathToFileURL } from "node:url";
|
|
1106
|
+
import { join, resolve } from "node:path";
|
|
1107
|
+
const checkout = process.argv[1];
|
|
1108
|
+
const vendor = join(
|
|
1109
|
+
checkout,
|
|
1110
|
+
"node_modules/@deftai/directive-runtime/vendor/directive-core/dist/init-deposit/agent-hooks.js",
|
|
1111
|
+
);
|
|
1112
|
+
let validate;
|
|
1113
|
+
try {
|
|
1114
|
+
({ validateCursorDepositAssociation: validate } = await import(pathToFileURL(resolve(vendor)).href));
|
|
1115
|
+
} catch (err) {
|
|
1116
|
+
const detail = err && err.message ? err.message : String(err);
|
|
1117
|
+
console.error("release:local-update: cannot load validateCursorDepositAssociation from installed runtime (#6163): " + detail);
|
|
1118
|
+
process.exit(1);
|
|
1119
|
+
}
|
|
1120
|
+
if (typeof validate !== "function") {
|
|
1121
|
+
console.error("release:local-update: installed runtime lacks validateCursorDepositAssociation (#6163); pin must co-travel the Bound helper");
|
|
1122
|
+
process.exit(1);
|
|
1123
|
+
}
|
|
1124
|
+
const result = validate(checkout, { source: "HEAD" });
|
|
1125
|
+
if (!result || result.ok !== true) {
|
|
1126
|
+
console.error("release:local-update: committed Cursor deposit association FAILED on HEAD (#6163)");
|
|
1127
|
+
console.error(result && result.detail ? result.detail : "unknown association failure");
|
|
1128
|
+
process.exit(1);
|
|
1129
|
+
}
|
|
1130
|
+
console.log("release:local-update: committed Cursor deposit association ok (" + result.sha8 + ")");
|
|
1131
|
+
' "$CHECKOUT"; then
|
|
1132
|
+
print_deposit_recovery
|
|
1133
|
+
exit 1
|
|
1134
|
+
fi
|
|
1135
|
+
UPGRADE_BIN=""
|
|
1136
|
+
if [ -x "node_modules/.bin/directive" ]; then
|
|
1137
|
+
UPGRADE_BIN="node_modules/.bin/directive"
|
|
1138
|
+
elif [ -f "node_modules/@deftai/directive/dist/bin.js" ]; then
|
|
1139
|
+
UPGRADE_BIN="node node_modules/@deftai/directive/dist/bin.js"
|
|
1140
|
+
elif command -v directive >/dev/null 2>&1; then
|
|
1141
|
+
UPGRADE_BIN="directive"
|
|
1142
|
+
else
|
|
1143
|
+
echo "release:local-update: cannot resolve directive upgrade binary after frozen install" >&2
|
|
1144
|
+
exit 1
|
|
1145
|
+
fi
|
|
1146
|
+
echo "release:local-update: $UPGRADE_BIN upgrade --target-version $VERSION --yes --root $CHECKOUT"
|
|
1147
|
+
$UPGRADE_BIN upgrade --target-version "$VERSION" --yes --root "$CHECKOUT"
|
|
1148
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
1149
|
+
echo "release:local-update: tracked-file diff after upgrade; closeout non-zero/incomplete (#5953)" >&2
|
|
1150
|
+
git status --short >&2
|
|
1151
|
+
print_deposit_recovery
|
|
1152
|
+
exit 1
|
|
1153
|
+
fi
|
|
1154
|
+
echo "release:local-update: verify:hooks-installed --project-root --scope=all"
|
|
1155
|
+
DEFT_DOCTOR_HOOK_DIAGNOSTIC=1 node "$RUNTIME_BIN" verify:hooks-installed --project-root "$CHECKOUT" --scope=all
|
|
1156
|
+
INST_PKG2="$(node -e 'const fs=require("fs"); const p=JSON.parse(fs.readFileSync("node_modules/@deftai/directive-runtime/package.json","utf8")); console.log(p.version);')"
|
|
1157
|
+
if [ "$INST_PKG2" != "$VERSION" ]; then
|
|
1158
|
+
echo "release:local-update: post-upgrade runtime $INST_PKG2 != $VERSION" >&2
|
|
1159
|
+
exit 1
|
|
1160
|
+
fi
|
|
1161
|
+
echo "release:local-update COMPLETE; checkout=$CHECKOUT version=$INST_PKG2 hooks=verify:hooks-installed --scope=all green"
|
|
1162
|
+
echo "global npm i -g was NOT run (report-only drift remains Phase 7 step 2)."
|
|
1163
|
+
|
|
848
1164
|
|
|
849
1165
|
# ------------------------------------------------------------------
|
|
850
1166
|
# Triage v1 user-facing alias tasks (#845, #913).
|
|
@@ -949,6 +949,7 @@ Every **real** policy write (Phase 2 / Phase 4, and every other `meta/policy-cha
|
|
|
949
949
|
- **On-disk layout changed.** Old: `.deft-cache/issues/<owner>-<repo>/<N>.{json,md}` (flat sidecar). New: `.deft-cache/<source>/<key>/{raw.json,content.md,meta.json}` (per-entry directory; schema-validated meta envelope). `cache:get` validates `meta.json` against `vbrief/schemas/cache-meta.schema.json` on every read so a corrupt or version-incompatible file fails closed.
|
|
950
950
|
- **Audit log UNCHANGED.** `vbrief/.eval/candidates.jsonl` preserves accept / reject / defer / needs-ac / mark-duplicate / reset records across the migration. The Story 3 Tier-2 short-circuit (terminal-decision skip on bulk-* re-runs) operates on the same file.
|
|
951
951
|
- **All other `triage:*` actions UNCHANGED.** `triage:accept` / `triage:reject` / `triage:defer` / `triage:needs-ac` / `triage:mark-duplicate` / `triage:bulk-accept` / `triage:bulk-reject` / `triage:bulk-defer` / `triage:bulk-needs-ac` / `triage:status` / `triage:reset` / `triage:history` / `triage:refresh-active` keep their v0.25.x surface byte-for-byte (13 aliases). The rebind onto `cache:get` is internal. `triage:bootstrap` keeps its v0.25.x command surface but its on-disk output is the new `.deft-cache/<source>/<key>/` per-entry layout (now delegates to `cache:fetch-all`); see the Commands list above.
|
|
952
|
+
- **Gitcrawl fallback semantics no longer apply.** After this cache rebind, the old `docs/gitcrawl-fallback.md` gh-only install/recovery path is withdrawn. Do not follow that doc for v0.26+ triage/cache; use `cache:*` and this migration section instead (#1092).
|
|
952
953
|
|
|
953
954
|
### Rollback
|
|
954
955
|
|
|
@@ -149,6 +149,7 @@ Common commands:
|
|
|
149
149
|
- Bare `evidence` / `disposition` keys are **not** valid (#1620 / Option B #3305). They fail `verify:vbrief-conformance` and are treated as missing by `scope:complete` (no dual-read). Migrate bare keys or narrative-only `Result`/`Verification` workarounds to the namespaced fields above while items are still non-terminal.
|
|
150
150
|
- Already-terminal items (`completed`/`failed`/`cancelled`/…) are not re-checked for typed evidence; pre-marking items complete to skip the gate is unsupported for the typed path.
|
|
151
151
|
- `merge`/`review` alone cannot satisfy smoke/UAT/deploy/observed_behavior criteria (title/Acceptance text or explicit axis).
|
|
152
|
+
- **Delivery identity (#5710):** with an issue origin, the PR must be associated with the issue as of `merged_at` by one of: (a) a unique sole `deft-story: N` mark in the merge-time PR body (PRs that change only briefs and `CHANGELOG.md` are excluded and never count), (b) a closing keyword (`Closes #N`, `owner/repo#N`, or the issue URL) in the merge-time body, or (c) a Connected issue link at `merged_at`. Brief-in-PR-diff still counts. A mark, keyword or link added after merge does not count, and current `closingIssuesReferences` alone is not enough. Basis (a) scans every merged PR within 20 minutes, `graphql.remaining` ≥ 200 and REST core ≥ 100; any gap refuses. With no issue origin, stamp `plan.metadata.productPullRequest` and complete with `--pr <that number> --merge-commit <sha>`; the repository is the `origin` remote. `--non-delivery` refuses when the stamped PR is merged, and refuses when its merge state cannot be read. `xbrief:preflight` prints one note for a code-bearing brief with no issue origin.
|
|
152
153
|
- `task scope:fail -- xbrief/active/<file>.xbrief.json` -- mark running work failed when the scope cannot complete.
|
|
153
154
|
- `task scope:cancel -- <path>` -- move a scope to `cancelled/`.
|
|
154
155
|
- `task scope:restore`, `task scope:block`, `task scope:unblock`, `task scope:demote`, and `task scope:undo:*` -- repair or reverse lifecycle transitions.
|
|
@@ -494,13 +495,14 @@ Cross-link: spawn three postures and deny recoveries live under § Agent-host di
|
|
|
494
495
|
### Mutable ritual (mutation posture)
|
|
495
496
|
|
|
496
497
|
- ! On **mutation** session start, run `deft session:start` (or `task session:start` in framework source) after loading AGENTS.md. Records quick-tier ritual in `.deft/ritual-state.json`: alignment confirmation, branch-policy disclosure, `deft verify:tools` guidance, default-branch sync warnings, and `deft triage:welcome` one-liner. State is worktree- and HEAD-bound; stale after `plan.policy.sessionRitualStalenessHours` hours (default 8). Mutation start also claims the worktree occupancy lease (`.deft/occupancy.json`); see Session routing (#3433).
|
|
497
|
-
- ! **
|
|
498
|
+
- ! **Quiet-default success stdout (#4966):** mutation `session:start` success human output defaults to one trusted go-signal line with stable prefix `[deft session] ready=…` (ready + branch/HEAD + occupancy). Routine dial/host-surface/effort/orientation/ceremony prose is verbose-only via `deft session:start --verbose` or `DEFT_SESSION_VERBOSE=1`. Non-exhaustive always-on allowlist keeps actionable zero-exit exceptions, non-default policy/bypass and human-merge disclosures, finalize-owed unknown/deferred qualifications, and actionable lifecycle/work-claim notices on the quiet path. Fail/deny/steal/non-zero stay loud. Tip `#3286` `--compact` / `DEFT_SESSION_COMPACT` are deprecated as whole-stdout volume controls (no-op for human stdout selection; `--json` / run-summary unchanged). Exit 0 is not the mutation go-signal — render from structured ready/posture/occupancy state.
|
|
499
|
+
- ! **Orientation compression Now (#3286):** mutation cold `session:start` composes `doctor` + #3282 toolchain preflight (and deposit-sha fast-paths for `agents:refresh` / `verify:cache-fresh`) as inline sections with per-section status lines — composition of existing steps, not a new monolith. When the deposit fingerprint (payload + templates + engine) is unchanged, refresh surfaces print one-line `unchanged - sha match` no-ops. Section formatting may still honor `--compact` / `DEFT_SESSION_COMPACT=1` inside the orientation bundle; whole-stdout volume is `#4966` quiet-default / `--verbose`. #2176 read-only default is unchanged. Dual-path Later (orient) stays open until run-summary telemetry shows ritual+gate share ≥ 25% after Now ships (#2899).
|
|
498
500
|
- ! Cold `session:start` does **not** run the live agent-hook probe. Functional readiness belongs to the gated mutation path so cold ceremony retains the #2990/#2991 latency profile.
|
|
499
501
|
- ! **Hot path latency (#2991):** by default, mutation `session:start` does **not** block ritual-state write on optional network. It skips the npm release-availability probe and triage cache empty-hydrate / self-heal (`ensureTriageCacheHydrated` / `maybeSelfHealCache`). Targets (operator-facing, not CI-hard): warm hot path typically under a few seconds once tools are on PATH; cold path dominated by local `verify:tools` and git, usually well under ~30s when optional network is off. Empty-cache GitHub fetch-all and npm `view` previously accounted for multi-minute hangs in the WWYSYDH pilot — those stay off the critical path unless opted in.
|
|
500
502
|
- ! **Cold vs re-arm ceremony tiers (#2992):** default `session:start` is the **cold** (full) path. After age staleness or compact re-arm (#2113) on the **same worktree** with continuous HEAD and previously-passing quick steps, prefer `deft session:start --rearm` (alias `--tier=rearm`) to refresh the ritual clock + HEAD/worktree bind without `verify:tools`, triage welcome, release probe, or staleness tickler. Full cold remains required for missing/invalid state, worktree change, discontinuous HEAD, first install, or failed/missing quick steps. Compact marks `rearm_needed`; PreToolUse denial and inspect/verify messages prefer re-arm recovery when cold is unnecessary.
|
|
501
503
|
- ? Opt into optional network: `deft session:start --with-network` or `DEFT_SESSION_START_NETWORK=1`. When enabled, the bounded release-availability probe runs against the public npm registry (skips framework source checkouts, non-release pins, and `DEFT_NO_NETWORK=1`; identical latest-version notices throttle for 24 hours in `xbrief/.triage-cache/release-availability-state.json`). Default-mode triage welcome then also hydrates/self-heals the triage cache. This is separate from `deft doctor`, whose bare and gated invocations remain offline by default (#2182). Refs #1692 / #2991. Re-arm never runs optional network.
|
|
502
504
|
- ~ `session:start --json` includes `steps[]` with `name` + `duration_ms` for major phases (`alignment`, `branch_policy`, `verify_tools`, `triage_welcome`, `release_probe`, `ritual_write`), plus total `duration_ms`, `optional_network`, and `ceremony_tier` (`cold` | `rearm`). Skipped optional steps report `skipped: true` and `duration_ms: 0`. Use this for attribution when investigating ceremony wall-clock.
|
|
503
|
-
- ~ **Process-cost events (#2994 / #3508):** on mutation `session:start` completion (cold or re-arm), Directive appends a local `session:start` behavioral event to `.deft-cache/events.jsonl` with `ceremony_tier`, `duration_ms`, `exit_code`, and optional `steps[]` (same labels as `--json`). Mutation `session:start` also
|
|
505
|
+
- ~ **Process-cost events (#2994 / #3508):** on mutation `session:start` completion (cold or re-arm), Directive appends a local `session:start` behavioral event to `.deft-cache/events.jsonl` with `ceremony_tier`, `duration_ms`, `exit_code`, and optional `steps[]` (same labels as `--json`). Mutation `session:start` also emits one operator-visible `ceremony <tier> <ms>` line on the verbose human path (`--verbose` / `DEFT_SESSION_VERBOSE`; quiet-default hides it per #4966). When PreToolUse denies for `ritual-not-ready`, a local `session:ritual-blocked` event records `tool_name`, `code`, and optional `recovery_tier` / `detail`. Always-on best-effort (never blocks ceremony or deny path); not gated on `valueFeedback`; **no remote upload** (Product Insights #2603 is a separate opt-in). Pull the rollup with `task value:show` (composed reader; CLI process time, not agent-turn wall clock). See § Process-cost events below. ⊗ Do not use the printed CLI duration as #3286 Later graduation input.
|
|
504
506
|
- ~ At safe idle points (clean tree, no in-flight story), mutation session start and `deft scope:complete` may also run the staleness tickler: an interactive, consent-based offer to upgrade Directive (`npm i -g @deftai/directive@latest`) and/or migrate xBRIEF (`deft migrate:xbrief`). Escalation tiers, snooze windows, and opt-out live under `plan.policy.stalenessTickler` — inspect with `deft policy:show --field=stalenessTickler`. State persists in `xbrief/.triage-cache/staleness-tickler-state.json`. Skips framework source checkouts, dirty trees, CI/headless (`DEFT_SESSION_RITUAL_SKIP=1`), and typed opt-out. Refs #2488 / #2489.
|
|
505
507
|
- ! Before any code-writing tool call or `start_agent` implementation dispatch, run `deft verify:session-ritual -- --tier=gated`. Gated tier fails closed unless quick-tier state is fresh; lazily records the non-deferrable `agent_hooks` readiness gate plus `deft doctor` and `task verify:cache-fresh` entrypoints. Agent-hook correctness is independent of doctor warnings and throttling. Step 0 of the pre-`start_agent` gate stack.
|
|
506
508
|
- ! **One-shot recovery (#2993 / #3100 / #4399):** when PreToolUse denies writes for a stale/missing gated ritual, run `deft session:ready` (or `task session:ready`). It composes `session:start` (only when quick-tier is not green) + `verify:session-ritual -- --tier=gated` with check-class `cache_fresh` (age + live drift, no `--skip-drift-probe`) + `cache fetch-all --force` when `cache_fresh` is the remaining blocker, then re-verifies. Skip-drift ritual argv is not the ready bar — that is the `task check` / FRAMEWORK_CHECK_GATES evaluate, so stale-by-drift can still fire fetch-all. Even when gated inspect is already fresh, the fast path forces one live `agent_hooks` check and the same check-class `cache_fresh`; it still avoids unnecessary fetch-all when that evaluate is green. Flags: `--json`, `--repo OWNER/NAME`, `--with-network` (forwarded to session:start). Prefer this over juggling the multi-step recovery sequence under hook pressure.
|
|
@@ -550,7 +552,7 @@ Local ceremony cost signal for WWYSYDH / weekly process rollups. Emits to `.deft
|
|
|
550
552
|
| PreToolUse ritual deny | `session:ritual-blocked` | Hook blocks write/spawn because gated ritual is not ready | `tool_name`, `code=ritual-not-ready`, `recovery_tier` (`cold`\|`rearm`) |
|
|
551
553
|
| Per-step wall-clock | (field on `session:start`) | Same emit as session start | `steps[].name` + `steps[].duration_ms` (`alignment`, `scm_readiness`, `branch_policy`, `verify_tools`, `triage_welcome`, `release_probe`, `ritual_write`) |
|
|
552
554
|
|
|
553
|
-
CLI mirror (no JSONL required): `deft session:start --json` already exposes the same `steps` / `duration_ms` / `ceremony_tier` fields for one-shot inspection. Human mutation output adds one `ceremony <tier> <ms>` line
|
|
555
|
+
CLI mirror (no JSONL required): `deft session:start --json` already exposes the same `steps` / `duration_ms` / `ceremony_tier` fields for one-shot inspection. Human mutation output adds one `ceremony <tier> <ms>` line on the verbose path (#3508 / #4966).
|
|
554
556
|
|
|
555
557
|
Composed reader (no new verb): `task value:show` / `deft value:show` prints last cold vs re-arm duration, last per-step breakdown, blocked-ritual count, and recovery-tier distribution from the same ledger. This is **CLI process time**, not agent-turn wall clock (#3500). ⊗ Do not feed the printed CLI duration into #3286 Later graduation.
|
|
556
558
|
|
|
@@ -65,7 +65,7 @@ Record `arc-mode: no-ingest` or `arc-mode: checkout` on the Stop 1 write-back. `
|
|
|
65
65
|
- ! Parent-unclaimed is its own MUST: `session:start --read-only`, or an explicit occupancy release if a mutation lease is already held. Dest create does not clear occupancy.
|
|
66
66
|
- ! Recognition of `no-ingest` happens before mutation initialization. Refuse github-only when mutation `session:start` has already occurred, unless the lease is released first.
|
|
67
67
|
- ! Posting path that survives a foreign lease: `gh issue comment --body-file -` (stdin). Least-authority envelope: bounded GitHub reads and one comment post.
|
|
68
|
-
- ! Parent fetches, then creates or verifies one dest at origin/<default> tip (`ensureArcDest`). dispatch-sha equals that tip. Against-implementation dest is the fetched PR head SHA, recorded on Stop 1. ⊗ Pin dest to local HEAD.
|
|
68
|
+
- ! Parent fetches, then creates or verifies one dest at origin/<default> tip via the sanctioned pin-bin verb `deft design-critique:ensure-arc-dest` (library `ensureArcDest`; guarded-prep default, or explicit `process-only-no-install`). When guarded-prep is selected, success requires the outer-visible runtime pin. dispatch-sha equals that tip. Against-implementation dest is the fetched PR head SHA, recorded on Stop 1. ⊗ Pin dest to local HEAD. ⊗ Treat gitignored `packages/core/dist` as SoT for `ensureArcDest` on framework-source.
|
|
69
69
|
- ! N>1 process-only critics share that dest with cwd-without-occupy. They are not swarm Phase 2 and not a #4066 mutating worker. Unique dest-lock stays for implement-class. Skip class is a host-visible Grok stdin marker (`subagent_type` `plan` or `process_only`), not dest-path. That marker is the process-only skip class, not an implementation-gate bypass: implement-class never sets `process_only`. ⊗ Skip #2885 on destProven. Keep #4066 primary-path deny. ⊗ Pin dest / process_only skip-class rules into `templates/agents-entry.md`.
|
|
70
70
|
- ! Pin reads to `git show <dispatch-sha>:` against the recorded SHA. ⊗ A moving branch ref.
|
|
71
71
|
- ! Before panel-deposit on a process-only dest, record a closed `verification-path:` line that either (a) names the read-only pin-read path (`git show <dispatch-sha>:`, dest cwd-without-occupy for on-pin file reads), or (b) records a provisioned runnable path when a specific check requires executing fixtures/tests. Default to (a). Keep N≥3 launch-probe (`evaluateN3LaunchProbe`) as launchability, separate from method-verification. `verificationPathRecordLine` / `evaluateVerificationPathBeforePanelDeposit` are the fixtures. ⊗ Mandate full install-on-dest for every panel.
|
|
@@ -195,6 +195,12 @@ OS-temp dests and commands with no recognized dest (`git status`,
|
|
|
195
195
|
remains **escape** polarity (in-tree dest whose realpath leaves the tree) and is
|
|
196
196
|
not this check. The hook still runs before the shell, so a link created between
|
|
197
197
|
check and write is TOCTOU.
|
|
198
|
+
- **Kill-switch / permanent opt-out plant (#6136):** Shell write reissue checks
|
|
199
|
+
`.deft-directive-disable` / `.no-deft-directive` basenames **before** the
|
|
200
|
+
`isInRepoShellWritePath` skip, so an out-of-tree plant cannot fail-open. Agent
|
|
201
|
+
Write/Edit/Shell of those basenames is always-on deny without a human-origin
|
|
202
|
+
settings grant (docs: `deft-directive-disable.md`). General protected-target /
|
|
203
|
+
out-of-tree floor work stays on #6138; deny wording on #6139.
|
|
198
204
|
|
|
199
205
|
Fail-open at this predicate is the bound posture (#3997). Inverting it to
|
|
200
206
|
fail-closed on dests the parser cannot prove external is that issue's refuted
|
|
@@ -82,11 +82,11 @@ rm .deft-directive-disable
|
|
|
82
82
|
# Start a NEW agent session
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
## Agent self-serve ban
|
|
85
|
+
## Agent self-serve ban (always-on, grant-gated) (#3186 / #6136)
|
|
86
86
|
|
|
87
|
-
Operators plant and remove this flag **outside** an agent session (or with a prior human-origin grant).
|
|
87
|
+
Operators plant and remove this flag **outside** an agent session (or with a prior human-origin grant covering **settings**). PreToolUse **always** denies agent Write / Edit / Shell that creates or renames-to `.deft-directive-disable` (and permanent opt-out `.no-deft-directive`) without that grant — not only under active UAT. Shell write reissue checks the protected basename **before** skipping out-of-tree dests, so a plant outside the repo tree cannot fail-open. Agents must not self-serve the kill-switch to bypass Write / push / PR / merge gates.
|
|
88
88
|
|
|
89
|
-
Related: `policy:allow-bot-merge`, `policy:allow-direct-commits`, and `policy:disable-directive` (peers) are
|
|
89
|
+
Related: `policy:allow-bot-merge`, `policy:allow-direct-commits`, and `policy:disable-directive` (peers) are settings under UAT and require a human grant.
|
|
90
90
|
|
|
91
91
|
## Non-goals (v1)
|
|
92
92
|
|