@mjasnikovs/pi-task 0.38.29 → 0.38.31
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/dist/config/config.d.ts +70 -70
- package/dist/config/config.js +26 -35
- package/dist/config/extension-list.d.ts +6 -5
- package/dist/config/extension-list.js +3 -2
- package/dist/config/reasoning-args.d.ts +9 -7
- package/dist/config/reasoning-args.js +12 -10
- package/dist/config/reasoning.d.ts +44 -105
- package/dist/config/reasoning.js +27 -704
- package/dist/config/register.d.ts +34 -48
- package/dist/config/register.js +41 -51
- package/dist/config/tool-list.d.ts +16 -16
- package/dist/config/tool-list.js +1 -1
- package/dist/index.js +2 -0
- package/dist/remote/bridge.d.ts +19 -10
- package/dist/remote/bridge.js +3 -2
- package/dist/remote/broadcast.js +3 -1
- package/dist/remote/events.js +12 -11
- package/dist/remote/history.d.ts +1 -1
- package/dist/remote/protocol.d.ts +6 -3
- package/dist/remote/protocol.js +2 -1
- package/dist/remote/push.d.ts +16 -16
- package/dist/remote/push.js +27 -27
- package/dist/remote/register.d.ts +3 -3
- package/dist/remote/register.js +17 -19
- package/dist/remote/server.d.ts +9 -8
- package/dist/remote/server.js +15 -14
- package/dist/remote/session-state.d.ts +5 -4
- package/dist/remote/session-state.js +8 -5
- package/dist/remote/sw.d.ts +7 -6
- package/dist/remote/sw.js +7 -6
- package/dist/remote/tailscale.d.ts +4 -2
- package/dist/remote/tailscale.js +4 -2
- package/dist/remote/ui-highlight.js +6 -5
- package/dist/remote/ui-render.js +4 -4
- package/dist/remote/ui-script.js +24 -24
- package/dist/remote/ui-styles.d.ts +1 -1
- package/dist/remote/ui-styles.js +10 -13
- package/dist/remote/ui-tools.js +9 -6
- package/dist/shared/child-extensions.d.ts +29 -17
- package/dist/shared/child-extensions.js +29 -17
- package/dist/shared/child-output.d.ts +30 -24
- package/dist/shared/child-output.js +25 -17
- package/dist/shared/child-process.d.ts +47 -40
- package/dist/shared/child-process.js +50 -59
- package/dist/shared/command-watchdog.d.ts +85 -16
- package/dist/shared/command-watchdog.js +115 -21
- package/dist/shared/fs-text.d.ts +16 -10
- package/dist/shared/fs-text.js +16 -10
- package/dist/shared/git-runner.d.ts +25 -25
- package/dist/shared/git-runner.js +25 -25
- package/dist/shared/leaked-tool-call.d.ts +17 -11
- package/dist/shared/leaked-tool-call.js +23 -15
- package/dist/shared/model-endpoint.d.ts +29 -16
- package/dist/shared/model-endpoint.js +33 -21
- package/dist/shared/pi-invocation.d.ts +7 -4
- package/dist/shared/pi-invocation.js +12 -7
- package/dist/shared/pkg-version.d.ts +13 -5
- package/dist/shared/pkg-version.js +13 -5
- package/dist/shared/reasoning-capability.d.ts +35 -24
- package/dist/shared/reasoning-capability.js +35 -24
- package/dist/shared/stream-watchdog.d.ts +60 -44
- package/dist/shared/stream-watchdog.js +62 -45
- package/dist/task/accept-debt.d.ts +41 -43
- package/dist/task/accept-debt.js +73 -65
- package/dist/task/api-synthesis.d.ts +24 -21
- package/dist/task/api-synthesis.js +32 -26
- package/dist/task/apis-contract.d.ts +32 -64
- package/dist/task/apis-contract.js +32 -64
- package/dist/task/artifact-closure.d.ts +27 -13
- package/dist/task/artifact-closure.js +95 -67
- package/dist/task/auto-commit.d.ts +46 -35
- package/dist/task/auto-commit.js +51 -38
- package/dist/task/auto-io.d.ts +45 -25
- package/dist/task/auto-io.js +57 -29
- package/dist/task/auto-orchestrator.d.ts +26 -24
- package/dist/task/auto-orchestrator.js +192 -165
- package/dist/task/auto-prompts.d.ts +36 -24
- package/dist/task/auto-prompts.js +40 -26
- package/dist/task/autofix-ledger.d.ts +27 -25
- package/dist/task/autofix-ledger.js +29 -26
- package/dist/task/batch-test-task.d.ts +20 -12
- package/dist/task/batch-test-task.js +67 -60
- package/dist/task/boot-probe.d.ts +60 -44
- package/dist/task/boot-probe.js +91 -72
- package/dist/task/cancel-input.d.ts +30 -16
- package/dist/task/cancel-input.js +20 -11
- package/dist/task/cancel-points.d.ts +27 -20
- package/dist/task/cancel-points.js +30 -22
- package/dist/task/child-runner.d.ts +124 -55
- package/dist/task/child-runner.js +298 -90
- package/dist/task/child-status.d.ts +23 -16
- package/dist/task/child-status.js +23 -16
- package/dist/task/clamp-output.js +12 -5
- package/dist/task/command-run.d.ts +31 -28
- package/dist/task/command-run.js +44 -35
- package/dist/task/command-shrink.d.ts +25 -18
- package/dist/task/command-shrink.js +37 -31
- package/dist/task/command-watchdog.d.ts +9 -6
- package/dist/task/command-watchdog.js +21 -15
- package/dist/task/context-attribution.d.ts +34 -26
- package/dist/task/context-attribution.js +34 -26
- package/dist/task/context-silence.d.ts +39 -29
- package/dist/task/context-silence.js +35 -25
- package/dist/task/context-usage.d.ts +16 -9
- package/dist/task/context-usage.js +16 -9
- package/dist/task/contracts.d.ts +8 -4
- package/dist/task/contracts.js +25 -17
- package/dist/task/coverage-loop.d.ts +22 -18
- package/dist/task/coverage-loop.js +35 -30
- package/dist/task/critique-probes.d.ts +13 -14
- package/dist/task/critique-probes.js +50 -39
- package/dist/task/debug-log.d.ts +13 -5
- package/dist/task/debug-log.js +32 -20
- package/dist/task/decompose-fidelity.d.ts +11 -9
- package/dist/task/decompose-fidelity.js +38 -33
- package/dist/task/decompose-granularity.d.ts +41 -38
- package/dist/task/decompose-granularity.js +41 -38
- package/dist/task/deep-render-check.d.ts +22 -14
- package/dist/task/deep-render-check.js +40 -31
- package/dist/task/dropped-input.d.ts +12 -7
- package/dist/task/dropped-input.js +5 -2
- package/dist/task/enforce-attribution.d.ts +38 -47
- package/dist/task/enforce-attribution.js +46 -52
- package/dist/task/enforce-guidelines.d.ts +31 -20
- package/dist/task/enforce-guidelines.js +32 -21
- package/dist/task/enrichment.d.ts +7 -2
- package/dist/task/enrichment.js +26 -14
- package/dist/task/env-notes.d.ts +16 -7
- package/dist/task/env-notes.js +48 -31
- package/dist/task/env-template-closure.d.ts +4 -4
- package/dist/task/env-template-closure.js +42 -34
- package/dist/task/external-context.d.ts +28 -21
- package/dist/task/external-context.js +17 -12
- package/dist/task/failure-classifier.d.ts +4 -5
- package/dist/task/failure-classifier.js +30 -8
- package/dist/task/file-inventory.d.ts +15 -11
- package/dist/task/file-inventory.js +25 -22
- package/dist/task/final-gate-fix.d.ts +74 -86
- package/dist/task/final-gate-fix.js +97 -116
- package/dist/task/final-gate-progress.d.ts +29 -46
- package/dist/task/final-gate-progress.js +40 -51
- package/dist/task/final-gate.d.ts +64 -97
- package/dist/task/final-gate.js +192 -199
- package/dist/task/fix-child.d.ts +21 -27
- package/dist/task/fix-child.js +21 -27
- package/dist/task/foreign-path.d.ts +6 -5
- package/dist/task/foreign-path.js +0 -0
- package/dist/task/frozen-conflict.d.ts +9 -10
- package/dist/task/frozen-conflict.js +61 -64
- package/dist/task/frozen-path-guard.d.ts +35 -14
- package/dist/task/frozen-path-guard.js +56 -39
- package/dist/task/gate-child.d.ts +27 -28
- package/dist/task/gate-child.js +36 -35
- package/dist/task/gate-deps.d.ts +34 -27
- package/dist/task/gate-deps.js +169 -159
- package/dist/task/gate-tally.d.ts +77 -80
- package/dist/task/gate-tally.js +65 -68
- package/dist/task/git-state-guard.d.ts +15 -11
- package/dist/task/git-state-guard.js +76 -66
- package/dist/task/impl-widget.d.ts +25 -16
- package/dist/task/impl-widget.js +27 -17
- package/dist/task/implementation-guards.d.ts +26 -0
- package/dist/task/implementation-guards.js +177 -0
- package/dist/task/implementation-thinking.d.ts +33 -31
- package/dist/task/implementation-thinking.js +5 -6
- package/dist/task/implementation-turn.d.ts +39 -31
- package/dist/task/implementation-turn.js +41 -28
- package/dist/task/inline-markdown.d.ts +20 -7
- package/dist/task/inline-markdown.js +15 -6
- package/dist/task/launch-config-gap.js +25 -39
- package/dist/task/launch-contract.d.ts +18 -21
- package/dist/task/launch-contract.js +28 -30
- package/dist/task/launch-manifest.d.ts +6 -2
- package/dist/task/launch-manifest.js +35 -34
- package/dist/task/ledger.js +16 -14
- package/dist/task/lint-fix.d.ts +6 -8
- package/dist/task/lint-fix.js +67 -69
- package/dist/task/loop-detector.d.ts +27 -8
- package/dist/task/loop-detector.js +38 -14
- package/dist/task/mid-run-input.d.ts +17 -15
- package/dist/task/mid-run-input.js +17 -15
- package/dist/task/orchestrator.d.ts +24 -28
- package/dist/task/orchestrator.js +89 -66
- package/dist/task/orientation.d.ts +18 -23
- package/dist/task/orientation.js +24 -31
- package/dist/task/owned-freeze-conflict.d.ts +21 -20
- package/dist/task/owned-freeze-conflict.js +52 -85
- package/dist/task/owned-freeze-reassign.d.ts +40 -60
- package/dist/task/owned-freeze-reassign.js +41 -61
- package/dist/task/parsers.d.ts +4 -2
- package/dist/task/parsers.js +4 -4
- package/dist/task/phases.d.ts +41 -48
- package/dist/task/phases.js +196 -252
- package/dist/task/plan-io.d.ts +6 -7
- package/dist/task/plan-io.js +6 -7
- package/dist/task/plan-orchestrator.d.ts +10 -8
- package/dist/task/plan-orchestrator.js +14 -10
- package/dist/task/plan-prompts.d.ts +6 -5
- package/dist/task/plan-prompts.js +6 -5
- package/dist/task/plan-readonly.d.ts +4 -5
- package/dist/task/plan-readonly.js +4 -5
- package/dist/task/plan-rounds.d.ts +17 -29
- package/dist/task/plan-rounds.js +21 -34
- package/dist/task/plan-session.d.ts +58 -72
- package/dist/task/plan-session.js +61 -83
- package/dist/task/probe-gaming.d.ts +28 -27
- package/dist/task/probe-gaming.js +0 -0
- package/dist/task/prohibition-probe.d.ts +14 -16
- package/dist/task/prompts.d.ts +3 -4
- package/dist/task/prompts.js +17 -26
- package/dist/task/qa-transcript.d.ts +15 -22
- package/dist/task/qa-transcript.js +15 -21
- package/dist/task/question-box.d.ts +17 -13
- package/dist/task/question-box.js +19 -15
- package/dist/task/question-dedup.d.ts +6 -7
- package/dist/task/question-dedup.js +13 -14
- package/dist/task/question-dialog.d.ts +22 -32
- package/dist/task/question-dialog.js +22 -32
- package/dist/task/question-source.d.ts +18 -44
- package/dist/task/question-source.js +22 -51
- package/dist/task/refuted-constraint.d.ts +11 -31
- package/dist/task/refuted-constraint.js +27 -51
- package/dist/task/regenerable-artifacts.d.ts +12 -31
- package/dist/task/regenerable-artifacts.js +12 -31
- package/dist/task/render-check.d.ts +11 -22
- package/dist/task/render-check.js +33 -46
- package/dist/task/repo-health-check.d.ts +10 -14
- package/dist/task/repo-health-check.js +17 -23
- package/dist/task/requirements.d.ts +38 -71
- package/dist/task/requirements.js +78 -126
- package/dist/task/research-fanout-budget.d.ts +51 -88
- package/dist/task/research-fanout-budget.js +51 -88
- package/dist/task/research-worker.d.ts +29 -39
- package/dist/task/research-worker.js +37 -61
- package/dist/task/resume-gap.d.ts +14 -15
- package/dist/task/root-cause-repair.d.ts +9 -9
- package/dist/task/root-cause-repair.js +28 -40
- package/dist/task/run-bracket.d.ts +10 -13
- package/dist/task/run-end.d.ts +12 -22
- package/dist/task/run-end.js +8 -16
- package/dist/task/run-final-gate.d.ts +19 -21
- package/dist/task/run-final-gate.js +62 -80
- package/dist/task/runner-globs.d.ts +12 -13
- package/dist/task/runner-globs.js +12 -13
- package/dist/task/runner-resolve.d.ts +9 -9
- package/dist/task/runner-resolve.js +22 -23
- package/dist/task/script-escape.d.ts +10 -12
- package/dist/task/script-escape.js +13 -14
- package/dist/task/serve-entry.d.ts +1 -1
- package/dist/task/serve-entry.js +22 -25
- package/dist/task/service-blocks.js +4 -2
- package/dist/task/shipped-source.d.ts +11 -29
- package/dist/task/shipped-source.js +11 -29
- package/dist/task/skip-escape.js +10 -14
- package/dist/task/spec-urls.d.ts +26 -65
- package/dist/task/spec-urls.js +26 -65
- package/dist/task/spec-validation.d.ts +17 -20
- package/dist/task/spec-validation.js +17 -20
- package/dist/task/stall-detector.d.ts +23 -30
- package/dist/task/stall-detector.js +23 -30
- package/dist/task/stream-watchdog.d.ts +14 -12
- package/dist/task/stream-watchdog.js +14 -12
- package/dist/task/substitution-probe.d.ts +17 -20
- package/dist/task/substitution-probe.js +17 -20
- package/dist/task/task-gates.d.ts +36 -41
- package/dist/task/task-gates.js +95 -106
- package/dist/task/task-io.d.ts +4 -4
- package/dist/task/task-io.js +4 -4
- package/dist/task/task-parsers.js +4 -3
- package/dist/task/task-provenance.d.ts +2 -2
- package/dist/task/task-provenance.js +11 -13
- package/dist/task/task-types.d.ts +4 -3
- package/dist/task/terminal-outcome.d.ts +14 -16
- package/dist/task/terminal-outcome.js +12 -14
- package/dist/task/test-assembly.d.ts +13 -20
- package/dist/task/test-assembly.js +13 -20
- package/dist/task/timings.d.ts +5 -3
- package/dist/task/timings.js +5 -3
- package/dist/task/title-label.d.ts +9 -4
- package/dist/task/title-label.js +9 -4
- package/dist/task/type-only-answer.d.ts +44 -52
- package/dist/task/type-only-answer.js +44 -52
- package/dist/task/unfailable-command.d.ts +18 -24
- package/dist/task/unfailable-command.js +21 -27
- package/dist/task/unknown-routing.d.ts +10 -4
- package/dist/task/unknown-routing.js +10 -4
- package/dist/task/user-directives.d.ts +5 -8
- package/dist/task/user-directives.js +5 -8
- package/dist/task/verify-quality.d.ts +18 -22
- package/dist/task/verify-quality.js +45 -46
- package/dist/task/verify-reconcile.d.ts +15 -10
- package/dist/task/verify-reconcile.js +45 -43
- package/dist/task/verify-resolution.d.ts +24 -20
- package/dist/task/verify-resolution.js +51 -50
- package/dist/task/verify-work.d.ts +59 -66
- package/dist/task/verify-work.js +101 -138
- package/dist/task/widget.d.ts +15 -14
- package/dist/task/widget.js +22 -17
- package/dist/task/wiring-claims.d.ts +25 -32
- package/dist/task/wiring-claims.js +30 -35
- package/dist/task/write-guard.d.ts +39 -39
- package/dist/task/write-guard.js +48 -51
- package/dist/task/yolo.d.ts +34 -30
- package/dist/task/yolo.js +42 -37
- package/dist/workers/abstention.d.ts +21 -41
- package/dist/workers/abstention.js +27 -48
- package/dist/workers/brave-search.d.ts +4 -3
- package/dist/workers/brave-search.js +5 -2
- package/dist/workers/brave-warning.d.ts +7 -4
- package/dist/workers/brave-warning.js +19 -7
- package/dist/workers/ddg-search.d.ts +6 -6
- package/dist/workers/ddg-search.js +18 -12
- package/dist/workers/docs-cache.js +5 -2
- package/dist/workers/docs-chunk.d.ts +30 -37
- package/dist/workers/docs-chunk.js +37 -41
- package/dist/workers/docs-core.d.ts +28 -44
- package/dist/workers/docs-core.js +25 -44
- package/dist/workers/docs-index.js +4 -3
- package/dist/workers/docs-lookup.d.ts +15 -22
- package/dist/workers/docs-lookup.js +12 -21
- package/dist/workers/docs-project.d.ts +15 -9
- package/dist/workers/docs-project.js +17 -10
- package/dist/workers/docs-resolve.d.ts +19 -20
- package/dist/workers/docs-resolve.js +35 -32
- package/dist/workers/docs-retrieve.d.ts +5 -6
- package/dist/workers/docs-retrieve.js +18 -15
- package/dist/workers/exa-search.d.ts +9 -6
- package/dist/workers/exa-search.js +23 -12
- package/dist/workers/fetch-core.d.ts +13 -16
- package/dist/workers/fetch-core.js +23 -23
- package/dist/workers/focused-extractor.d.ts +13 -12
- package/dist/workers/focused-extractor.js +27 -19
- package/dist/workers/html-clean.js +24 -14
- package/dist/workers/http-request.d.ts +28 -20
- package/dist/workers/http-request.js +22 -17
- package/dist/workers/npm-version.d.ts +28 -11
- package/dist/workers/npm-version.js +24 -15
- package/dist/workers/phantom-imports.d.ts +15 -12
- package/dist/workers/phantom-imports.js +30 -24
- package/dist/workers/pi-worker-core.d.ts +65 -96
- package/dist/workers/pi-worker-core.js +93 -181
- package/dist/workers/pi-worker-docs.d.ts +24 -19
- package/dist/workers/pi-worker-docs.js +67 -76
- package/dist/workers/pi-worker-fetch.d.ts +7 -3
- package/dist/workers/pi-worker-fetch.js +27 -19
- package/dist/workers/pi-worker-search.js +12 -8
- package/dist/workers/pi-worker.d.ts +9 -4
- package/dist/workers/pi-worker.js +21 -14
- package/dist/workers/reasoning-warning.d.ts +18 -17
- package/dist/workers/reasoning-warning.js +22 -20
- package/dist/workers/research-cache.js +50 -78
- package/dist/workers/search-core.js +7 -5
- package/dist/workers/search-types.d.ts +10 -9
- package/dist/workers/search-types.js +9 -8
- package/dist/workers/session-hint.d.ts +13 -14
- package/dist/workers/session-hint.js +8 -9
- package/dist/workers/shared.d.ts +21 -25
- package/dist/workers/shared.js +0 -0
- package/dist/workers/single-read-extension.d.ts +14 -7
- package/dist/workers/single-read-extension.js +14 -7
- package/dist/workers/single-read-guard.d.ts +27 -30
- package/dist/workers/single-read-guard.js +36 -36
- package/dist/workers/typeonly-log.d.ts +12 -9
- package/dist/workers/typeonly-log.js +29 -33
- package/dist/workers/worker-channels.d.ts +15 -23
- package/dist/workers/worker-channels.js +15 -23
- package/dist/workers/worker-failure.d.ts +38 -46
- package/dist/workers/worker-failure.js +31 -39
- package/dist/workers/worker-kill.d.ts +25 -26
- package/dist/workers/worker-kill.js +16 -19
- package/dist/workers/worker-profiles.d.ts +54 -56
- package/dist/workers/worker-profiles.js +63 -39
- package/package.json +10 -8
package/dist/task/task-gates.js
CHANGED
|
@@ -23,13 +23,12 @@ export const MAX_AUTO_AUTOFIX = 3;
|
|
|
23
23
|
/**
|
|
24
24
|
* The reason an auto-ACCEPT is being written — NAMED, not assumed.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* misstates why a defect shipped
|
|
32
|
-
* reads as an exhausted fixer when nothing was ever attempted.
|
|
26
|
+
* Four disjoint branches reach the terminal auto-ACCEPT, and only ONE of them has
|
|
27
|
+
* spent the autofix budget. An UNOBSERVED FAIL never consults the research; a
|
|
28
|
+
* frozen-blocked one is a contradiction no re-run can resolve; an ACCEPT
|
|
29
|
+
* recommendation can arrive with the budget untouched. A single "autofix budget
|
|
30
|
+
* spent" line would be false on three of the four, and a durable trail that
|
|
31
|
+
* misstates why a defect shipped reads as an exhausted fixer that never tried.
|
|
33
32
|
*/
|
|
34
33
|
export function yoloAcceptReason(c) {
|
|
35
34
|
if (c.isUnobserved)
|
|
@@ -44,7 +43,7 @@ export function yoloAcceptReason(c) {
|
|
|
44
43
|
: `judge recommended ACCEPT (autofix budget ${c.autoFixCount}/${MAX_AUTO_AUTOFIX} already spent)`;
|
|
45
44
|
}
|
|
46
45
|
// The trail-side output ceiling lives in clamp-output.ts, so the render probe's
|
|
47
|
-
// evidence clamps identically
|
|
46
|
+
// evidence clamps identically — one ceiling, one implementation.
|
|
48
47
|
/**
|
|
49
48
|
* Show the boxed two-choice picker after a verify FAIL and return what the user
|
|
50
49
|
* decided. The model-recommended card is placed first so the renderer tints it
|
|
@@ -73,12 +72,10 @@ export async function askVerifyResolution(ctx, title, failReason, rec) {
|
|
|
73
72
|
* recommendation → unattended autofix → picker) until it verifies, is accepted,
|
|
74
73
|
* or terminates.
|
|
75
74
|
*
|
|
76
|
-
* Split
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* why `deps.verify` was driven by an invocation counter whose first return existed
|
|
81
|
-
* only to unlock `mode === 'edit'`.
|
|
75
|
+
* Split from `runGatesForTask` at the single boolean that crosses to the ENFORCE
|
|
76
|
+
* half (`cleanPass`). This loop has four terminal exits and carries the whole
|
|
77
|
+
* negotiation; enforce always falls through. Joined, a test of the enforce
|
|
78
|
+
* differential would have to traverse this entire loop first.
|
|
82
79
|
*/
|
|
83
80
|
export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
84
81
|
let active = ctxIn;
|
|
@@ -107,9 +104,9 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
107
104
|
let autoFixCount = 0;
|
|
108
105
|
// Set when the bounded lint-fix reports the `frozen-path:` rejection: the
|
|
109
106
|
// repo-health FAIL can only be fixed by editing a path THIS task's spec
|
|
110
|
-
// froze
|
|
111
|
-
//
|
|
112
|
-
//
|
|
107
|
+
// froze. An impl re-run happens under the same freeze — rule 4b fails the
|
|
108
|
+
// task if it complies with the linter — so unattended AUTOFIX rounds
|
|
109
|
+
// CANNOT converge and are skipped;
|
|
113
110
|
// the picker is forced with the cross-task contradiction named, and the
|
|
114
111
|
// defect is recorded as a durable debt for the final gate.
|
|
115
112
|
let frozenContradiction = null;
|
|
@@ -202,10 +199,9 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
202
199
|
// AUTOFIX must not bootstrap the full budget from it.
|
|
203
200
|
&& !yoloRescueUsed;
|
|
204
201
|
// YOLO, THE RESCUE BRANCH: the recommendation is ACCEPT, nobody can be
|
|
205
|
-
// asked, and the unattended budget is UNTOUCHED. Accepting here
|
|
206
|
-
// defect having attempted nothing
|
|
207
|
-
//
|
|
208
|
-
// (`0 pass 130 fail` → `121 pass 0 fail`). So spend ONE attempt first.
|
|
202
|
+
// asked, and the unattended budget is UNTOUCHED. Accepting here would
|
|
203
|
+
// ship a defect having attempted nothing, on a judgement the human who
|
|
204
|
+
// would normally weigh it never saw. So spend ONE attempt first.
|
|
209
205
|
// Bounded by construction: one, not MAX_AUTO_AUTOFIX, so an ACCEPT
|
|
210
206
|
// recommendation can never restart a full loop; if it still FAILs the
|
|
211
207
|
// next turn falls through to the same auto-ACCEPT and the same debt.
|
|
@@ -226,8 +222,8 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
226
222
|
if (yoloChoice !== null) {
|
|
227
223
|
choice = yoloChoice;
|
|
228
224
|
// NAME the branch. This line is the durable record of why a defect
|
|
229
|
-
// shipped
|
|
230
|
-
//
|
|
225
|
+
// shipped, and three of the four branches that reach it have spent
|
|
226
|
+
// no budget at all.
|
|
231
227
|
await rec(`resolution: auto-ACCEPTED despite verify FAIL — ${yoloAcceptReason({
|
|
232
228
|
isUnobserved,
|
|
233
229
|
isFrozenBlocked,
|
|
@@ -258,9 +254,9 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
258
254
|
if (!byYolo)
|
|
259
255
|
await rec('resolution: user ACCEPTED the work despite verify FAIL');
|
|
260
256
|
// Durable debt: the human blessed a FAILing artifact as-is, so the
|
|
261
|
-
// defect ships and nothing else
|
|
262
|
-
//
|
|
263
|
-
//
|
|
257
|
+
// defect ships and nothing else in this task revisits it. Record it
|
|
258
|
+
// to the run ledger; the final integration gate re-checks it at run
|
|
259
|
+
// end and surfaces it if still open. Best-effort.
|
|
264
260
|
// The frozen-blocked routing above already recorded this defect (with
|
|
265
261
|
// the contradiction named) — don't double-enter it in the ledger.
|
|
266
262
|
if (!frozenDebtRecorded) {
|
|
@@ -275,13 +271,12 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
275
271
|
}
|
|
276
272
|
}
|
|
277
273
|
// ROOT CAUSE: an accepted FAIL that some OTHER task's file caused is
|
|
278
|
-
// not fixed by accepting it —
|
|
279
|
-
//
|
|
280
|
-
// so the plan actually closes it.
|
|
274
|
+
// not fixed by accepting it — every later task keeps tripping over
|
|
275
|
+
// the same bug. Queue the scoped repair so the plan closes it.
|
|
281
276
|
await routeRootCause(failReason, recOutcome.rationale, 'worktree');
|
|
282
277
|
// Cross-task deletions the verify probe detected ship in the next
|
|
283
278
|
// commit with this ACCEPT — record each as its own durable debt so
|
|
284
|
-
// the final gate re-checks them
|
|
279
|
+
// the final gate re-checks them. Best-effort.
|
|
285
280
|
for (const del of verified.crossTaskDeletions ?? []) {
|
|
286
281
|
try {
|
|
287
282
|
await deps.recordDebt?.(p.cwd, p.taskId, crossTaskDeletionReason(del), 'cross-task-deletion');
|
|
@@ -296,11 +291,10 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
296
291
|
}
|
|
297
292
|
// AUTOFIX: re-run the implementation turn with the failure (and any typed
|
|
298
293
|
// guidance) prepended as a RE-ATTEMPT banner, then re-verify. The
|
|
299
|
-
// recommendation child already LOCATED the defect while deciding
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
// is no researched rationale beyond the failure text itself.
|
|
294
|
+
// recommendation child already LOCATED the defect while deciding, so
|
|
295
|
+
// hand its diagnosis to the re-run rather than making it re-derive the
|
|
296
|
+
// cause from the bare FAIL line. Skipped when there is no researched
|
|
297
|
+
// rationale beyond the failure text itself.
|
|
304
298
|
// Only the picker branch may claim a person chose this: the two
|
|
305
299
|
// unattended branches already recorded themselves one line above, and a
|
|
306
300
|
// trail that says "user chose" when nobody was asked is the same lie the
|
|
@@ -362,8 +356,7 @@ export async function resolveVerifyGate(ctxIn, deps, p, rec, routeRootCause) {
|
|
|
362
356
|
* then decide whether the pass\'s own commit survives.
|
|
363
357
|
*
|
|
364
358
|
* `reVerify` is deliberately NOT `deps.verify`. They answer two different
|
|
365
|
-
* questions — the gate above, and this differential —
|
|
366
|
-
* field the only way to answer them differently was to count invocations.
|
|
359
|
+
* questions — the gate above, and this differential — so they are two fields.
|
|
367
360
|
*
|
|
368
361
|
* Reads `active` and never reassigns it: nothing here can replace the live
|
|
369
362
|
* session, unlike the autofix in the verify half.
|
|
@@ -378,19 +371,19 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
378
371
|
const mode = verifyCleanPass ? 'edit' : 'flag';
|
|
379
372
|
// BASELINE repo health, captured BEFORE the edit pass touches the tree, so the
|
|
380
373
|
// pre-commit gate below is DIFFERENTIAL: it can tell an enforce-CAUSED
|
|
381
|
-
// regression (was clean, now fails) from a repo that was ALREADY unhealthy
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
374
|
+
// regression (was clean, now fails) from a repo that was ALREADY unhealthy.
|
|
375
|
+
// Without the baseline, a lint that was already crashing before the pass ran
|
|
376
|
+
// makes every enforce pass look like the cause, and its good work is
|
|
377
|
+
// discarded for a fault it did not commit. Only meaningful in edit mode (flag
|
|
385
378
|
// makes no edits); the task's work is already committed so this reflects the
|
|
386
379
|
// committed state the pass is about to build on.
|
|
387
380
|
const healthBefore = mode === 'edit' && deps.repoHealth ?
|
|
388
381
|
await deps.repoHealth(active, p.cwd, p.title)
|
|
389
382
|
: undefined;
|
|
390
383
|
const verdict = await deps.enforce(active, p.cwd, p.title, mode);
|
|
391
|
-
// FROZEN-PATH WRITE-DENY (mechanical, not prompt —
|
|
392
|
-
// instruction is
|
|
393
|
-
//
|
|
384
|
+
// FROZEN-PATH WRITE-DENY (mechanical, not prompt — a "MUST NOT edit"
|
|
385
|
+
// instruction is not reliable): the enforce EDIT pass runs read,edit and can
|
|
386
|
+
// mutate a path the spec froze.
|
|
394
387
|
// Before its edits are inspected/committed below, restore any frozen path it
|
|
395
388
|
// touched to the committed task state, so the violating write cannot land in
|
|
396
389
|
// the ENFORCE GUIDELINES commit regardless of what the model intended. The
|
|
@@ -417,20 +410,21 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
417
410
|
if (!verdict.ok) {
|
|
418
411
|
active.ui.notify(`${p.tag}: guideline ${mode === 'edit' ? 'enforcement' : 'review'} on "${p.title}" — ${verdict.reason ?? 'not clean'} — continuing.`, 'warning');
|
|
419
412
|
}
|
|
420
|
-
// PRE-COMMIT health gate on enforce edits:
|
|
421
|
-
//
|
|
422
|
-
// revert
|
|
423
|
-
// and discards the bad edits outright. Only runs
|
|
413
|
+
// PRE-COMMIT health gate on enforce edits: an edit pass that breaks the
|
|
414
|
+
// repo's own lint would otherwise burn a commit, a model re-verify and a
|
|
415
|
+
// revert before anything noticed. A deterministic static check BEFORE
|
|
416
|
+
// committing skips that cycle and discards the bad edits outright. Only runs
|
|
417
|
+
// when the tree is actually
|
|
424
418
|
// dirty (or dirtiness is unknowable); the differential guard below still
|
|
425
419
|
// catches behavioral regressions the static check cannot see.
|
|
426
420
|
//
|
|
427
|
-
// The gate is DIFFERENTIAL, not absolute
|
|
421
|
+
// The gate is DIFFERENTIAL, not absolute: discard the edits only
|
|
428
422
|
// when they REGRESSED the health signal — clean before, failing after. A repo
|
|
429
423
|
// that was already failing before enforce ran is not enforce's fault, so its
|
|
430
|
-
// edits are KEPT (and the pre-existing failure is recorded, to be caught by
|
|
431
|
-
// final integration gate, not blamed on this pass). The failing command's
|
|
432
|
-
//
|
|
433
|
-
//
|
|
424
|
+
// edits are KEPT (and the pre-existing failure is recorded, to be caught by
|
|
425
|
+
// the final integration gate, not blamed on this pass). The failing command's
|
|
426
|
+
// OUTPUT is captured into the trail, not just its exit code, so the discard
|
|
427
|
+
// is explainable after the run.
|
|
434
428
|
let enforceEditsBlocked = false;
|
|
435
429
|
if (mode === 'edit' && deps.repoHealth && editsMade !== false) {
|
|
436
430
|
const after = await deps.repoHealth(active, p.cwd, p.title);
|
|
@@ -460,16 +454,15 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
460
454
|
}
|
|
461
455
|
}
|
|
462
456
|
if (mode === 'edit' && !enforceEditsBlocked && editsMade === false) {
|
|
463
|
-
// KNOWN-clean tree (dirty dep ran and found no code edits): skip the
|
|
457
|
+
// KNOWN-clean tree (the dirty dep ran and found no code edits): skip the
|
|
464
458
|
// enforce commit AND the differential re-verify outright. Without this
|
|
465
459
|
// gate the commit is never empty — the .pi-tasks gate-trail lines written
|
|
466
|
-
// above make it real — so
|
|
467
|
-
// UNCHANGED tree
|
|
468
|
-
//
|
|
469
|
-
//
|
|
470
|
-
//
|
|
471
|
-
//
|
|
472
|
-
// along in the next ordinary commit.
|
|
460
|
+
// above make it real — so every task would burn a model re-verify on an
|
|
461
|
+
// UNCHANGED tree, and any FAIL it turned up would be "reverted" into the
|
|
462
|
+
// void: the revert drops a bookkeeping-only commit while the defect
|
|
463
|
+
// report is discarded and the task stays PASS. No edits ⇒ nothing to
|
|
464
|
+
// guard ⇒ no commit, no re-verify, no revert. The trail lines ride along
|
|
465
|
+
// in the next ordinary commit.
|
|
473
466
|
await rec('enforce(edit): no code edits — enforce commit and re-verify skipped');
|
|
474
467
|
}
|
|
475
468
|
else if (mode === 'edit' && !enforceEditsBlocked) {
|
|
@@ -484,30 +477,27 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
484
477
|
await differential(active, p.cwd, p.title, p.taskId)
|
|
485
478
|
: { ok: true };
|
|
486
479
|
const afterReason = after.reason ?? 'enforce re-verify failed';
|
|
487
|
-
// PRE-EXISTING-CAUSE KEEP PATH
|
|
488
|
-
//
|
|
489
|
-
//
|
|
490
|
-
//
|
|
491
|
-
//
|
|
492
|
-
//
|
|
493
|
-
//
|
|
494
|
-
//
|
|
495
|
-
// unknown (git unavailable, no provenance, this task touched the file,
|
|
496
|
-
// an environment-blamed FAIL) falls through to the revert below —
|
|
497
|
-
// the conservative pre-existing behavior.
|
|
480
|
+
// PRE-EXISTING-CAUSE KEEP PATH. A re-verify can FAIL on a file the
|
|
481
|
+
// enforce pass never touched — another task's bug this one merely
|
|
482
|
+
// ran into. Reverting there destroys good work over a fault it did
|
|
483
|
+
// not cause AND leaves the actual cause unscheduled. So when the FAIL
|
|
484
|
+
// is attributed to another task's untouched file, KEEP the edits and
|
|
485
|
+
// route the real defect to a repair task. Everything unknown (git
|
|
486
|
+
// unavailable, no provenance, this task touched the file, an
|
|
487
|
+
// environment-blamed FAIL) falls through to the revert below.
|
|
498
488
|
//
|
|
499
|
-
// The scope is `enforce-commit`, NOT the task's own commit
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
//
|
|
504
|
-
// it in a way that destroyed a correct one-line change.
|
|
489
|
+
// The scope is `enforce-commit`, NOT the task's own commit. This
|
|
490
|
+
// differential decides whether to discard the ENFORCE COMMIT, so the
|
|
491
|
+
// causal question is "could the enforce diff have caused this?".
|
|
492
|
+
// Asking what the TASK touched answers a question nobody at this seam
|
|
493
|
+
// is asking.
|
|
505
494
|
const rootCause = after.ok ? null : await routeRootCause(afterReason, '', 'enforce-commit');
|
|
506
|
-
// ATTRIBUTION PRE-FILTER
|
|
507
|
-
//
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
// the revert. This filter asks only the
|
|
495
|
+
// ATTRIBUTION PRE-FILTER. The root-cause channel above needs a blame
|
|
496
|
+
// CUE, a path-separator token and known provenance. A FAIL text can
|
|
497
|
+
// carry none of the three — a bare `MyListings.spec.tsx:186` names a
|
|
498
|
+
// file with no directory and no blame wording — and then falls
|
|
499
|
+
// straight through to the revert. This filter asks only the
|
|
500
|
+
// mechanical question: does the
|
|
511
501
|
// failing check name any file the ENFORCE COMMIT touched? Disjoint =>
|
|
512
502
|
// the revert cannot repair the failure, so keep the edits and route
|
|
513
503
|
// the defect. Unknown diff, or a FAIL naming no file at all, still
|
|
@@ -527,15 +517,14 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
527
517
|
else if (!after.ok && attribution?.verdict === 'keep') {
|
|
528
518
|
// KEEP, mechanically justified: every file the failing check named
|
|
529
519
|
// is outside the enforce diff (and outside its companions — a
|
|
530
|
-
// touched file's own spec/story counts as inside). Discarding
|
|
531
|
-
// enforce commit could not repair this,
|
|
532
|
-
//
|
|
520
|
+
// touched file's own spec/story counts as inside). Discarding
|
|
521
|
+
// the enforce commit could not repair this, so doing so only
|
|
522
|
+
// costs the correct change the pass made.
|
|
533
523
|
await rec(`enforce: re-verify FAILED (${afterReason.slice(0, 200)}) but the failing check names only \`${attribution.named.join(', ')}\`, `
|
|
534
524
|
+ `which the ENFORCE COMMIT does not touch (its diff: ${attribution.enforceDiff.join(', ') || '—'}) — `
|
|
535
525
|
+ 'reverting it could not repair this, so the edits are KEPT and the defect is recorded as durable debt');
|
|
536
|
-
// Keeping the edits must NOT lose the finding
|
|
537
|
-
//
|
|
538
|
-
// disposition of the edits differs.
|
|
526
|
+
// Keeping the edits must NOT lose the finding. Same durability
|
|
527
|
+
// as the revert path; only the disposition of the edits differs.
|
|
539
528
|
await deps.recordDebt?.(p.cwd, p.taskId, afterReason, 'enforce-kept');
|
|
540
529
|
// …and, when the named file is somebody else's committed work,
|
|
541
530
|
// queue the scoped repair so something actually FIXES it.
|
|
@@ -571,12 +560,12 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
571
560
|
` — the check names \`${attribution.overlap.named}\`, the enforce diff touches \`${attribution.overlap.enforce}\``
|
|
572
561
|
: ''}]`
|
|
573
562
|
: ''));
|
|
574
|
-
// Persist the FAIL as a durable defect
|
|
575
|
-
//
|
|
576
|
-
//
|
|
577
|
-
//
|
|
578
|
-
//
|
|
579
|
-
//
|
|
563
|
+
// Persist the FAIL as a durable defect. The revert restores the
|
|
564
|
+
// tree the ORIGINAL verify already blessed, so this re-verify
|
|
565
|
+
// caught something that verify's earlier PASS missed — erasing it
|
|
566
|
+
// along with the enforce edits would bury a real fault. The final
|
|
567
|
+
// gate re-checks and surfaces it (static-class auto-closes if a
|
|
568
|
+
// later task fixed the statics; otherwise it stays open).
|
|
580
569
|
await deps.recordDebt?.(p.cwd, p.taskId, after.reason ?? 'enforce re-verify failed', 'enforce-revert');
|
|
581
570
|
active.ui.notify(`${p.tag}: guideline fixes regressed verification on "${p.title}" (${(after.reason ?? 'now fails').slice(0, 120)}) — ${deps.revert ? 'reverted them, kept the verified work' : 'left in place (no revert available)'}.`, 'warning');
|
|
582
571
|
}
|
|
@@ -593,7 +582,7 @@ export async function runEnforcePass(active, deps, p, rec, routeRootCause, args)
|
|
|
593
582
|
}
|
|
594
583
|
else if (deps.enforce) {
|
|
595
584
|
// deps.enforce wired but nothing was committed this round — record the skip
|
|
596
|
-
// so a missing enforce run is explainable from the trail
|
|
585
|
+
// so a missing enforce run is explainable from the trail.
|
|
597
586
|
await rec('enforce: skipped (nothing committed this round)');
|
|
598
587
|
}
|
|
599
588
|
}
|
|
@@ -607,12 +596,12 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
607
596
|
}
|
|
608
597
|
};
|
|
609
598
|
/**
|
|
610
|
-
* ROOT-CAUSE CHANNEL
|
|
599
|
+
* ROOT-CAUSE CHANNEL. Ask whether a FAIL was caused by a
|
|
611
600
|
* pre-existing defect in a file some OTHER task created and this task never
|
|
612
601
|
* touched. On a hit: record the durable debt (so the final gate surfaces it)
|
|
613
|
-
* and queue a scoped repair task
|
|
614
|
-
*
|
|
615
|
-
*
|
|
602
|
+
* and queue a scoped repair task, so something finally FIXES it rather than
|
|
603
|
+
* recording the same cause once per task that trips over it. Returns the
|
|
604
|
+
* candidate so the caller can also decide
|
|
616
605
|
* NOT to punish the current task for it. Never throws: any fault degrades to
|
|
617
606
|
* null, i.e. exactly the pre-existing behavior.
|
|
618
607
|
*/
|
|
@@ -652,10 +641,10 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
652
641
|
if (commit.committed) {
|
|
653
642
|
await rec(`commit: task snapshot committed${commit.note ? ` (${commit.note})` : ''}`);
|
|
654
643
|
// SAY WHAT WAS LEFT OUT. The stage skips untracked regenerable test-runner
|
|
655
|
-
// output
|
|
656
|
-
//
|
|
657
|
-
//
|
|
658
|
-
//
|
|
644
|
+
// output, so a blind `git add -A` cannot make a screenshot a tracked
|
|
645
|
+
// deliverable that a later fix attempt is then rejected for deleting. A
|
|
646
|
+
// SILENT exclusion is the same failure class as a silent ignored-path write,
|
|
647
|
+
// so it gets its own trail line.
|
|
659
648
|
if (commit.excluded && commit.excluded.length > 0) {
|
|
660
649
|
await rec(`commit: left ${commit.excluded.length} untracked test-runner artifact(s) out of the `
|
|
661
650
|
+ `snapshot — regenerable output, not deliverables: `
|
|
@@ -668,8 +657,8 @@ export async function runGatesForTask(ctxIn, deps, p) {
|
|
|
668
657
|
await rec(`commit: skipped (${commit.reason ?? 'unknown'})`);
|
|
669
658
|
// A benign skip ("nothing to commit", auto-commit off) is a warning. A real
|
|
670
659
|
// git failure is louder: it silently disables enforce AND every commit-based
|
|
671
|
-
// guard
|
|
672
|
-
//
|
|
660
|
+
// guard, so a whole run can end with nothing committed and only per-task
|
|
661
|
+
// warnings to show for it. "blocked" is the unmerged-index refusal
|
|
673
662
|
// (gitCommitAll) — the same severity: nothing can commit until it's resolved.
|
|
674
663
|
const gitFailure = /^git (commit|add) (failed|blocked)/.test(commit.reason ?? '');
|
|
675
664
|
active.ui.notify(gitFailure ?
|
package/dist/task/task-io.d.ts
CHANGED
|
@@ -24,10 +24,10 @@ export declare function setTaskSection(cwd: string, id: string, heading: string,
|
|
|
24
24
|
/**
|
|
25
25
|
* Append one timestamped line to the task's `## gates` section — the durable
|
|
26
26
|
* per-task trail of gate outcomes (verify verdicts, enforce mode/verdict, commit
|
|
27
|
-
* results).
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* results). A verdict that lives only in memory and a terminal notify cannot
|
|
28
|
+
* answer "did enforce run for this task, and in which mode?" after the run.
|
|
29
|
+
* Best-effort by design: a failure to record must never break the gate sequence,
|
|
30
|
+
* so all errors are swallowed.
|
|
31
31
|
*/
|
|
32
32
|
export declare function appendGateRecord(cwd: string, id: string, line: string): Promise<void>;
|
|
33
33
|
/** Remove a section (heading + body) if present; a no-op when it's absent. */
|
package/dist/task/task-io.js
CHANGED
|
@@ -115,10 +115,10 @@ export async function setTaskSection(cwd, id, heading, content) {
|
|
|
115
115
|
/**
|
|
116
116
|
* Append one timestamped line to the task's `## gates` section — the durable
|
|
117
117
|
* per-task trail of gate outcomes (verify verdicts, enforce mode/verdict, commit
|
|
118
|
-
* results).
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
118
|
+
* results). A verdict that lives only in memory and a terminal notify cannot
|
|
119
|
+
* answer "did enforce run for this task, and in which mode?" after the run.
|
|
120
|
+
* Best-effort by design: a failure to record must never break the gate sequence,
|
|
121
|
+
* so all errors are swallowed.
|
|
122
122
|
*/
|
|
123
123
|
export async function appendGateRecord(cwd, id, line) {
|
|
124
124
|
try {
|
|
@@ -33,9 +33,10 @@ export function emitFrontMatter(fm) {
|
|
|
33
33
|
}
|
|
34
34
|
export function parseFrontMatter(content) {
|
|
35
35
|
// `\r?\n` throughout so a CRLF/Windows task file parses too. Reads normally
|
|
36
|
-
// pass through readTextFile (which normalizes to LF), but
|
|
37
|
-
// the parser itself is the safety net for any read site
|
|
38
|
-
//
|
|
36
|
+
// pass through readTextFile (which normalizes CRLF and lone CR to LF), but
|
|
37
|
+
// tolerating CRLF at the parser itself is the safety net for any read site
|
|
38
|
+
// that forgets to. A lone CR still needs the normalization — no regex here
|
|
39
|
+
// matches it, because every one requires an `\n`. See shared/fs-text.ts.
|
|
39
40
|
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);
|
|
40
41
|
if (!m)
|
|
41
42
|
return null;
|
|
@@ -39,7 +39,7 @@ export interface CrossTaskDeletion {
|
|
|
39
39
|
export declare function findCrossTaskDeletions(changes: TreeChangeSummary, currentTaskId: string, introducedBy: (rel: string) => string | null | Promise<string | null>): Promise<CrossTaskDeletion[]>;
|
|
40
40
|
/**
|
|
41
41
|
* Finding lines for the verify prompt (the substitution-probe injection pattern:
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* a rule on its own is ignored; the rule plus a concrete finding naming the
|
|
43
|
+
* file is what lands).
|
|
44
44
|
*/
|
|
45
45
|
export declare function crossTaskDeletionVerifyFindings(found: CrossTaskDeletion[]): string[];
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* task-provenance — file → introducing-task lookup, and the cross-task deletion
|
|
3
|
-
* detection built on it
|
|
3
|
+
* detection built on it.
|
|
4
4
|
*
|
|
5
|
-
* The failure class: write-enabled gate
|
|
6
|
-
* committed deliverable to turn a red check green
|
|
7
|
-
*
|
|
8
|
-
* committed playwright ct files were not registered in a spec-frozen tsconfig —
|
|
9
|
-
* so a lint-fix child deleted TASK_0020's verified deliverables and the pass
|
|
10
|
-
* returned ok. Every existing guard missed the class:
|
|
5
|
+
* The failure class: a write-enabled gate or fix child can DELETE a sibling
|
|
6
|
+
* task's committed deliverable to turn a red check green — a lint that only goes
|
|
7
|
+
* green once the offending files are gone. Every other guard misses that class:
|
|
11
8
|
*
|
|
12
9
|
* - the lint-fix revert-guard checks only pre-DIRTY files reverted and
|
|
13
|
-
* pre-UNTRACKED files gone — a CLEAN tracked sibling file is in neither set
|
|
10
|
+
* pre-UNTRACKED files gone — a CLEAN tracked sibling file is in neither set
|
|
11
|
+
* (lint-fix.ts says so at its own site);
|
|
14
12
|
* - the frozen-path guard covers only paths THIS task's spec froze;
|
|
15
|
-
* -
|
|
13
|
+
* - `findForbiddenDeletions` (write-guard.ts) was reached only by the final-fix
|
|
14
|
+
* child (final-gate-fix.ts);
|
|
16
15
|
* - the impl turn legitimately deletes files (its own refactors), so a blanket
|
|
17
16
|
* ban is wrong — the discriminator must be PROVENANCE: who introduced the file.
|
|
18
17
|
*
|
|
19
|
-
* The provenance primitive
|
|
20
|
-
* conflicting-claim annotation) resolves a file to the task whose commit ADDED it
|
|
18
|
+
* The provenance primitive resolves a file to the task whose commit ADDED it
|
|
21
19
|
* (`git log --diff-filter=A` → oldest task-subject commit). Every unknown — a file
|
|
22
20
|
* predating the run, a non-task commit, any git error — degrades to null:
|
|
23
21
|
* inconclusive is never evidence, so the guards built on this may only cost time,
|
|
@@ -90,8 +88,8 @@ export async function findCrossTaskDeletions(changes, currentTaskId, introducedB
|
|
|
90
88
|
}
|
|
91
89
|
/**
|
|
92
90
|
* Finding lines for the verify prompt (the substitution-probe injection pattern:
|
|
93
|
-
*
|
|
94
|
-
*
|
|
91
|
+
* a rule on its own is ignored; the rule plus a concrete finding naming the
|
|
92
|
+
* file is what lands).
|
|
95
93
|
*/
|
|
96
94
|
export function crossTaskDeletionVerifyFindings(found) {
|
|
97
95
|
return found.map(f => `\`${f.path}\` — introduced and committed by ${f.owner}, DELETED by this task's work`);
|
|
@@ -15,9 +15,10 @@ export interface TaskFrontMatter {
|
|
|
15
15
|
title: string;
|
|
16
16
|
/**
|
|
17
17
|
* Short, human-readable display label compressed from `title`. Visual only —
|
|
18
|
-
* `title` always holds the full text the pipeline reads. Absent on
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* `title` always holds the full text the pipeline reads. Absent on a task file
|
|
19
|
+
* written before the field existed, and on any task that never reached the
|
|
20
|
+
* phase that writes it; display then falls back to a deterministic truncation
|
|
21
|
+
* of `title` (`titleForDisplay`, parsers.ts). See title-label.ts.
|
|
21
22
|
*/
|
|
22
23
|
label?: string;
|
|
23
24
|
reason?: string;
|
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
* What each way a gated task can END means for persistence and for what the user
|
|
3
3
|
* is told — stated once, for both `/task` and `/task-auto`.
|
|
4
4
|
*
|
|
5
|
-
* `runGatesForTask` is
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* `runGatesForTask` is shared by the two commands, so both consume the same
|
|
6
|
+
* outcome union. Each kind raises the same three questions: demote the inner task
|
|
7
|
+
* file? fail the parent run file? what do we say, at what level? This table
|
|
8
|
+
* answers them once. It touches none of either loop's state — it is the
|
|
9
|
+
* outcome → (persistence, message) mapping and nothing else — and a new outcome
|
|
10
|
+
* kind is a compile error here rather than a silent fallthrough in whichever
|
|
11
|
+
* command was not updated.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* state. Adding a sixth outcome kind is now a compile error in one place rather
|
|
17
|
-
* than a silently-unhandled fallthrough in whichever command was not updated.
|
|
13
|
+
* The three things that genuinely differ per command are parameters: the resume
|
|
14
|
+
* verb, whether the message names a step (`/task` runs one task and passes an
|
|
15
|
+
* empty `at`), and whether a parent run file exists to fail.
|
|
18
16
|
*
|
|
19
17
|
* The PRE-gate outcomes (`res.sessionCancelled` / `res.interrupted` / `!res.ok`,
|
|
20
18
|
* before the gate runs) are deliberately NOT here. Their wording genuinely
|
|
@@ -28,7 +26,7 @@
|
|
|
28
26
|
export type TerminalOutcomeKind = 'done' | 'paused' | 'session-cancelled' | 'cancelled' | 'interrupted' | 'failed';
|
|
29
27
|
/** What the message needs to name. */
|
|
30
28
|
export interface TerminalMessageContext {
|
|
31
|
-
/** The task or run id shown to the user
|
|
29
|
+
/** The task or run id shown to the user. */
|
|
32
30
|
tag: string;
|
|
33
31
|
/**
|
|
34
32
|
* The step this happened at, ALREADY formatted with its leading space —
|
|
@@ -45,7 +43,7 @@ export interface TerminalOutcome {
|
|
|
45
43
|
/**
|
|
46
44
|
* Demote the INNER task file to resumable. It reads `completed` from
|
|
47
45
|
* spec-handoff, and leaving it that way is how a failed run's task file
|
|
48
|
-
* claimed success
|
|
46
|
+
* claimed success after the run had failed.
|
|
49
47
|
*/
|
|
50
48
|
markResumable: boolean;
|
|
51
49
|
/**
|
|
@@ -58,8 +56,8 @@ export interface TerminalOutcome {
|
|
|
58
56
|
message: (c: TerminalMessageContext) => string;
|
|
59
57
|
}
|
|
60
58
|
/**
|
|
61
|
-
* Truncate a failure reason for a one-line notification, or produce nothing
|
|
62
|
-
*
|
|
59
|
+
* Truncate a failure reason for a one-line notification, or produce nothing when
|
|
60
|
+
* there is no reason.
|
|
63
61
|
*/
|
|
64
62
|
export declare function formatWhy(reason?: string): string;
|
|
65
63
|
/** The step suffix, or empty when the command has no step to name. */
|
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
* What each way a gated task can END means for persistence and for what the user
|
|
3
3
|
* is told — stated once, for both `/task` and `/task-auto`.
|
|
4
4
|
*
|
|
5
|
-
* `runGatesForTask` is
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* `runGatesForTask` is shared by the two commands, so both consume the same
|
|
6
|
+
* outcome union. Each kind raises the same three questions: demote the inner task
|
|
7
|
+
* file? fail the parent run file? what do we say, at what level? This table
|
|
8
|
+
* answers them once. It touches none of either loop's state — it is the
|
|
9
|
+
* outcome → (persistence, message) mapping and nothing else — and a new outcome
|
|
10
|
+
* kind is a compile error here rather than a silent fallthrough in whichever
|
|
11
|
+
* command was not updated.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* state. Adding a sixth outcome kind is now a compile error in one place rather
|
|
17
|
-
* than a silently-unhandled fallthrough in whichever command was not updated.
|
|
13
|
+
* The three things that genuinely differ per command are parameters: the resume
|
|
14
|
+
* verb, whether the message names a step (`/task` runs one task and passes an
|
|
15
|
+
* empty `at`), and whether a parent run file exists to fail.
|
|
18
16
|
*
|
|
19
17
|
* The PRE-gate outcomes (`res.sessionCancelled` / `res.interrupted` / `!res.ok`,
|
|
20
18
|
* before the gate runs) are deliberately NOT here. Their wording genuinely
|
|
@@ -25,8 +23,8 @@
|
|
|
25
23
|
* overrides, which is not a simplification.
|
|
26
24
|
*/
|
|
27
25
|
/**
|
|
28
|
-
* Truncate a failure reason for a one-line notification, or produce nothing
|
|
29
|
-
*
|
|
26
|
+
* Truncate a failure reason for a one-line notification, or produce nothing when
|
|
27
|
+
* there is no reason.
|
|
30
28
|
*/
|
|
31
29
|
export function formatWhy(reason) {
|
|
32
30
|
return reason ? ` — ${reason.slice(0, 160)}` : '';
|