@deftai/directive-core 0.104.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authz/classify.js +1108 -67
- package/dist/check/cached-orchestrator.d.ts +1 -1
- package/dist/check/cached-orchestrator.js +2 -2
- package/dist/check/named-cause.d.ts +1 -1
- package/dist/check/named-cause.js +34 -4
- package/dist/codebase/default-extractor.d.ts +5 -0
- package/dist/codebase/default-extractor.js +7 -15
- package/dist/deposit/copy-tree.js +60 -0
- package/dist/deposit/python-free.js +26 -18
- package/dist/doctor/checks.d.ts +8 -0
- package/dist/doctor/checks.js +37 -25
- package/dist/doctor/doctor-state.d.ts +4 -0
- package/dist/doctor/doctor-state.js +7 -1
- package/dist/doctor/main.js +9 -19
- package/dist/doctor/types.d.ts +9 -0
- package/dist/forward-coverage/diff-coverage.d.ts +39 -0
- package/dist/forward-coverage/diff-coverage.js +112 -0
- package/dist/forward-coverage/diff-lines.d.ts +19 -0
- package/dist/forward-coverage/diff-lines.js +173 -0
- package/dist/forward-coverage/evaluate.d.ts +24 -9
- package/dist/forward-coverage/evaluate.js +125 -19
- package/dist/fs/contained-write.d.ts +115 -1
- package/dist/fs/contained-write.js +241 -5
- package/dist/fs/mutation-ledger.d.ts +54 -0
- package/dist/fs/mutation-ledger.js +133 -0
- package/dist/fs/non-product-dirs.d.ts +79 -0
- package/dist/fs/non-product-dirs.js +96 -0
- package/dist/hooks/dispatcher.d.ts +3 -1
- package/dist/hooks/dispatcher.js +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/agent-hooks.d.ts +1 -1
- package/dist/init-deposit/agent-hooks.js +18 -16
- package/dist/init-deposit/core-guard-pin-content.d.ts +7 -0
- package/dist/init-deposit/core-guard-pin-content.js +393 -0
- package/dist/init-deposit/gitignore.js +9 -0
- package/dist/init-deposit/hygiene.d.ts +47 -11
- package/dist/init-deposit/hygiene.js +172 -37
- package/dist/init-deposit/legacy-detect.js +6 -2
- package/dist/init-deposit/refresh.d.ts +21 -1
- package/dist/init-deposit/refresh.js +106 -9
- package/dist/init-deposit/scaffold.js +28 -279
- package/dist/init-deposit/slash-deposit.js +13 -7
- package/dist/init-deposit/xbrief-projections.d.ts +8 -1
- package/dist/init-deposit/xbrief-projections.js +24 -11
- package/dist/intake/clause-derivation.d.ts +47 -1
- package/dist/intake/clause-derivation.js +238 -9
- package/dist/intake/issue-ingest.d.ts +3 -1
- package/dist/intake/issue-ingest.js +35 -6
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +5 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +85 -18
- package/dist/lifecycle-visible/evaluate.d.ts +98 -0
- package/dist/lifecycle-visible/evaluate.js +710 -0
- package/dist/lifecycle-visible/index.d.ts +2 -0
- package/dist/lifecycle-visible/index.js +2 -0
- package/dist/literal-acceptance/capture.d.ts +10 -0
- package/dist/literal-acceptance/capture.js +226 -77
- package/dist/literal-acceptance/evaluate.d.ts +29 -4
- package/dist/literal-acceptance/evaluate.js +70 -2
- package/dist/literal-acceptance/index.d.ts +3 -3
- package/dist/literal-acceptance/index.js +3 -3
- package/dist/literal-acceptance/safety.d.ts +41 -0
- package/dist/literal-acceptance/safety.js +126 -2
- package/dist/literal-acceptance/types.d.ts +8 -0
- package/dist/orchestration/judgment-policy.d.ts +13 -0
- package/dist/orchestration/judgment-policy.js +15 -0
- package/dist/orchestration/probe-session.js +13 -8
- package/dist/orchestration/verify-judgment-gates.d.ts +4 -0
- package/dist/orchestration/verify-judgment-gates.js +43 -11
- package/dist/orphan-active/evaluate.d.ts +7 -1
- package/dist/orphan-active/evaluate.js +102 -23
- package/dist/platform/platform-capabilities.js +2 -3
- package/dist/policy/base-branch.d.ts +37 -0
- package/dist/policy/base-branch.js +114 -0
- package/dist/policy/branch-sync.d.ts +80 -0
- package/dist/policy/branch-sync.js +211 -0
- package/dist/policy/ceremony-dial-escalation.js +1 -0
- package/dist/policy/ceremony-dial.js +11 -21
- package/dist/policy/delivery-branch.d.ts +5 -3
- package/dist/policy/delivery-branch.js +7 -3
- package/dist/policy/file-size-thresholds.d.ts +24 -0
- package/dist/policy/file-size-thresholds.js +23 -0
- package/dist/policy/forge-outage-retry.d.ts +47 -0
- package/dist/policy/forge-outage-retry.js +157 -0
- package/dist/policy/host-hooks.d.ts +20 -0
- package/dist/policy/host-hooks.js +121 -2
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.js +66 -7
- package/dist/policy/org-force-on-migration.js +2 -1
- package/dist/policy/plan-extensions.d.ts +1 -1
- package/dist/policy/plan-extensions.js +2 -0
- package/dist/policy/product-signal.js +6 -7
- package/dist/policy/project-invariants.d.ts +50 -0
- package/dist/policy/project-invariants.js +205 -0
- package/dist/policy/require-human-merge.js +8 -6
- package/dist/policy/resolve.d.ts +7 -2
- package/dist/policy/resolve.js +25 -8
- package/dist/policy/sync-default.d.ts +129 -0
- package/dist/policy/sync-default.js +452 -0
- package/dist/policy/sync-max-files.d.ts +93 -0
- package/dist/policy/sync-max-files.js +192 -0
- package/dist/policy/value-feedback.js +7 -8
- package/dist/pr-monitor/absent-required.d.ts +11 -0
- package/dist/pr-monitor/absent-required.js +61 -0
- package/dist/pr-monitor/constants.d.ts +7 -0
- package/dist/pr-monitor/constants.js +7 -0
- package/dist/pr-monitor/index.d.ts +2 -1
- package/dist/pr-monitor/index.js +2 -1
- package/dist/pr-monitor/main.js +4 -0
- package/dist/pr-monitor/monitor.js +24 -1
- package/dist/pr-wait-mergeable/classify.js +6 -0
- package/dist/preflight/evaluate.d.ts +4 -0
- package/dist/preflight/evaluate.js +35 -1
- package/dist/preflight/index.d.ts +4 -0
- package/dist/preflight/index.js +2 -0
- package/dist/preflight/intended-placement.d.ts +62 -0
- package/dist/preflight/intended-placement.js +275 -0
- package/dist/preflight/project-invariants-gate.d.ts +29 -0
- package/dist/preflight/project-invariants-gate.js +82 -0
- package/dist/preflight-cache/evaluate.d.ts +12 -0
- package/dist/preflight-cache/evaluate.js +15 -1
- package/dist/preflight-cache/index.d.ts +1 -1
- package/dist/preflight-cache/index.js +1 -1
- package/dist/product-first-done-gate/acceptance-resolver.d.ts +128 -0
- package/dist/product-first-done-gate/acceptance-resolver.js +144 -0
- package/dist/product-first-done-gate/acceptance.d.ts +7 -4
- package/dist/product-first-done-gate/acceptance.js +79 -8
- package/dist/product-first-done-gate/empty-resolution.d.ts +4 -1
- package/dist/product-first-done-gate/empty-resolution.js +12 -1
- package/dist/product-first-done-gate/evaluate.d.ts +16 -0
- package/dist/product-first-done-gate/evaluate.js +298 -34
- package/dist/product-first-done-gate/index.d.ts +2 -0
- package/dist/product-first-done-gate/index.js +1 -0
- package/dist/release/build-dist.d.ts +101 -0
- package/dist/release/build-dist.js +428 -46
- package/dist/release/closed-verb-gate.d.ts +12 -0
- package/dist/release/closed-verb-gate.js +51 -0
- package/dist/release/index.d.ts +1 -0
- package/dist/release/index.js +1 -0
- package/dist/release/pipeline.js +7 -0
- package/dist/release/types.d.ts +12 -0
- package/dist/render/constants.d.ts +2 -1
- package/dist/render/constants.js +2 -1
- package/dist/render/framework-commands.js +4 -0
- package/dist/render/spec-validate.js +23 -12
- package/dist/run-summary/emit.d.ts +16 -10
- package/dist/run-summary/emit.js +26 -15
- package/dist/run-summary/index.d.ts +3 -2
- package/dist/run-summary/index.js +2 -1
- package/dist/run-summary/session-id.d.ts +21 -0
- package/dist/run-summary/session-id.js +92 -0
- package/dist/run-summary/types.d.ts +33 -4
- package/dist/run-summary/types.js +1 -0
- package/dist/scope/acceptance-evidence.d.ts +19 -7
- package/dist/scope/acceptance-evidence.js +38 -11
- package/dist/scope/delivery-evidence.d.ts +3 -3
- package/dist/scope/delivery-evidence.js +22 -27
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/main.js +15 -5
- package/dist/scope/parent-lineage.js +7 -6
- package/dist/scope/project-invariant-coverage.d.ts +54 -0
- package/dist/scope/project-invariant-coverage.js +322 -0
- package/dist/scope/promote-from-issue.js +5 -5
- package/dist/scope/transition.js +1 -1
- package/dist/scope-provenance/compare-intent.d.ts +27 -0
- package/dist/scope-provenance/compare-intent.js +233 -0
- package/dist/scope-provenance/digest.d.ts +18 -1
- package/dist/scope-provenance/digest.js +16 -11
- package/dist/scope-provenance/evaluate.d.ts +5 -1
- package/dist/scope-provenance/evaluate.js +67 -7
- package/dist/scope-provenance/extract-intent.d.ts +43 -0
- package/dist/scope-provenance/extract-intent.js +262 -0
- package/dist/scope-provenance/index.d.ts +7 -1
- package/dist/scope-provenance/index.js +7 -1
- package/dist/scope-provenance/intent-digest.d.ts +12 -0
- package/dist/scope-provenance/intent-digest.js +33 -0
- package/dist/scope-provenance/intent-evaluate.d.ts +43 -0
- package/dist/scope-provenance/intent-evaluate.js +149 -0
- package/dist/scope-provenance/json-tokenizer.d.ts +19 -0
- package/dist/scope-provenance/json-tokenizer.js +225 -0
- package/dist/scope-provenance/known-machine.d.ts +38 -0
- package/dist/scope-provenance/known-machine.js +157 -0
- package/dist/scope-provenance/mint-artifacts.d.ts +102 -0
- package/dist/scope-provenance/mint-artifacts.js +425 -0
- package/dist/session/ac-pass-banking.d.ts +9 -36
- package/dist/session/ac-pass-banking.js +33 -79
- package/dist/session/ac-pass-reuse.d.ts +53 -0
- package/dist/session/ac-pass-reuse.js +95 -0
- package/dist/session/git.js +19 -4
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.js +4 -0
- package/dist/session/occupancy-stress-worker.d.ts +7 -0
- package/dist/session/occupancy-stress-worker.js +36 -0
- package/dist/session/occupancy.d.ts +97 -0
- package/dist/session/occupancy.js +422 -0
- package/dist/session/openclaw-soft-rebind-deposit.js +6 -6
- package/dist/session/process-cost.d.ts +32 -10
- package/dist/session/process-cost.js +189 -1
- package/dist/session/product-state-hash.d.ts +26 -0
- package/dist/session/product-state-hash.js +700 -0
- package/dist/session/ritual-entrypoint.js +16 -1
- package/dist/session/session-ready.d.ts +2 -0
- package/dist/session/session-ready.js +52 -30
- package/dist/session/session-start.d.ts +13 -0
- package/dist/session/session-start.js +103 -9
- package/dist/session/verify-ac-session-cache.d.ts +42 -0
- package/dist/session/verify-ac-session-cache.js +126 -0
- package/dist/session/verify-session-ritual.d.ts +28 -0
- package/dist/session/verify-session-ritual.js +97 -5
- package/dist/slash/openclaw-deposit.js +13 -9
- package/dist/slice/constants.d.ts +2 -2
- package/dist/slice/constants.js +2 -2
- package/dist/slice/existing.js +9 -3
- package/dist/slice/lock.d.ts +16 -1
- package/dist/slice/lock.js +137 -11
- package/dist/story-ready/evaluate.d.ts +2 -0
- package/dist/story-ready/evaluate.js +13 -0
- package/dist/swarm/complete-cohort.d.ts +3 -0
- package/dist/swarm/complete-cohort.js +59 -11
- package/dist/swarm/finalize-cohort-cli.d.ts +7 -2
- package/dist/swarm/finalize-cohort-cli.js +165 -35
- package/dist/swarm/finalize-cohort.d.ts +1 -0
- package/dist/swarm/finalize-cohort.js +47 -4
- package/dist/swarm/launch.d.ts +22 -0
- package/dist/swarm/launch.js +155 -0
- package/dist/swarm/routing-set-cli.d.ts +11 -1
- package/dist/swarm/routing-set-cli.js +15 -3
- package/dist/swarm/routing-verify.d.ts +13 -1
- package/dist/swarm/routing-verify.js +60 -21
- package/dist/swarm/routing.d.ts +14 -0
- package/dist/swarm/routing.js +53 -3
- package/dist/telemetry-coverage/fake-trial.js +10 -0
- package/dist/telemetry-coverage/kinds.js +2 -0
- package/dist/triage/actions/index.js +4 -1
- package/dist/triage/bootstrap/index.js +6 -6
- package/dist/triage/help/registry-data.d.ts +1 -1
- package/dist/triage/help/registry-data.js +1 -1
- package/dist/triage/welcome/writers.d.ts +1 -1
- package/dist/triage/welcome/writers.js +10 -5
- package/dist/ts-check-lane/index.d.ts +3 -0
- package/dist/ts-check-lane/index.js +2 -0
- package/dist/ts-check-lane/progress-reporter.d.ts +17 -0
- package/dist/ts-check-lane/progress-reporter.js +38 -0
- package/dist/ts-check-lane/progress.d.ts +32 -0
- package/dist/ts-check-lane/progress.js +57 -0
- package/dist/ts-check-lane/run-lane.d.ts +3 -1
- package/dist/ts-check-lane/run-lane.js +8 -6
- package/dist/validate-content/validate-links.d.ts +8 -0
- package/dist/validate-content/validate-links.js +9 -15
- package/dist/value/feedback-file.js +12 -2
- package/dist/value/readback.d.ts +4 -1
- package/dist/value/readback.js +51 -12
- package/dist/vbrief-build/index.d.ts +1 -0
- package/dist/vbrief-build/index.js +1 -0
- package/dist/vbrief-build/project-invariants-io.d.ts +16 -0
- package/dist/vbrief-build/project-invariants-io.js +41 -0
- package/dist/vbrief-reconcile/graph.js +18 -1
- package/dist/vbrief-reconcile/index.d.ts +1 -1
- package/dist/vbrief-reconcile/index.js +1 -1
- package/dist/vbrief-reconcile/types.d.ts +13 -0
- package/dist/vbrief-reconcile/umbrellas.d.ts +14 -0
- package/dist/vbrief-reconcile/umbrellas.js +261 -26
- package/dist/vbrief-validate/index.d.ts +1 -1
- package/dist/vbrief-validate/index.js +1 -1
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +68 -0
- package/dist/vbrief-validate/schema.d.ts +4 -0
- package/dist/vbrief-validate/schema.js +1 -1
- package/dist/verify-ac/evaluate.d.ts +7 -1
- package/dist/verify-ac/evaluate.js +34 -26
- package/dist/verify-ac/flag.d.ts +4 -0
- package/dist/verify-ac/flag.js +16 -0
- package/dist/verify-ac/index.d.ts +2 -2
- package/dist/verify-ac/index.js +2 -2
- package/dist/verify-env/agent-hook-readiness.d.ts +2 -2
- package/dist/verify-env/agent-hook-readiness.js +12 -8
- package/dist/verify-env/agent-hooks-live-probe.d.ts +5 -1
- package/dist/verify-env/agent-hooks-live-probe.js +26 -5
- package/dist/verify-env/agent-hooks.js +3 -4
- package/dist/verify-source/contained-writes.js +2 -0
- package/dist/verify-source/verify-stubs.d.ts +15 -1
- package/dist/verify-source/verify-stubs.js +20 -16
- package/dist/vitest-runner/win32-coverage-tmp-setup.d.ts +5 -6
- package/dist/vitest-runner/win32-coverage-tmp-setup.js +5 -6
- package/dist/xbrief-migrate/migrate-project.js +2 -5
- package/package.json +7 -3
|
@@ -46,12 +46,27 @@ function parseProjectRoot(argv) {
|
|
|
46
46
|
}
|
|
47
47
|
return ".";
|
|
48
48
|
}
|
|
49
|
+
function parseOptionalForIssue(argv) {
|
|
50
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
51
|
+
if (argv[i] !== "--for-issue")
|
|
52
|
+
continue;
|
|
53
|
+
const next = argv[i + 1];
|
|
54
|
+
if (next === undefined || next.startsWith("-"))
|
|
55
|
+
return null;
|
|
56
|
+
const parsed = Number.parseInt(next, 10);
|
|
57
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
49
61
|
/** CLI-shaped cache-fresh entrypoint (mirrors scripts/preflight_cache.py main). */
|
|
50
62
|
export function runCacheFreshMain(argv) {
|
|
51
63
|
const projectRoot = parseProjectRoot(argv);
|
|
52
64
|
const allowMissingBootstrap = argv.includes("--allow-missing-bootstrap");
|
|
53
65
|
const quiet = argv.includes("--quiet");
|
|
54
|
-
const
|
|
66
|
+
const workSelection = argv.includes("--work-selection");
|
|
67
|
+
const skipDriftProbe = argv.includes("--skip-drift-probe") && !workSelection;
|
|
68
|
+
const forIssue = parseOptionalForIssue(argv);
|
|
69
|
+
const result = evaluate(projectRoot, { allowMissingBootstrap, skipDriftProbe, forIssue });
|
|
55
70
|
if (result.code === 0) {
|
|
56
71
|
if (!quiet) {
|
|
57
72
|
if (result.message.startsWith("⚠")) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* remaining hard blocker is printed once).
|
|
13
13
|
*/
|
|
14
14
|
import type { GitRunner } from "./git.js";
|
|
15
|
+
import { type ApplyOccupancyInput, type OccupancyDecision } from "./occupancy.js";
|
|
15
16
|
import { type SessionStartOptions, type SessionStartResult } from "./session-start.js";
|
|
16
17
|
import { type InspectSessionRitualOptions, type RitualRunner, type VerifyResult, type VerifySessionRitualOptions } from "./verify-session-ritual.js";
|
|
17
18
|
export declare const SESSION_READY_FAST_PATH = "fast";
|
|
@@ -45,6 +46,7 @@ export interface SessionReadyOptions {
|
|
|
45
46
|
readonly inspectRitual?: (projectRoot: string, options: InspectSessionRitualOptions) => VerifyResult;
|
|
46
47
|
readonly verifyRitual?: (projectRoot: string, options: VerifySessionRitualOptions) => VerifyResult;
|
|
47
48
|
readonly runStart?: (projectRoot: string, options: SessionStartOptions) => SessionStartResult;
|
|
49
|
+
readonly applyOccupancy?: (projectRoot: string, input: ApplyOccupancyInput) => OccupancyDecision;
|
|
48
50
|
readonly fetchAll?: CacheFetchAllSeam;
|
|
49
51
|
readonly inferRepo?: (projectRoot: string) => string | null;
|
|
50
52
|
/** Skip cache recovery even when cache_fresh failed (tests). */
|
|
@@ -15,6 +15,7 @@ import { execFileSync } from "node:child_process";
|
|
|
15
15
|
import { join } from "node:path";
|
|
16
16
|
import { cacheFetchAll } from "../cache/fetch.js";
|
|
17
17
|
import { formatFrameworkCommand } from "../render/framework-commands.js";
|
|
18
|
+
import { applyWorktreeOccupancy, } from "./occupancy.js";
|
|
18
19
|
import { runSessionStart, } from "./session-start.js";
|
|
19
20
|
import { inspectSessionRitual, verifySessionRitual, } from "./verify-session-ritual.js";
|
|
20
21
|
export const SESSION_READY_FAST_PATH = "fast";
|
|
@@ -95,6 +96,54 @@ export function runSessionReady(projectRoot, options = {}) {
|
|
|
95
96
|
const start = options.runStart ?? runSessionStart;
|
|
96
97
|
const fetchAll = options.fetchAll ?? cacheFetchAll;
|
|
97
98
|
const inferRepo = options.inferRepo ?? ((root) => inferSessionReadyRepo(root, env));
|
|
99
|
+
const applyOccupancy = options.applyOccupancy ?? applyWorktreeOccupancy;
|
|
100
|
+
const occupancyInput = (write) => ({
|
|
101
|
+
env,
|
|
102
|
+
now,
|
|
103
|
+
steal: options.sessionStartOptions?.steal,
|
|
104
|
+
confirm: options.sessionStartOptions?.confirm,
|
|
105
|
+
occupant: options.sessionStartOptions?.occupant,
|
|
106
|
+
newSessionId: options.sessionStartOptions?.newSessionId,
|
|
107
|
+
intent: options.sessionStartOptions?.occupancyIntent ?? "mutation",
|
|
108
|
+
write,
|
|
109
|
+
});
|
|
110
|
+
const previewOccupancy = applyOccupancy(projectRoot, occupancyInput(false));
|
|
111
|
+
if (previewOccupancy.code !== 0) {
|
|
112
|
+
const message = previewOccupancy.message;
|
|
113
|
+
lines.push(message);
|
|
114
|
+
return {
|
|
115
|
+
code: previewOccupancy.code,
|
|
116
|
+
message,
|
|
117
|
+
path: SESSION_READY_FAILED,
|
|
118
|
+
lines,
|
|
119
|
+
steps,
|
|
120
|
+
duration_ms: elapsedMs(started),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const claimOnSuccess = () => applyOccupancy(projectRoot, occupancyInput(true));
|
|
124
|
+
const finishReady = (path, message) => {
|
|
125
|
+
const claimed = claimOnSuccess();
|
|
126
|
+
if (claimed.code !== 0) {
|
|
127
|
+
lines.push(claimed.message);
|
|
128
|
+
return {
|
|
129
|
+
code: claimed.code,
|
|
130
|
+
message: claimed.message,
|
|
131
|
+
path: SESSION_READY_FAILED,
|
|
132
|
+
lines,
|
|
133
|
+
steps,
|
|
134
|
+
duration_ms: elapsedMs(started),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
lines.push(message);
|
|
138
|
+
return {
|
|
139
|
+
code: 0,
|
|
140
|
+
message,
|
|
141
|
+
path,
|
|
142
|
+
lines,
|
|
143
|
+
steps,
|
|
144
|
+
duration_ms: elapsedMs(started),
|
|
145
|
+
};
|
|
146
|
+
};
|
|
98
147
|
const verifyOpts = {
|
|
99
148
|
tier: "gated",
|
|
100
149
|
posture: "mutation",
|
|
@@ -127,16 +176,7 @@ export function runSessionReady(projectRoot, options = {}) {
|
|
|
127
176
|
duration_ms: elapsedMs(started),
|
|
128
177
|
};
|
|
129
178
|
}
|
|
130
|
-
|
|
131
|
-
lines.push(message);
|
|
132
|
-
return {
|
|
133
|
-
code: 0,
|
|
134
|
-
message,
|
|
135
|
-
path: SESSION_READY_FAST_PATH,
|
|
136
|
-
lines,
|
|
137
|
-
steps,
|
|
138
|
-
duration_ms: elapsedMs(started),
|
|
139
|
-
};
|
|
179
|
+
return finishReady(SESSION_READY_FAST_PATH, "OK session ready (gated ritual already fresh).");
|
|
140
180
|
}
|
|
141
181
|
// --- Ensure quick-tier ritual state when missing / stale / drifted ---
|
|
142
182
|
const quickInspect = inspect(projectRoot, {
|
|
@@ -175,16 +215,7 @@ export function runSessionReady(projectRoot, options = {}) {
|
|
|
175
215
|
steps.push("verify:session-ritual:gated");
|
|
176
216
|
let verifyResult = verify(projectRoot, verifyOpts);
|
|
177
217
|
if (isGatedVerifyActuallyReady(verifyResult)) {
|
|
178
|
-
|
|
179
|
-
lines.push(message);
|
|
180
|
-
return {
|
|
181
|
-
code: 0,
|
|
182
|
-
message,
|
|
183
|
-
path: SESSION_READY_VERIFIED,
|
|
184
|
-
lines,
|
|
185
|
-
steps,
|
|
186
|
-
duration_ms: elapsedMs(started),
|
|
187
|
-
};
|
|
218
|
+
return finishReady(SESSION_READY_VERIFIED, "OK session ready (gated ritual verified).");
|
|
188
219
|
}
|
|
189
220
|
if (verifyResult.code === 0 && verifyResult.bypassed) {
|
|
190
221
|
const message = bypassedReadyFailure(verifyResult);
|
|
@@ -241,16 +272,7 @@ export function runSessionReady(projectRoot, options = {}) {
|
|
|
241
272
|
steps.push("verify:session-ritual:gated:retry");
|
|
242
273
|
verifyResult = verify(projectRoot, { ...verifyOpts, forceGatedSteps: [] });
|
|
243
274
|
if (isGatedVerifyActuallyReady(verifyResult)) {
|
|
244
|
-
|
|
245
|
-
lines.push(message);
|
|
246
|
-
return {
|
|
247
|
-
code: 0,
|
|
248
|
-
message,
|
|
249
|
-
path: SESSION_READY_RECOVERED,
|
|
250
|
-
lines,
|
|
251
|
-
steps,
|
|
252
|
-
duration_ms: elapsedMs(started),
|
|
253
|
-
};
|
|
275
|
+
return finishReady(SESSION_READY_RECOVERED, "OK session ready (recovered via cache refresh).");
|
|
254
276
|
}
|
|
255
277
|
if (verifyResult.code === 0 && verifyResult.bypassed) {
|
|
256
278
|
const message = bypassedReadyFailure(verifyResult);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type LifecycleVisibleResult } from "../lifecycle-visible/evaluate.js";
|
|
1
2
|
import { type HostContentSurfaceSeams } from "../platform/host-content-surface.js";
|
|
2
3
|
import { type EnvironmentContext } from "../platform/shell-context.js";
|
|
3
4
|
import { type CeremonyDialInputs, type CeremonyDialSelection, type ProvisionalCeremonyEstimateHints } from "../policy/ceremony-dial.js";
|
|
@@ -6,6 +7,7 @@ import { type ProbeScmReadinessOptions, type ScmReadinessReport } from "../scm/r
|
|
|
6
7
|
import { type ResolveUserMdResult } from "../user-config/resolve-user-md.js";
|
|
7
8
|
import { type DetectHardEffortBudgetInput } from "./effort-budget.js";
|
|
8
9
|
import type { GitRunner } from "./git.js";
|
|
10
|
+
import { type ApplyOccupancyInput, type OccupancyDecision } from "./occupancy.js";
|
|
9
11
|
import { type OrientationBundle, type RunOrientationOptions } from "./orientation-compression.js";
|
|
10
12
|
import { type ReleaseAvailabilityProbeOptions } from "./release-availability.js";
|
|
11
13
|
import { type RitualState, ritualStatePath } from "./ritual-sentinel.js";
|
|
@@ -63,6 +65,12 @@ export interface SessionStartOptions {
|
|
|
63
65
|
readonly writeHistory?: boolean;
|
|
64
66
|
readonly runGit?: GitRunner;
|
|
65
67
|
readonly newSessionId?: () => string;
|
|
68
|
+
/** #3433: steal the worktree occupancy lease. Requires confirm + occupant. */
|
|
69
|
+
readonly steal?: boolean;
|
|
70
|
+
readonly confirm?: boolean;
|
|
71
|
+
readonly occupant?: string;
|
|
72
|
+
readonly occupancyIntent?: ApplyOccupancyInput["intent"];
|
|
73
|
+
readonly applyOccupancy?: (projectRoot: string, input: ApplyOccupancyInput) => OccupancyDecision;
|
|
66
74
|
readonly runTriageWelcome?: (projectRoot: string, options: {
|
|
67
75
|
writeHistory: boolean;
|
|
68
76
|
now: Date;
|
|
@@ -110,6 +118,11 @@ export interface SessionStartOptions {
|
|
|
110
118
|
* network is enabled. Inject in tests.
|
|
111
119
|
*/
|
|
112
120
|
readonly probeScm?: (options: ProbeScmReadinessOptions) => ScmReadinessReport;
|
|
121
|
+
/**
|
|
122
|
+
* #3505: per-clone lifecycle-root visibility (ignore / skip-worktree).
|
|
123
|
+
* Warn-only; never blocks session:start. Inject in tests.
|
|
124
|
+
*/
|
|
125
|
+
readonly probeLifecycleVisible?: (projectRoot: string, runGit: GitRunner) => LifecycleVisibleResult;
|
|
113
126
|
/**
|
|
114
127
|
* #3214: ceremony dial inputs (task size × model tier × project shape).
|
|
115
128
|
* Missing fields are filled by the headless provisional classifier
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
1
|
import { runningInsideDeftRepo } from "../doctor/paths.js";
|
|
3
2
|
import { emitSessionEvalReadback } from "../eval/readback.js";
|
|
4
3
|
import { bindSessionGeneration } from "../freshness/bind.js";
|
|
5
4
|
import { readLiveGeneration } from "../freshness/generation.js";
|
|
6
5
|
import { MIGRATE_COMPLETION_NUDGE, shouldEmitMigrateNudge } from "../init-deposit/migrate.js";
|
|
6
|
+
import { evaluateLifecycleVisible, formatLifecycleVisibleSessionLines, } from "../lifecycle-visible/evaluate.js";
|
|
7
7
|
import { hostContentSurfaceToDict, maybeFormatHostContentSurfaceLines, } from "../platform/host-content-surface.js";
|
|
8
8
|
import { detectEnvironmentContext, environmentContextToDict, formatEnvironmentContext, } from "../platform/shell-context.js";
|
|
9
9
|
import { ceremonyDialToDict, formatCeremonyDialStatusLine, mergeCeremonyDialDeferrals, resolveCeremonyDial, resolveSessionCeremonyDialInputs, } from "../policy/ceremony-dial.js";
|
|
@@ -26,8 +26,9 @@ import { verifyRequiredTools } from "../verify-env/verify-tools.js";
|
|
|
26
26
|
import { ceremonyDialEvidenceToDict, collectCeremonyDialConsumerEvidence, formatCeremonyDialEvidenceLine, mergeCeremonyDialInputsWithConsumerEvidence, } from "./ceremony-dial-evidence.js";
|
|
27
27
|
import { effortBudgetToDict, maybeFormatEffortBudgetLines, resolveProductionHostEffortDescriptor, } from "./effort-budget.js";
|
|
28
28
|
import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
29
|
+
import { applyWorktreeOccupancy, } from "./occupancy.js";
|
|
30
|
+
import { resolveSessionCompact, runOrientationCompression, } from "./orientation-compression.js";
|
|
31
|
+
import { emitSessionStartProcessCost, formatSessionStartCeremonyCostLine } from "./process-cost.js";
|
|
31
32
|
import { probeSessionReleaseAvailability, } from "./release-availability.js";
|
|
32
33
|
import { newRitualStatePayload, readRitualState, ritualStatePath, ritualStep, writeRitualState, } from "./ritual-sentinel.js";
|
|
33
34
|
import { timestampIso } from "./time.js";
|
|
@@ -50,6 +51,18 @@ export const QUICK_STEPS = [
|
|
|
50
51
|
"verify_tools",
|
|
51
52
|
];
|
|
52
53
|
export const GATED_STEPS = ["agent_hooks", "doctor", "cache_fresh"];
|
|
54
|
+
/** Per-clone ignore/index hide of lifecycle roots — warn-only (#3505). */
|
|
55
|
+
function pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit) {
|
|
56
|
+
try {
|
|
57
|
+
const probe = options.probeLifecycleVisible ??
|
|
58
|
+
((root, git) => evaluateLifecycleVisible({ projectRoot: root, runGit: git }));
|
|
59
|
+
const result = probe(projectRoot, runGit);
|
|
60
|
+
lines.push(...formatLifecycleVisibleSessionLines(result));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// best-effort — session:start must not abort on a clone-local advisory
|
|
64
|
+
}
|
|
65
|
+
}
|
|
53
66
|
/** Standing one-liner when coverageDebt/checkResume is non-default (#3314). */
|
|
54
67
|
function pushCoverageCheckResumeDisclosure(lines, projectRoot) {
|
|
55
68
|
try {
|
|
@@ -433,6 +446,46 @@ function resolveEffortBudget(options) {
|
|
|
433
446
|
};
|
|
434
447
|
}
|
|
435
448
|
}
|
|
449
|
+
function occupancyInput(options, now, write) {
|
|
450
|
+
return {
|
|
451
|
+
env: options.env,
|
|
452
|
+
now,
|
|
453
|
+
newSessionId: options.newSessionId,
|
|
454
|
+
steal: options.steal,
|
|
455
|
+
confirm: options.confirm,
|
|
456
|
+
occupant: options.occupant,
|
|
457
|
+
intent: options.occupancyIntent ?? "mutation",
|
|
458
|
+
write,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function runOccupancy(projectRoot, options, now, write) {
|
|
462
|
+
const apply = options.applyOccupancy ?? applyWorktreeOccupancy;
|
|
463
|
+
return apply(projectRoot, occupancyInput(options, now, write));
|
|
464
|
+
}
|
|
465
|
+
function occupancyDeniedResult(occupancy, environment) {
|
|
466
|
+
return {
|
|
467
|
+
code: occupancy.code,
|
|
468
|
+
payload: {
|
|
469
|
+
ready: false,
|
|
470
|
+
exit_code: occupancy.code,
|
|
471
|
+
posture: MUTATION_POSTURE,
|
|
472
|
+
occupancy: {
|
|
473
|
+
action: occupancy.action,
|
|
474
|
+
session_id: occupancy.sessionId,
|
|
475
|
+
occupant_id: occupancy.record?.sessionId ?? null,
|
|
476
|
+
},
|
|
477
|
+
environment: environmentContextToDict(environment),
|
|
478
|
+
message: occupancy.message,
|
|
479
|
+
},
|
|
480
|
+
lines: occupancy.message.split("\n"),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function persistOccupancyOrDeny(projectRoot, options, now, environment) {
|
|
484
|
+
const occupancy = runOccupancy(projectRoot, options, now, true);
|
|
485
|
+
if (occupancy.code !== 0)
|
|
486
|
+
return occupancyDeniedResult(occupancy, environment);
|
|
487
|
+
return occupancy;
|
|
488
|
+
}
|
|
436
489
|
function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
437
490
|
const lines = [];
|
|
438
491
|
const resolveUserMd = options.resolveUserMd ?? ((root) => resolveUserMdPath({ projectRoot: root }));
|
|
@@ -454,6 +507,8 @@ function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
|
454
507
|
lines.push(...formatScmReadinessLines(scm));
|
|
455
508
|
lines.push(...hostSurface.lines);
|
|
456
509
|
lines.push(...effortBudget.lines);
|
|
510
|
+
const runGit = options.runGit ?? defaultGitRunner;
|
|
511
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
457
512
|
const resultPayload = {
|
|
458
513
|
ready: true,
|
|
459
514
|
exit_code: 0,
|
|
@@ -509,6 +564,10 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
509
564
|
lines: [formatEnvironmentContext(environment), message],
|
|
510
565
|
};
|
|
511
566
|
}
|
|
567
|
+
const plannedOccupancy = runOccupancy(projectRoot, options, instant, options.steal === true);
|
|
568
|
+
if (plannedOccupancy.code !== 0) {
|
|
569
|
+
return occupancyDeniedResult(plannedOccupancy, environment);
|
|
570
|
+
}
|
|
512
571
|
const resolveUserMd = options.resolveUserMd ?? ((root) => resolveUserMdPath({ projectRoot: root }));
|
|
513
572
|
const userMd = resolveUserMd(projectRoot);
|
|
514
573
|
const safePath = userMd.path.replace(/\r?\n/g, " ");
|
|
@@ -532,6 +591,7 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
532
591
|
...effortBudget.lines,
|
|
533
592
|
REARM_SKIPPED_FAT_PATH_MESSAGE,
|
|
534
593
|
];
|
|
594
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
535
595
|
// Light branch-policy disclosure (local only) so re-arm still surfaces policy state.
|
|
536
596
|
const policyResult = resolvePolicy(projectRoot);
|
|
537
597
|
const policyMessage = disclosureLine(policyResult);
|
|
@@ -606,7 +666,12 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
606
666
|
};
|
|
607
667
|
const gatedSteps = restampSteps(eligibility.state.gatedSteps, instant);
|
|
608
668
|
const writeStarted = performance.now();
|
|
609
|
-
const
|
|
669
|
+
const persistedOccupancy = persistOccupancyOrDeny(projectRoot, options, instant, environment);
|
|
670
|
+
if ("payload" in persistedOccupancy) {
|
|
671
|
+
return persistedOccupancy;
|
|
672
|
+
}
|
|
673
|
+
// #3433: keep DEFT_SESSION_ID / occupant id. Do not mint a new UUID on re-arm.
|
|
674
|
+
const rearmSessionId = persistedOccupancy.sessionId;
|
|
610
675
|
// Fresh payload (no rearm_needed / compact_resume_at) clears compact markers (#2992).
|
|
611
676
|
const writePayload = {
|
|
612
677
|
...newRitualStatePayload({
|
|
@@ -690,6 +755,10 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
690
755
|
optionalNetwork: false,
|
|
691
756
|
steps: stepTimings,
|
|
692
757
|
}, { projectRoot });
|
|
758
|
+
// #3508: operator-visible CLI process time. ⊗ not #3286 Later graduation input.
|
|
759
|
+
if (!resolveSessionCompact({ compact: options.compact, env: options.env })) {
|
|
760
|
+
lines.push(formatSessionStartCeremonyCostLine(REARM_CEREMONY_TIER, totalMs));
|
|
761
|
+
}
|
|
693
762
|
return {
|
|
694
763
|
code,
|
|
695
764
|
payload: {
|
|
@@ -714,6 +783,10 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
714
783
|
scm: scmReadinessToDict(scm),
|
|
715
784
|
host_content_surface: hostContentSurfaceToDict(hostSurface.report),
|
|
716
785
|
effort_budget: effortBudgetToDict(effortBudget.budget),
|
|
786
|
+
occupancy: {
|
|
787
|
+
action: persistedOccupancy.action,
|
|
788
|
+
session_id: rearmSessionId,
|
|
789
|
+
},
|
|
717
790
|
message: code === 0 ? "session ritual re-armed" : "session ritual re-arm failed",
|
|
718
791
|
},
|
|
719
792
|
lines,
|
|
@@ -847,6 +920,10 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
847
920
|
lines: [formatEnvironmentContext(environment), payload.message],
|
|
848
921
|
};
|
|
849
922
|
}
|
|
923
|
+
const plannedOccupancy = runOccupancy(projectRoot, options, instant, options.steal === true);
|
|
924
|
+
if (plannedOccupancy.code !== 0) {
|
|
925
|
+
return occupancyDeniedResult(plannedOccupancy, environment);
|
|
926
|
+
}
|
|
850
927
|
const quickSteps = recordDeferredSteps(QUICK_STEPS, effectiveDeferrals, instant);
|
|
851
928
|
const gatedSteps = recordDeferredSteps(GATED_STEPS, effectiveDeferrals, instant);
|
|
852
929
|
const lines = [];
|
|
@@ -919,6 +996,12 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
919
996
|
name: "effort_budget",
|
|
920
997
|
duration_ms: elapsedMs(effortBudgetStepStarted),
|
|
921
998
|
});
|
|
999
|
+
const lifecycleVisibleStarted = performance.now();
|
|
1000
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
1001
|
+
stepTimings.push({
|
|
1002
|
+
name: "lifecycle_visible",
|
|
1003
|
+
duration_ms: elapsedMs(lifecycleVisibleStarted),
|
|
1004
|
+
});
|
|
922
1005
|
if (!quickSteps.branch_policy) {
|
|
923
1006
|
const stepStarted = performance.now();
|
|
924
1007
|
const result = resolvePolicy(projectRoot);
|
|
@@ -1214,7 +1297,11 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1214
1297
|
lines.push(consentPrompt.trimEnd());
|
|
1215
1298
|
}
|
|
1216
1299
|
const writeStarted = performance.now();
|
|
1217
|
-
const
|
|
1300
|
+
const persistedOccupancy = persistOccupancyOrDeny(projectRoot, options, instant, environment);
|
|
1301
|
+
if ("payload" in persistedOccupancy) {
|
|
1302
|
+
return persistedOccupancy;
|
|
1303
|
+
}
|
|
1304
|
+
const coldSessionId = persistedOccupancy.sessionId;
|
|
1218
1305
|
const dialDict = {
|
|
1219
1306
|
...ceremonyDialToDict(ceremonyDialSelection),
|
|
1220
1307
|
start_tier: ceremonyDialSelection.depth,
|
|
@@ -1298,10 +1385,9 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1298
1385
|
}
|
|
1299
1386
|
: {}),
|
|
1300
1387
|
});
|
|
1301
|
-
// #
|
|
1302
|
-
//
|
|
1303
|
-
//
|
|
1304
|
-
// else this session:start CLI invocation (1).
|
|
1388
|
+
// #3399: emit a denominator only when a host/harness value is known.
|
|
1389
|
+
// Prefer DEFT_TOTAL_TOOL_TURNS (harness_actual), then DEFT_MAX_TURNS /
|
|
1390
|
+
// host maxTurns (host_planned). Unset → no event; share is unevaluable.
|
|
1305
1391
|
emitter.emitSessionToolTurnDenominator(effortBudget.budget.maxTurns);
|
|
1306
1392
|
// #3319: evaluate escalate-on-evidence only when #3274 is live. A pin
|
|
1307
1393
|
// emits nothing so never-evaluated stays distinguishable from declined.
|
|
@@ -1386,6 +1472,10 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1386
1472
|
scm: scmReadinessToDict(scm),
|
|
1387
1473
|
host_content_surface: hostContentSurfaceToDict(hostSurface.report),
|
|
1388
1474
|
effort_budget: effortBudgetToDict(effortBudget.budget),
|
|
1475
|
+
occupancy: {
|
|
1476
|
+
action: persistedOccupancy.action,
|
|
1477
|
+
session_id: coldSessionId,
|
|
1478
|
+
},
|
|
1389
1479
|
message: code === 0 ? "session ritual recorded" : "session ritual failed",
|
|
1390
1480
|
};
|
|
1391
1481
|
// #2994: local process-cost event (best-effort; never blocks ceremony).
|
|
@@ -1397,6 +1487,10 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1397
1487
|
optionalNetwork: allowOptionalNetwork,
|
|
1398
1488
|
steps: stepTimings,
|
|
1399
1489
|
}, { projectRoot });
|
|
1490
|
+
// #3508: operator-visible CLI process time. ⊗ not #3286 Later graduation input.
|
|
1491
|
+
if (!resolveSessionCompact({ compact: options.compact, env: options.env })) {
|
|
1492
|
+
lines.push(formatSessionStartCeremonyCostLine(COLD_CEREMONY_TIER, totalMs));
|
|
1493
|
+
}
|
|
1400
1494
|
return { code, payload: resultPayload, lines };
|
|
1401
1495
|
}
|
|
1402
1496
|
export { ritualStatePath };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Same-session verify:ac result cache (#3387).
|
|
3
|
+
*
|
|
4
|
+
* Disk-backed so check composition (spawned verify:ac) can serve from_cache
|
|
5
|
+
* after a green run in the same session when plan + product hash still match.
|
|
6
|
+
*/
|
|
7
|
+
export declare const VERIFY_AC_SESSION_CACHE_DIR = ".deft/verify-ac-session-cache";
|
|
8
|
+
export declare const AC_SERVED_FROM: readonly ["bank", "cache", "executed"];
|
|
9
|
+
export type AcServedFrom = (typeof AC_SERVED_FROM)[number];
|
|
10
|
+
export interface CachedVerifyAcSnapshot {
|
|
11
|
+
readonly ok: boolean;
|
|
12
|
+
readonly code: 0 | 1 | 2;
|
|
13
|
+
readonly message: string;
|
|
14
|
+
readonly commands: readonly unknown[];
|
|
15
|
+
readonly runs: readonly unknown[];
|
|
16
|
+
readonly rejected?: readonly unknown[];
|
|
17
|
+
readonly sourceRung: string;
|
|
18
|
+
readonly noneStated: boolean;
|
|
19
|
+
readonly acceptance: unknown;
|
|
20
|
+
readonly resolution: string;
|
|
21
|
+
readonly resolvedCommandCount: number;
|
|
22
|
+
}
|
|
23
|
+
export interface VerifyAcSessionCacheRecord {
|
|
24
|
+
readonly sessionId: string;
|
|
25
|
+
readonly scopeId: string;
|
|
26
|
+
readonly productStateHash: string;
|
|
27
|
+
readonly cachedAt: string;
|
|
28
|
+
readonly snapshot: CachedVerifyAcSnapshot;
|
|
29
|
+
}
|
|
30
|
+
export declare function verifyAcSessionCacheDir(projectRoot: string): string;
|
|
31
|
+
export declare function verifyAcSessionCachePath(projectRoot: string, sessionId: string, scopeId: string): string;
|
|
32
|
+
export declare function resolveVerifyAcSessionId(env?: Readonly<Record<string, string | undefined>>, explicit?: string | null): string | null;
|
|
33
|
+
export declare function readVerifyAcSessionCache(projectRoot: string, sessionId: string, scopeId: string): VerifyAcSessionCacheRecord | null;
|
|
34
|
+
export declare function writeVerifyAcSessionCache(input: {
|
|
35
|
+
readonly projectRoot: string;
|
|
36
|
+
readonly sessionId: string;
|
|
37
|
+
readonly scopeId: string;
|
|
38
|
+
readonly productStateHash: string;
|
|
39
|
+
readonly snapshot: CachedVerifyAcSnapshot;
|
|
40
|
+
readonly now?: string;
|
|
41
|
+
}): VerifyAcSessionCacheRecord;
|
|
42
|
+
//# sourceMappingURL=verify-ac-session-cache.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Same-session verify:ac result cache (#3387).
|
|
3
|
+
*
|
|
4
|
+
* Disk-backed so check composition (spawned verify:ac) can serve from_cache
|
|
5
|
+
* after a green run in the same session when plan + product hash still match.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
|
+
import { containedWrite } from "../fs/contained-write.js";
|
|
10
|
+
import { sanitizeScopeIdForFilename } from "./ac-pass-banking.js";
|
|
11
|
+
export const VERIFY_AC_SESSION_CACHE_DIR = ".deft/verify-ac-session-cache";
|
|
12
|
+
export const AC_SERVED_FROM = ["bank", "cache", "executed"];
|
|
13
|
+
function asRecord(value) {
|
|
14
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export function verifyAcSessionCacheDir(projectRoot) {
|
|
20
|
+
return join(resolve(projectRoot), ...VERIFY_AC_SESSION_CACHE_DIR.split("/"));
|
|
21
|
+
}
|
|
22
|
+
export function verifyAcSessionCachePath(projectRoot, sessionId, scopeId) {
|
|
23
|
+
const safeSession = sanitizeScopeIdForFilename(sessionId);
|
|
24
|
+
const safeScope = sanitizeScopeIdForFilename(scopeId);
|
|
25
|
+
return join(verifyAcSessionCacheDir(projectRoot), `${safeSession}-${safeScope}.json`);
|
|
26
|
+
}
|
|
27
|
+
export function resolveVerifyAcSessionId(env, explicit) {
|
|
28
|
+
const injected = explicit?.trim() ?? "";
|
|
29
|
+
if (injected.length > 0)
|
|
30
|
+
return injected;
|
|
31
|
+
const fromEnv = typeof env?.DEFT_SESSION_ID === "string" ? env.DEFT_SESSION_ID.trim() : "";
|
|
32
|
+
return fromEnv.length > 0 ? fromEnv : null;
|
|
33
|
+
}
|
|
34
|
+
function parseSnapshot(raw) {
|
|
35
|
+
const rec = asRecord(raw);
|
|
36
|
+
if (rec === null)
|
|
37
|
+
return null;
|
|
38
|
+
if (typeof rec.ok !== "boolean")
|
|
39
|
+
return null;
|
|
40
|
+
if (rec.code !== 0 && rec.code !== 1 && rec.code !== 2)
|
|
41
|
+
return null;
|
|
42
|
+
if (typeof rec.message !== "string")
|
|
43
|
+
return null;
|
|
44
|
+
if (!Array.isArray(rec.commands) || !Array.isArray(rec.runs))
|
|
45
|
+
return null;
|
|
46
|
+
if (typeof rec.sourceRung !== "string")
|
|
47
|
+
return null;
|
|
48
|
+
if (typeof rec.noneStated !== "boolean")
|
|
49
|
+
return null;
|
|
50
|
+
if (typeof rec.resolution !== "string")
|
|
51
|
+
return null;
|
|
52
|
+
if (typeof rec.resolvedCommandCount !== "number")
|
|
53
|
+
return null;
|
|
54
|
+
return {
|
|
55
|
+
ok: rec.ok,
|
|
56
|
+
code: rec.code,
|
|
57
|
+
message: rec.message,
|
|
58
|
+
commands: rec.commands,
|
|
59
|
+
runs: rec.runs,
|
|
60
|
+
rejected: Array.isArray(rec.rejected) ? rec.rejected : undefined,
|
|
61
|
+
sourceRung: rec.sourceRung,
|
|
62
|
+
noneStated: rec.noneStated,
|
|
63
|
+
acceptance: rec.acceptance,
|
|
64
|
+
resolution: rec.resolution,
|
|
65
|
+
resolvedCommandCount: rec.resolvedCommandCount,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function readVerifyAcSessionCache(projectRoot, sessionId, scopeId) {
|
|
69
|
+
const path = verifyAcSessionCachePath(projectRoot, sessionId, scopeId);
|
|
70
|
+
if (!existsSync(path))
|
|
71
|
+
return null;
|
|
72
|
+
let text;
|
|
73
|
+
try {
|
|
74
|
+
text = readFileSync(path, { encoding: "utf8" });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const parsed = JSON.parse(text);
|
|
81
|
+
const rec = asRecord(parsed);
|
|
82
|
+
if (rec === null)
|
|
83
|
+
return null;
|
|
84
|
+
if (rec.sessionId !== sessionId || rec.scopeId !== scopeId)
|
|
85
|
+
return null;
|
|
86
|
+
if (typeof rec.productStateHash !== "string" || rec.productStateHash.length === 0) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const snapshot = parseSnapshot(rec.snapshot);
|
|
90
|
+
if (snapshot === null || snapshot.ok !== true)
|
|
91
|
+
return null;
|
|
92
|
+
return {
|
|
93
|
+
sessionId,
|
|
94
|
+
scopeId,
|
|
95
|
+
productStateHash: rec.productStateHash,
|
|
96
|
+
cachedAt: typeof rec.cachedAt === "string" ? rec.cachedAt : "",
|
|
97
|
+
snapshot,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function writeVerifyAcSessionCache(input) {
|
|
105
|
+
const root = resolve(input.projectRoot);
|
|
106
|
+
const path = verifyAcSessionCachePath(root, input.sessionId, input.scopeId);
|
|
107
|
+
const dir = verifyAcSessionCacheDir(root);
|
|
108
|
+
if (!existsSync(dir))
|
|
109
|
+
mkdirSync(dir, { recursive: true });
|
|
110
|
+
const record = {
|
|
111
|
+
sessionId: input.sessionId,
|
|
112
|
+
scopeId: input.scopeId,
|
|
113
|
+
productStateHash: input.productStateHash,
|
|
114
|
+
cachedAt: input.now ?? new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
115
|
+
snapshot: input.snapshot,
|
|
116
|
+
};
|
|
117
|
+
containedWrite({
|
|
118
|
+
root,
|
|
119
|
+
target: path,
|
|
120
|
+
data: `${JSON.stringify(record, null, 2)}\n`,
|
|
121
|
+
mode: "replace",
|
|
122
|
+
mkdir: true,
|
|
123
|
+
});
|
|
124
|
+
return record;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=verify-ac-session-cache.js.map
|
|
@@ -6,6 +6,26 @@ export { formatCacheFetchAllRecoveryCommand, recoveryHintForStaleFailure, } from
|
|
|
6
6
|
export declare const ENV_SKIP = "DEFT_SESSION_RITUAL_SKIP";
|
|
7
7
|
export { ENTRYPOINT_TIMEOUT_EXIT_CODE, ENTRYPOINT_TIMEOUT_SECONDS, } from "./ritual-entrypoint.js";
|
|
8
8
|
export declare const GATED_ENTRYPOINT_COMMANDS: Readonly<Record<GatedStepName, readonly string[]>>;
|
|
9
|
+
/** Explicit skip flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
10
|
+
export declare const SKIP_DRIFT_PROBE_FLAG = "--skip-drift-probe";
|
|
11
|
+
/** Explicit work-selection flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
12
|
+
export declare const WORK_SELECTION_FLAG = "--work-selection";
|
|
13
|
+
/** Distinct ritual-state field — never `deferred_reason` (#3507). */
|
|
14
|
+
export declare const DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION = "skipped-no-work-selection";
|
|
15
|
+
export type WorkSelectionKind = "none" | "active-story" | "triage-queue" | "ordered-plan" | "for-issue" | "explicit-flag";
|
|
16
|
+
export interface WorkSelectionSignal {
|
|
17
|
+
readonly inPlay: boolean;
|
|
18
|
+
readonly kind: WorkSelectionKind;
|
|
19
|
+
}
|
|
20
|
+
export type DetectWorkSelection = (projectRoot: string) => WorkSelectionSignal;
|
|
21
|
+
/**
|
|
22
|
+
* Default work-selection detector for the gated `cache_fresh` seam (#3507).
|
|
23
|
+
* Active story xBRIEF (scope:activate residue), unexhausted ordered-plan /
|
|
24
|
+
* triage sequence. `--for-issue` is a positive evaluate override, not this
|
|
25
|
+
* detector — the gated argv never carries it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectWorkSelection(projectRoot: string): WorkSelectionSignal;
|
|
28
|
+
export declare function resolveGatedEntrypointCommand(stepName: GatedStepName, projectRoot: string, detect?: DetectWorkSelection): string[];
|
|
9
29
|
export interface VerifyResult {
|
|
10
30
|
readonly code: number;
|
|
11
31
|
readonly message: string;
|
|
@@ -28,6 +48,12 @@ export type RitualRunner = (command: readonly string[], projectRoot: string) =>
|
|
|
28
48
|
};
|
|
29
49
|
/** Human recovery line after a failed ritual probe (#2992 / #2993). */
|
|
30
50
|
export declare function formatRitualRecoveryInstruction(tier?: SessionCeremonyTier): string;
|
|
51
|
+
/**
|
|
52
|
+
* Sanctioned audited defer copy for gated `cache_fresh` failure (#3506 / #3507).
|
|
53
|
+
* Independent of the #3507 work-selection argv seam — defer is still the
|
|
54
|
+
* operator-audited escape, not the drift-probe skip.
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatCacheFreshDeferSoftPath(): string;
|
|
31
57
|
export interface VerifySessionRitualOptions {
|
|
32
58
|
readonly tier?: "quick" | "gated";
|
|
33
59
|
readonly now?: Date;
|
|
@@ -53,6 +79,8 @@ export interface VerifySessionRitualOptions {
|
|
|
53
79
|
* {@link checkActiveCliAgainstTarget}.
|
|
54
80
|
*/
|
|
55
81
|
readonly checkActiveCli?: (targetVersion: string | null, seams?: ActiveCliCheckSeams) => ActiveCliCheckResult;
|
|
82
|
+
/** Injectable work-selection detector for gated `cache_fresh` (#3507). */
|
|
83
|
+
readonly detectWorkSelection?: DetectWorkSelection;
|
|
56
84
|
}
|
|
57
85
|
export interface InspectSessionRitualOptions {
|
|
58
86
|
readonly tier?: "quick" | "gated";
|