@mjasnikovs/pi-task 0.38.28 → 0.38.30
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/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 +22 -16
- package/dist/shared/command-watchdog.js +28 -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 +178 -162
- 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 +46 -51
- package/dist/task/child-runner.js +48 -49
- 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 +25 -7
- package/dist/task/context-usage.js +21 -6
- 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 +6 -7
- 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 +37 -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-thinking.d.ts +33 -31
- package/dist/task/implementation-thinking.js +5 -6
- package/dist/task/implementation-turn.d.ts +34 -31
- package/dist/task/implementation-turn.js +29 -27
- 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 +9 -8
- package/dist/task/loop-detector.js +16 -12
- 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 +62 -64
- 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 +180 -248
- 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 +33 -36
- package/dist/task/research-worker.js +39 -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 +12 -12
- package/dist/workers/focused-extractor.js +16 -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 +86 -54
- package/dist/workers/pi-worker-core.js +112 -112
- 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 +23 -10
- 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 +25 -28
- package/dist/workers/single-read-guard.js +32 -32
- 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 +43 -53
- package/dist/workers/worker-profiles.js +30 -38
- package/package.json +10 -8
|
@@ -5,13 +5,15 @@ import { type TreeChangeSummary, type IgnoredSnapshot } from './write-guard.js';
|
|
|
5
5
|
export declare const FINAL_FIX_TOOLS = "read,edit,bash";
|
|
6
6
|
/**
|
|
7
7
|
* How many fix passes the user may launch from the picker before the option is
|
|
8
|
-
* withdrawn
|
|
9
|
-
* full model child plus a full gate re-run — after this many that still FAIL,
|
|
10
|
-
*
|
|
8
|
+
* withdrawn. Same value as the per-task MAX_AUTO_AUTOFIX budget. Each attempt is
|
|
9
|
+
* a full model child plus a full gate re-run — after this many that still FAIL,
|
|
10
|
+
* `run-final-gate.ts` drops the Autofix card and only Leave-failed / Accept
|
|
11
|
+
* remain, so a person breaks the loop.
|
|
11
12
|
*/
|
|
12
13
|
export declare const MAX_FINAL_GATE_AUTOFIX = 3;
|
|
13
|
-
/** Picker labels/values.
|
|
14
|
-
*
|
|
14
|
+
/** Picker labels/values. Each label starts with its own value word, so
|
|
15
|
+
* `classifyFinalGateAnswer` accepts the value token and the label alike;
|
|
16
|
+
* anything else is free text and becomes autofix guidance. */
|
|
15
17
|
export declare const FINAL_LEAVE_VALUE = "fail";
|
|
16
18
|
export declare const FINAL_ACCEPT_VALUE = "accept";
|
|
17
19
|
export declare const FINAL_AUTOFIX_VALUE = "autofix";
|
|
@@ -19,8 +21,8 @@ export declare const FINAL_LEAVE_LABEL = "Leave failed \u2014 I will fix and /ta
|
|
|
19
21
|
export declare const FINAL_ACCEPT_LABEL = "Accept \u2014 complete the run anyway";
|
|
20
22
|
export declare const FINAL_AUTOFIX_LABEL = "Autofix \u2014 run a bounded fix pass and re-run the gate";
|
|
21
23
|
export interface FinalGateChoice {
|
|
22
|
-
/** What the user decided. 'leave' = leave the run failed
|
|
23
|
-
*
|
|
24
|
+
/** What the user decided. 'leave' = leave the run failed, and also what a
|
|
25
|
+
* dismissed picker means. */
|
|
24
26
|
action: 'leave' | 'accept' | 'autofix';
|
|
25
27
|
/** Free-text guidance typed instead of picking a card; folded into the fix
|
|
26
28
|
* child's failure seed. Only set with 'autofix'. */
|
|
@@ -28,63 +30,51 @@ export interface FinalGateChoice {
|
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Map a final-gate picker answer to an action. Dismissal (undefined/empty) and
|
|
31
|
-
* an explicit leave stay "leave"
|
|
32
|
-
*
|
|
33
|
-
*
|
|
33
|
+
* an explicit leave both stay "leave". Free text becomes autofix guidance; the
|
|
34
|
+
* caller's `choice.action === 'autofix' && canAutofix` test demotes autofix back
|
|
35
|
+
* to leave when the card was not offered.
|
|
34
36
|
*/
|
|
35
37
|
export declare function classifyFinalGateAnswer(answer: string | undefined): FinalGateChoice;
|
|
36
38
|
/**
|
|
37
|
-
* The gate's fail reason
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* discovered-command sets, so a reason
|
|
39
|
+
* The gate's fail reason carries the failing command in backticks — final-gate
|
|
40
|
+
* mints `` `<label>` exited <status> — <tail> ``, with a `lockfile check: ` or
|
|
41
|
+
* `launch script: ` prefix on two of the sections. Extract it for reporting
|
|
42
|
+
* only; the shrink guard compares the FULL discovered-command sets, so a reason
|
|
43
|
+
* this cannot parse still guards.
|
|
41
44
|
*/
|
|
42
45
|
export declare function exitedCommandFromReason(reason: string): string | null;
|
|
43
46
|
/**
|
|
44
47
|
* Build the fix child's prompt. Generic by construction: the only project facts
|
|
45
|
-
* in it are the gate's own failure text
|
|
46
|
-
* discovered manifest
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* child is told to fix all of them.
|
|
48
|
+
* in it are the gate's own failure text, whose command labels come from the
|
|
49
|
+
* project's discovered manifest. The seed may carry SEVERAL failures — the gate
|
|
50
|
+
* runs every section and aggregates, emitting "N failures (ranked, most
|
|
51
|
+
* load-bearing first)" — and it reports `ok` only when that list is empty, so
|
|
52
|
+
* the child is told to fix all of them.
|
|
50
53
|
*/
|
|
51
54
|
export declare function buildFinalFixPrompt(failReason: string): string;
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* concluding and bash output can echo the words). No marker → treated as DONE:
|
|
55
|
-
* the gate re-run is the arbiter either way, so a missing marker only skips the
|
|
56
|
-
* early-out on a self-declared BLOCKED.
|
|
57
|
-
*/
|
|
55
|
+
/** This pass's marker word, parsed by the shared `parseFixMarker` (last match
|
|
56
|
+
* wins; no marker → DONE). */
|
|
58
57
|
export declare function parseFinalFixMarker(text: string): {
|
|
59
58
|
blocked: boolean;
|
|
60
59
|
note?: string;
|
|
61
60
|
};
|
|
62
61
|
/**
|
|
63
|
-
* STRANDED SUB-FIXES
|
|
64
|
-
*
|
|
65
|
-
* A fix attempt that does not converge keeps its edits: they are NOT discarded
|
|
66
|
-
* (only a guard trip discards), and `deps.commit` runs only on `fix.ok`. So a
|
|
67
|
-
* partial fix that genuinely repaired something sits in the working tree, uncommitted,
|
|
68
|
-
* and if the user then ACCEPTs the FAIL the run completes around it — leaving HEAD
|
|
69
|
-
* broken while the repair is invisible unless someone runs `git status`.
|
|
62
|
+
* STRANDED SUB-FIXES.
|
|
70
63
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* by default.
|
|
64
|
+
* An attempt that does not converge KEEPS its edits — only a guard trip
|
|
65
|
+
* discards — and the caller commits only on `fix.ok`. So a partial fix that
|
|
66
|
+
* genuinely repaired something sits uncommitted in the working tree while HEAD
|
|
67
|
+
* still carries the defect, invisible unless someone runs `git status`.
|
|
76
68
|
*
|
|
77
|
-
* The rule: a partial fix is either committed
|
|
78
|
-
* explicitly surfaced — never silently stranded.
|
|
69
|
+
* The rule: a partial fix is either committed as its own named commit or
|
|
70
|
+
* explicitly surfaced — never silently stranded. `run-final-gate.ts` calls
|
|
71
|
+
* `commitStranded` on BOTH terminal outcomes, accept and leave-failed, so an
|
|
72
|
+
* unattended run that ends on LEAVE does not leave real repairs one `git
|
|
73
|
+
* checkout` from gone.
|
|
79
74
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* app work today — were left dirty in the tree, one `git checkout` from gone, after
|
|
84
|
-
* an UNATTENDED run nobody was watching. So EVERY terminal non-converged outcome
|
|
85
|
-
* commits them now, not just ACCEPT. Only guard-CLEAN edits qualify: an attempt a
|
|
86
|
-
* write-guard rejected without discarding leaves REJECTED edits in the tree, and
|
|
87
|
-
* those are never committed (the guard is not weakened to make committing easier).
|
|
75
|
+
* Only guard-CLEAN edits qualify. `AutofixLedger.mayCommitTree()` goes false
|
|
76
|
+
* once a guard has rejected an attempt whose edits could not be discarded, and
|
|
77
|
+
* never flips back: the guard is not weakened to make committing easier.
|
|
88
78
|
*/
|
|
89
79
|
/** Commit subject for partial fixes committed alongside a terminal gate FAIL. */
|
|
90
80
|
export declare const STRANDED_FIX_COMMIT: (runId: string, outcome?: "accepted" | "left-failed") => string;
|
|
@@ -99,38 +89,32 @@ export interface FinalFixResult {
|
|
|
99
89
|
/** Human-readable outcome (converged gate reason, or why the attempt failed). */
|
|
100
90
|
reason: string;
|
|
101
91
|
/**
|
|
102
|
-
* The re-run gate's OUTCOME, whole — present whenever the gate actually ran
|
|
103
|
-
*
|
|
104
|
-
* skipped
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* things. `openDebts` never crossed at all, so `runFinalGateStage` rebuilt
|
|
108
|
-
* `fin` as a literal three times and each literal dropped it — the recorded
|
|
109
|
-
* mx5 run-18 defect, fixed by RE-DERIVING the field (`reconcileDebts`) rather
|
|
110
|
-
* than by keeping the value. Then 19A had to push `observedFailures` across the
|
|
111
|
-
* same wall as a third parallel field and re-pair it downstream by
|
|
112
|
-
* `gateObservedFailures?.includes(detail)` — a membership test that exists only
|
|
113
|
-
* because the pairing was broken in transit.
|
|
92
|
+
* The re-run gate's OUTCOME, whole — present whenever the gate actually ran,
|
|
93
|
+
* absent only when the fix child self-declared BLOCKED and the re-run was
|
|
94
|
+
* skipped. The whole `FinalGateOutcome` crosses, not a hand-picked copy of
|
|
95
|
+
* some of its fields: a copy silently drops whatever it forgot, and the
|
|
96
|
+
* pairing between `failures` and `observedFailures` only holds inside it.
|
|
114
97
|
*/
|
|
115
98
|
gate?: FinalGateOutcome;
|
|
116
99
|
/** On a converged outcome: the UNOBSERVED note the CALLER should show. It is
|
|
117
100
|
* the gate's own note plus any downgrade this fix pass added (see the
|
|
118
101
|
* ignored-dependency probe below), so it is not simply `gate.unobserved`. */
|
|
119
102
|
unobserved?: string;
|
|
120
|
-
/** Gitignored path(s) this fix pass wrote, exempt classes already
|
|
121
|
-
*
|
|
122
|
-
*
|
|
103
|
+
/** Gitignored path(s) this fix pass wrote, with the exempt classes already
|
|
104
|
+
* removed (task dir, `.git`, node_modules, build output — write-guard.ts).
|
|
105
|
+
* Present whether or not the gate converged; path names only, never
|
|
106
|
+
* contents. */
|
|
123
107
|
ignoredWrites?: string[];
|
|
124
108
|
/** …and the mechanical dependency probe found the converged gate does NOT pass
|
|
125
109
|
* without them, so `unobserved` above carries the downgrade. Absent when the
|
|
126
|
-
* probe could not answer
|
|
110
|
+
* probe could not answer: no probe wired, a path that would not move, or more
|
|
111
|
+
* paths than its bound allows. */
|
|
127
112
|
ignoredDependent?: boolean;
|
|
128
113
|
/** A write-guard rejected this attempt (deletion / shrink / probe-gaming). */
|
|
129
114
|
guardTripped?: boolean;
|
|
130
|
-
/** …and its edits were discarded.
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* only guard-CLEAN ones; the cheat guard is never weakened to ease committing). */
|
|
115
|
+
/** …and its edits were discarded. False here with `guardTripped` true means
|
|
116
|
+
* the tree still holds REJECTED edits, and the caller must not commit what it
|
|
117
|
+
* finds: that is what `AutofixLedger.mayCommitTree()` latches off. */
|
|
134
118
|
editsDiscarded?: boolean;
|
|
135
119
|
}
|
|
136
120
|
export interface FinalFixDeps {
|
|
@@ -143,34 +127,37 @@ export interface FinalFixDeps {
|
|
|
143
127
|
runChild: (tools: string, prompt: string, signal?: AbortSignal) => Promise<string>;
|
|
144
128
|
/** Re-run the final integration gate — the only arbiter of convergence.
|
|
145
129
|
* Converges only when the gate's FULL aggregated failure list is empty
|
|
146
|
-
* (ok=true); `failures` rides through so the caller sees every entry.
|
|
147
|
-
|
|
148
|
-
* fields — a re-declaration is how `openDebts` came to be silently absent. */
|
|
130
|
+
* (ok=true); `failures` rides through so the caller sees every entry.
|
|
131
|
+
* Typed as the gate's own outcome, not a structural copy of some fields. */
|
|
149
132
|
gate: (cwd: string) => Promise<FinalGateOutcome>;
|
|
150
|
-
/** Labels of every currently-discoverable gate command
|
|
151
|
-
* for the shrink guard. Pure discovery
|
|
133
|
+
/** Labels of every currently-discoverable gate command — health, lockfile,
|
|
134
|
+
* integration and boot — for the shrink guard. Pure discovery: nothing
|
|
135
|
+
* runs. */
|
|
152
136
|
discoverLabels: (cwd: string) => string[];
|
|
153
137
|
/** The same commands' RESOLVED BODIES (`label → scripts[name]` / Makefile
|
|
154
138
|
* recipe), for the scope-shrink half of the guard. Absent → only the label
|
|
155
|
-
* comparison runs
|
|
139
|
+
* comparison runs. */
|
|
156
140
|
discoverBodies?: (cwd: string) => Record<string, string>;
|
|
157
141
|
/** Discard the fix child's working-tree edits (guard trips only). Absent
|
|
158
142
|
* → the violation is still rejected, edits are left for inspection. */
|
|
159
143
|
discard?: (cwd: string) => Promise<void>;
|
|
160
|
-
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
144
|
+
/** Tree changes in `git status --porcelain` shape — the deletion guard's input
|
|
145
|
+
* and the "created by this fix" set the scope-shrink guard consults. Every
|
|
146
|
+
* task is committed before this stage, so what status reports is fix-pass
|
|
147
|
+
* work; on a second attempt that includes the first attempt's kept edits,
|
|
148
|
+
* since a non-converged attempt is not discarded. */
|
|
163
149
|
treeChanges?: () => Promise<TreeChangeSummary>;
|
|
164
150
|
/** The union of every task spec's frozen (Do-NOT-modify) paths — the whole-run
|
|
165
151
|
* write-deny set, since this child works across all slices at once. */
|
|
166
152
|
frozenPaths?: () => Promise<string[]>;
|
|
167
|
-
/** Restore the given frozen paths to HEAD; returns the files actually reverted
|
|
168
|
-
*
|
|
153
|
+
/** Restore the given frozen paths to HEAD; returns the files actually reverted.
|
|
154
|
+
* `frozen-path-guard.ts`'s `revertFrozenPaths`, the same one the per-task
|
|
155
|
+
* passes use. */
|
|
169
156
|
revertFrozen?: (paths: string[]) => Promise<string[]>;
|
|
170
|
-
/** Deterministic probe scan over the child's ADDED lines
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
157
|
+
/** Deterministic probe scan over the child's ADDED lines: a fix whose own
|
|
158
|
+
* added text says it is gaming a check rather than meeting it rejects the
|
|
159
|
+
* attempt. There is no verify child downstream of this pass to judge such a
|
|
160
|
+
* finding. Findings are the verbatim offending lines. */
|
|
174
161
|
probeScan?: () => Promise<string[]>;
|
|
175
162
|
/** Fingerprint of the ACTIONABLE ignored paths (build output and node_modules
|
|
176
163
|
* already exempt). Called before and after the child; the difference is what
|
|
@@ -189,9 +176,10 @@ export interface FinalFixDeps {
|
|
|
189
176
|
log?: (msg: string) => void;
|
|
190
177
|
}
|
|
191
178
|
/**
|
|
192
|
-
* Run one bounded final-gate fix attempt: snapshot discovery
|
|
193
|
-
*
|
|
194
|
-
* scan
|
|
195
|
-
* runChild propagates
|
|
179
|
+
* Run one bounded final-gate fix attempt: snapshot discovery and ignored paths →
|
|
180
|
+
* child → frozen-path revert → deletion guard → shrink guard → scope-shrink
|
|
181
|
+
* guard → probe scan → gate re-run. Never throws for an outcome; only a user
|
|
182
|
+
* cancel inside runChild propagates, and the caller's USER_CANCELLED path
|
|
183
|
+
* handles that.
|
|
196
184
|
*/
|
|
197
185
|
export declare function runFinalGateAutofix(deps: FinalFixDeps): Promise<FinalFixResult>;
|
|
@@ -1,47 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* final-gate-fix — the bounded, model-driven fix pass
|
|
3
|
-
*
|
|
2
|
+
* final-gate-fix — the bounded, model-driven fix pass the FINAL integration
|
|
3
|
+
* gate's resolution picker offers as its second card.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* write-enabled child (read, edit, bash) is seeded with the gate's exact failure
|
|
14
|
-
* (command + exit code + output tail), fixes the defect in place, and the gate
|
|
15
|
-
* itself is re-run as the only arbiter — the child's self-report is never
|
|
16
|
-
* trusted. The user always chooses this path from the picker ("Leave failed"
|
|
17
|
-
* stays the recommended default), and attempts are capped so a non-converging
|
|
18
|
-
* loop hands control back to a person.
|
|
5
|
+
* This mirrors the per-task graduated-resolution shape (lint-fix.ts) and shares
|
|
6
|
+
* its child ladder through `runFixChild`: a write-enabled child limited to
|
|
7
|
+
* `read,edit,bash` is seeded with the gate's own failure text, edits in place,
|
|
8
|
+
* and then the gate is RE-RUN. The child's self-report can only end an attempt
|
|
9
|
+
* early as BLOCKED; it can never produce a PASS. `run-final-gate.ts` keeps
|
|
10
|
+
* "Leave failed" as the recommended card and stops offering Autofix after
|
|
11
|
+
* MAX_FINAL_GATE_AUTOFIX attempts, so a non-converging loop hands control back
|
|
12
|
+
* to a person.
|
|
19
13
|
*
|
|
20
14
|
* CHEAT GUARD (deterministic): the cheapest way for a fix child to "converge" is
|
|
21
15
|
* to remove the failing command itself — delete the `test` script, drop the
|
|
22
|
-
* Makefile target — so the gate discovers nothing and vacuously passes.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* the
|
|
26
|
-
*
|
|
27
|
-
*
|
|
16
|
+
* Makefile target — so the gate discovers nothing and vacuously passes. The
|
|
17
|
+
* discovered gate commands are therefore snapshotted before the child runs; a
|
|
18
|
+
* previously-discovered command that is no longer discoverable afterwards
|
|
19
|
+
* rejects the attempt and discards its edits, and so does one whose resolved
|
|
20
|
+
* BODY narrowed. A fix may change what a command DOES, never make it disappear
|
|
21
|
+
* or shrink what it covers.
|
|
28
22
|
*
|
|
29
|
-
* WRITE-GUARD STACK
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* rejects the attempt) → shrink guard (above) → probe-gaming scan over the added
|
|
36
|
-
* lines (a fix that SAYS it games a check rejects the attempt). Diff capture for
|
|
37
|
-
* every write-capable gate child lives at the gate-deps seam, keyed on the
|
|
38
|
-
* child's TOOLS, so the next write-capable kind cannot run invisibly either.
|
|
23
|
+
* WRITE-GUARD STACK, in the order `runFinalGateAutofix` runs it: frozen-path
|
|
24
|
+
* revert (only when a freeze set is wired) → deletion guard (a tracked file
|
|
25
|
+
* deleted without relocation rejects the attempt) → shrink guard → scope-shrink
|
|
26
|
+
* guard → probe-gaming scan over the added lines. Diff capture is NOT here: it
|
|
27
|
+
* lives at the gate-child seam, where a `/\b(?:edit|bash|write)\b/` test on the
|
|
28
|
+
* child's TOOLS decides it, so any future write-capable kind is logged too.
|
|
39
29
|
*
|
|
40
|
-
* The frozen-path deny is implemented but NOT wired by gate-deps
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* legitimate whole-repo fix
|
|
44
|
-
*
|
|
30
|
+
* The frozen-path deny is implemented here but NOT wired by gate-deps — the
|
|
31
|
+
* `finalGateFix` wiring there passes every other dep and omits these two.
|
|
32
|
+
* Per-task frozen fences are task-SCOPED, so their union across a run's specs
|
|
33
|
+
* can fence off a file a legitimate whole-repo fix has to touch. It activates
|
|
34
|
+
* only when a run-GLOBAL freeze source exists.
|
|
45
35
|
*/
|
|
46
36
|
import { parseFixMarker, runFixChild } from './fix-child.js';
|
|
47
37
|
import { findForbiddenDeletions, diffIgnoredSnapshots, ignoredWriteTrailLine, ignoredWriteUnobservedNote } from './write-guard.js';
|
|
@@ -51,13 +41,15 @@ import { findNarrowedCommands, narrowingRejectionText } from './command-shrink.j
|
|
|
51
41
|
export const FINAL_FIX_TOOLS = 'read,edit,bash';
|
|
52
42
|
/**
|
|
53
43
|
* How many fix passes the user may launch from the picker before the option is
|
|
54
|
-
* withdrawn
|
|
55
|
-
* full model child plus a full gate re-run — after this many that still FAIL,
|
|
56
|
-
*
|
|
44
|
+
* withdrawn. Same value as the per-task MAX_AUTO_AUTOFIX budget. Each attempt is
|
|
45
|
+
* a full model child plus a full gate re-run — after this many that still FAIL,
|
|
46
|
+
* `run-final-gate.ts` drops the Autofix card and only Leave-failed / Accept
|
|
47
|
+
* remain, so a person breaks the loop.
|
|
57
48
|
*/
|
|
58
49
|
export const MAX_FINAL_GATE_AUTOFIX = 3;
|
|
59
|
-
/** Picker labels/values.
|
|
60
|
-
*
|
|
50
|
+
/** Picker labels/values. Each label starts with its own value word, so
|
|
51
|
+
* `classifyFinalGateAnswer` accepts the value token and the label alike;
|
|
52
|
+
* anything else is free text and becomes autofix guidance. */
|
|
61
53
|
export const FINAL_LEAVE_VALUE = 'fail';
|
|
62
54
|
export const FINAL_ACCEPT_VALUE = 'accept';
|
|
63
55
|
export const FINAL_AUTOFIX_VALUE = 'autofix';
|
|
@@ -66,9 +58,9 @@ export const FINAL_ACCEPT_LABEL = 'Accept — complete the run anyway';
|
|
|
66
58
|
export const FINAL_AUTOFIX_LABEL = 'Autofix — run a bounded fix pass and re-run the gate';
|
|
67
59
|
/**
|
|
68
60
|
* Map a final-gate picker answer to an action. Dismissal (undefined/empty) and
|
|
69
|
-
* an explicit leave stay "leave"
|
|
70
|
-
*
|
|
71
|
-
*
|
|
61
|
+
* an explicit leave both stay "leave". Free text becomes autofix guidance; the
|
|
62
|
+
* caller's `choice.action === 'autofix' && canAutofix` test demotes autofix back
|
|
63
|
+
* to leave when the card was not offered.
|
|
72
64
|
*/
|
|
73
65
|
export function classifyFinalGateAnswer(answer) {
|
|
74
66
|
if (answer === undefined)
|
|
@@ -85,10 +77,11 @@ export function classifyFinalGateAnswer(answer) {
|
|
|
85
77
|
return { action: 'autofix', guidance: t };
|
|
86
78
|
}
|
|
87
79
|
/**
|
|
88
|
-
* The gate's fail reason
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* discovered-command sets, so a reason
|
|
80
|
+
* The gate's fail reason carries the failing command in backticks — final-gate
|
|
81
|
+
* mints `` `<label>` exited <status> — <tail> ``, with a `lockfile check: ` or
|
|
82
|
+
* `launch script: ` prefix on two of the sections. Extract it for reporting
|
|
83
|
+
* only; the shrink guard compares the FULL discovered-command sets, so a reason
|
|
84
|
+
* this cannot parse still guards.
|
|
92
85
|
*/
|
|
93
86
|
export function exitedCommandFromReason(reason) {
|
|
94
87
|
const m = /`([^`]+)`\s+exited\b/.exec(reason);
|
|
@@ -96,11 +89,11 @@ export function exitedCommandFromReason(reason) {
|
|
|
96
89
|
}
|
|
97
90
|
/**
|
|
98
91
|
* Build the fix child's prompt. Generic by construction: the only project facts
|
|
99
|
-
* in it are the gate's own failure text
|
|
100
|
-
* discovered manifest
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* child is told to fix all of them.
|
|
92
|
+
* in it are the gate's own failure text, whose command labels come from the
|
|
93
|
+
* project's discovered manifest. The seed may carry SEVERAL failures — the gate
|
|
94
|
+
* runs every section and aggregates, emitting "N failures (ranked, most
|
|
95
|
+
* load-bearing first)" — and it reports `ok` only when that list is empty, so
|
|
96
|
+
* the child is told to fix all of them.
|
|
104
97
|
*/
|
|
105
98
|
export function buildFinalFixPrompt(failReason) {
|
|
106
99
|
return [
|
|
@@ -144,41 +137,28 @@ export function buildFinalFixPrompt(failReason) {
|
|
|
144
137
|
' FINAL-GATE-FIX: BLOCKED <why you could not fix it>'
|
|
145
138
|
].join('\n');
|
|
146
139
|
}
|
|
147
|
-
/**
|
|
148
|
-
*
|
|
149
|
-
* concluding and bash output can echo the words). No marker → treated as DONE:
|
|
150
|
-
* the gate re-run is the arbiter either way, so a missing marker only skips the
|
|
151
|
-
* early-out on a self-declared BLOCKED.
|
|
152
|
-
*/
|
|
140
|
+
/** This pass's marker word, parsed by the shared `parseFixMarker` (last match
|
|
141
|
+
* wins; no marker → DONE). */
|
|
153
142
|
export function parseFinalFixMarker(text) {
|
|
154
143
|
return parseFixMarker('FINAL-GATE-FIX', text);
|
|
155
144
|
}
|
|
156
145
|
/**
|
|
157
|
-
* STRANDED SUB-FIXES
|
|
158
|
-
*
|
|
159
|
-
* A fix attempt that does not converge keeps its edits: they are NOT discarded
|
|
160
|
-
* (only a guard trip discards), and `deps.commit` runs only on `fix.ok`. So a
|
|
161
|
-
* partial fix that genuinely repaired something sits in the working tree, uncommitted,
|
|
162
|
-
* and if the user then ACCEPTs the FAIL the run completes around it — leaving HEAD
|
|
163
|
-
* broken while the repair is invisible unless someone runs `git status`.
|
|
146
|
+
* STRANDED SUB-FIXES.
|
|
164
147
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* by default.
|
|
148
|
+
* An attempt that does not converge KEEPS its edits — only a guard trip
|
|
149
|
+
* discards — and the caller commits only on `fix.ok`. So a partial fix that
|
|
150
|
+
* genuinely repaired something sits uncommitted in the working tree while HEAD
|
|
151
|
+
* still carries the defect, invisible unless someone runs `git status`.
|
|
170
152
|
*
|
|
171
|
-
* The rule: a partial fix is either committed
|
|
172
|
-
* explicitly surfaced — never silently stranded.
|
|
153
|
+
* The rule: a partial fix is either committed as its own named commit or
|
|
154
|
+
* explicitly surfaced — never silently stranded. `run-final-gate.ts` calls
|
|
155
|
+
* `commitStranded` on BOTH terminal outcomes, accept and leave-failed, so an
|
|
156
|
+
* unattended run that ends on LEAVE does not leave real repairs one `git
|
|
157
|
+
* checkout` from gone.
|
|
173
158
|
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* app work today — were left dirty in the tree, one `git checkout` from gone, after
|
|
178
|
-
* an UNATTENDED run nobody was watching. So EVERY terminal non-converged outcome
|
|
179
|
-
* commits them now, not just ACCEPT. Only guard-CLEAN edits qualify: an attempt a
|
|
180
|
-
* write-guard rejected without discarding leaves REJECTED edits in the tree, and
|
|
181
|
-
* those are never committed (the guard is not weakened to make committing easier).
|
|
159
|
+
* Only guard-CLEAN edits qualify. `AutofixLedger.mayCommitTree()` goes false
|
|
160
|
+
* once a guard has rejected an attempt whose edits could not be discarded, and
|
|
161
|
+
* never flips back: the guard is not weakened to make committing easier.
|
|
182
162
|
*/
|
|
183
163
|
/** Commit subject for partial fixes committed alongside a terminal gate FAIL. */
|
|
184
164
|
export const STRANDED_FIX_COMMIT = (runId, outcome = 'accepted') => `FINAL GATE PARTIAL FIX (${runId}) — ${outcome === 'accepted' ?
|
|
@@ -198,10 +178,11 @@ export function strandedFixNote(paths) {
|
|
|
198
178
|
+ `checkout — the run's outcome is recorded in the gate trail either way.`);
|
|
199
179
|
}
|
|
200
180
|
/**
|
|
201
|
-
* Run one bounded final-gate fix attempt: snapshot discovery
|
|
202
|
-
*
|
|
203
|
-
* scan
|
|
204
|
-
* runChild propagates
|
|
181
|
+
* Run one bounded final-gate fix attempt: snapshot discovery and ignored paths →
|
|
182
|
+
* child → frozen-path revert → deletion guard → shrink guard → scope-shrink
|
|
183
|
+
* guard → probe scan → gate re-run. Never throws for an outcome; only a user
|
|
184
|
+
* cancel inside runChild propagates, and the caller's USER_CANCELLED path
|
|
185
|
+
* handles that.
|
|
205
186
|
*/
|
|
206
187
|
export async function runFinalGateAutofix(deps) {
|
|
207
188
|
const before = deps.discoverLabels(deps.cwd);
|
|
@@ -210,7 +191,7 @@ export async function runFinalGateAutofix(deps) {
|
|
|
210
191
|
// ignored files are untracked, so git alone cannot tell a file this pass wrote
|
|
211
192
|
// from one that was already sitting in the worktree.
|
|
212
193
|
const ignoredBefore = deps.ignoredSnapshot ? await deps.ignoredSnapshot() : null;
|
|
213
|
-
// The
|
|
194
|
+
// The child ladder is task/fix-child.ts, shared with the per-task pass.
|
|
214
195
|
const end = await runFixChild({
|
|
215
196
|
runChild: deps.runChild,
|
|
216
197
|
tools: FINAL_FIX_TOOLS,
|
|
@@ -241,12 +222,13 @@ export async function runFinalGateAutofix(deps) {
|
|
|
241
222
|
guardTripped: true,
|
|
242
223
|
editsDiscarded: deps.discard !== undefined
|
|
243
224
|
});
|
|
244
|
-
// (Diff capture — what the pass changed, durably — happens
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
225
|
+
// (Diff capture — what the pass changed, durably — happens in gate-child.ts,
|
|
226
|
+
// which logs the tree changes of any child whose TOOLS include edit/bash/
|
|
227
|
+
// write; here only the guards act on them.)
|
|
228
|
+
// FROZEN-PATH WRITE-DENY: undo the child's edits to any path a task's spec
|
|
229
|
+
// froze, before anything downstream can act on them — the same mechanical
|
|
230
|
+
// revert the per-task passes carry, not prompt framing. Non-fatal: the rest
|
|
231
|
+
// of the fix survives, only the frozen edits are undone.
|
|
250
232
|
if (deps.frozenPaths && deps.revertFrozen) {
|
|
251
233
|
const frozen = await deps.frozenPaths();
|
|
252
234
|
if (frozen.length > 0) {
|
|
@@ -256,8 +238,10 @@ export async function runFinalGateAutofix(deps) {
|
|
|
256
238
|
}
|
|
257
239
|
}
|
|
258
240
|
}
|
|
259
|
-
// DELETION GUARD (post-revert state): a tracked file the pass deleted
|
|
260
|
-
//
|
|
241
|
+
// DELETION GUARD (post-revert state): a tracked file the pass deleted is a
|
|
242
|
+
// completed task's committed deliverable destroyed — reject the attempt. A
|
|
243
|
+
// deletion paired with an added file of the SAME BASENAME is a relocation and
|
|
244
|
+
// passes, as do the regenerable artifacts write-guard.ts exempts.
|
|
261
245
|
const changes = deps.treeChanges ? await deps.treeChanges() : null;
|
|
262
246
|
if (changes) {
|
|
263
247
|
const gone = findForbiddenDeletions(changes);
|
|
@@ -280,14 +264,12 @@ export async function runFinalGateAutofix(deps) {
|
|
|
280
264
|
await deps.discard(deps.cwd);
|
|
281
265
|
return rejected(`fix pass removed the gate's own command(s) (${vanished.join(', ')})`);
|
|
282
266
|
}
|
|
283
|
-
// SCOPE-SHRINK GUARD
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
// the
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
// mechanical shapes, measured at 3 hits in 274 manifest-touching corpus
|
|
290
|
-
// commits, all three read by hand as real narrowings).
|
|
267
|
+
// SCOPE-SHRINK GUARD: the label surviving is not enough. A child can keep
|
|
268
|
+
// `bun run test` and rewrite its BODY to run a subdirectory instead of the
|
|
269
|
+
// repository — the set difference above stays empty while the suite stops
|
|
270
|
+
// covering what the gate is meant to measure, and the re-run then goes green
|
|
271
|
+
// and reports "converged". So compare the resolved bodies too
|
|
272
|
+
// (command-shrink.ts holds the mechanical narrowing shapes).
|
|
291
273
|
if (deps.discoverBodies) {
|
|
292
274
|
const addedByFix = new Set((changes?.added ?? []).map(p => p.replace(/^\.\//, '')));
|
|
293
275
|
const narrowed = findNarrowedCommands(bodiesBefore, deps.discoverBodies(deps.cwd), {
|
|
@@ -304,10 +286,10 @@ export async function runFinalGateAutofix(deps) {
|
|
|
304
286
|
return r;
|
|
305
287
|
}
|
|
306
288
|
}
|
|
307
|
-
// PROBE SCAN
|
|
308
|
-
// rather than meet the requirement reject the attempt
|
|
309
|
-
//
|
|
310
|
-
//
|
|
289
|
+
// PROBE SCAN: added lines whose own stated purpose is to make a check pass
|
|
290
|
+
// rather than meet the requirement reject the attempt. Nothing downstream of
|
|
291
|
+
// this pass would judge such a finding — the gate re-run only sees exit
|
|
292
|
+
// codes.
|
|
311
293
|
if (deps.probeScan) {
|
|
312
294
|
const findings = await deps.probeScan();
|
|
313
295
|
if (findings.length > 0) {
|
|
@@ -326,15 +308,14 @@ export async function runFinalGateAutofix(deps) {
|
|
|
326
308
|
if (!fin.ok) {
|
|
327
309
|
return withIgnored({ ok: false, reason: `did not converge: ${fin.reason}`, gate: fin });
|
|
328
310
|
}
|
|
329
|
-
// IGNORED-DEPENDENCY DOWNGRADE
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
// overwhelming majority — 1 of 68 recorded child logs) pays nothing.
|
|
311
|
+
// IGNORED-DEPENDENCY DOWNGRADE. The gate says PASS; this decides whether the
|
|
312
|
+
// PASS belongs to the REPOSITORY or only to this worktree. Mechanical, never
|
|
313
|
+
// judgement: move the ignored files the pass wrote aside, re-run the gate
|
|
314
|
+
// once, put them back. Still passing ⇒ incidental, the PASS stands. Failing ⇒
|
|
315
|
+
// the checks were passing on state no fresh clone has, which is UNOBSERVED
|
|
316
|
+
// (final-gate.ts unobservedVerdict), not a FAIL — the fix is real, it just
|
|
317
|
+
// did not ship. Guarded on a non-empty `ignoredWrites`, so a pass that wrote
|
|
318
|
+
// no ignored paths runs no extra gate.
|
|
338
319
|
let ignoredDependent;
|
|
339
320
|
if (ignoredWrites.length > 0 && deps.gateWithoutIgnored) {
|
|
340
321
|
const passesWithout = await deps.gateWithoutIgnored(ignoredWrites);
|