@deftai/directive-core 0.99.0 → 0.101.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/actions.d.ts +6 -0
- package/dist/authz/actions.js +3 -0
- package/dist/authz/classify.js +241 -30
- package/dist/authz/decompose-apply.d.ts +81 -0
- package/dist/authz/decompose-apply.js +377 -0
- package/dist/authz/index.d.ts +3 -1
- package/dist/authz/index.js +3 -1
- package/dist/authz/store.d.ts +53 -0
- package/dist/authz/store.js +219 -1
- package/dist/authz/types.d.ts +19 -2
- package/dist/authz/types.js +5 -1
- package/dist/check/cached-orchestrator.d.ts +26 -5
- package/dist/check/cached-orchestrator.js +228 -6
- package/dist/check/gate-lists.d.ts +10 -4
- package/dist/check/gate-lists.js +19 -5
- package/dist/check/index.d.ts +3 -2
- package/dist/check/index.js +2 -1
- package/dist/check/named-cause.d.ts +45 -0
- package/dist/check/named-cause.js +121 -0
- package/dist/check/orchestrator.js +6 -1
- package/dist/doctor/checks.d.ts +44 -0
- package/dist/doctor/checks.js +428 -2
- package/dist/doctor/help.d.ts +5 -0
- package/dist/doctor/help.js +31 -0
- package/dist/doctor/index.d.ts +2 -0
- package/dist/doctor/index.js +2 -0
- package/dist/doctor/main.d.ts +6 -7
- package/dist/doctor/main.js +130 -79
- package/dist/doctor/session-coda.d.ts +82 -0
- package/dist/doctor/session-coda.js +151 -0
- package/dist/doctor/types.d.ts +16 -0
- package/dist/doctor/which.d.ts +20 -1
- package/dist/doctor/which.js +67 -1
- package/dist/finish-loop/pr-finish-loop.d.ts +13 -2
- package/dist/finish-loop/pr-finish-loop.js +116 -5
- package/dist/finish-loop/types.d.ts +1 -1
- package/dist/hooks/dispatcher.d.ts +9 -5
- package/dist/hooks/dispatcher.js +23 -15
- package/dist/hooks/readonly.d.ts +6 -3
- package/dist/hooks/readonly.js +44 -25
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/init-deposit/agent-hooks.d.ts +20 -0
- package/dist/init-deposit/agent-hooks.js +51 -31
- package/dist/init-deposit/gitignore.js +2 -0
- package/dist/intake/issue-ingest.js +36 -0
- package/dist/lifecycle/completed-consistency.d.ts +60 -0
- package/dist/lifecycle/completed-consistency.js +443 -0
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +47 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +415 -0
- package/dist/lifecycle/index.d.ts +2 -0
- package/dist/lifecycle/index.js +2 -0
- package/dist/literal-acceptance/capture.d.ts +52 -0
- package/dist/literal-acceptance/capture.js +658 -0
- package/dist/literal-acceptance/evaluate.d.ts +47 -0
- package/dist/literal-acceptance/evaluate.js +193 -0
- package/dist/literal-acceptance/index.d.ts +12 -0
- package/dist/literal-acceptance/index.js +12 -0
- package/dist/literal-acceptance/run.d.ts +38 -0
- package/dist/literal-acceptance/run.js +216 -0
- package/dist/literal-acceptance/safety.d.ts +24 -0
- package/dist/literal-acceptance/safety.js +251 -0
- package/dist/literal-acceptance/types.d.ts +82 -0
- package/dist/literal-acceptance/types.js +26 -0
- package/dist/policy/ac-pass-banking.d.ts +58 -0
- package/dist/policy/ac-pass-banking.js +150 -0
- package/dist/policy/ceremony-dial.d.ts +96 -11
- package/dist/policy/ceremony-dial.js +250 -23
- package/dist/policy/index.d.ts +2 -0
- package/dist/policy/index.js +16 -1
- package/dist/policy/merge-approval-head.d.ts +129 -0
- package/dist/policy/merge-approval-head.js +461 -0
- package/dist/policy/require-human-merge.d.ts +5 -0
- package/dist/policy/require-human-merge.js +5 -0
- package/dist/pr-merge-readiness/ci-gate.d.ts +20 -3
- package/dist/pr-merge-readiness/ci-gate.js +65 -5
- package/dist/pr-merge-readiness/compute.d.ts +13 -0
- package/dist/pr-merge-readiness/compute.js +99 -14
- package/dist/pr-merge-readiness/gh.d.ts +49 -0
- package/dist/pr-merge-readiness/gh.js +268 -0
- package/dist/pr-merge-readiness/index.d.ts +2 -2
- package/dist/pr-merge-readiness/index.js +2 -2
- package/dist/pr-merge-readiness/test-gh-fixtures.helpers.js +4 -0
- package/dist/pr-wait-mergeable/cascade.d.ts +11 -0
- package/dist/pr-wait-mergeable/cascade.js +115 -1
- package/dist/pr-wait-mergeable/main.d.ts +4 -0
- package/dist/pr-wait-mergeable/main.js +4 -0
- package/dist/pr-wait-mergeable/types.d.ts +3 -1
- package/dist/pr-wait-mergeable/wrappers.d.ts +6 -1
- package/dist/pr-wait-mergeable/wrappers.js +7 -1
- package/dist/preflight/evaluate.d.ts +15 -1
- package/dist/preflight/evaluate.js +33 -2
- package/dist/preflight-cache/evaluate.d.ts +3 -0
- package/dist/preflight-cache/evaluate.js +3 -0
- package/dist/product-first-done-gate/acceptance.d.ts +25 -0
- package/dist/product-first-done-gate/acceptance.js +247 -0
- package/dist/product-first-done-gate/check-mode.d.ts +45 -0
- package/dist/product-first-done-gate/check-mode.js +148 -0
- package/dist/product-first-done-gate/evaluate.d.ts +50 -0
- package/dist/product-first-done-gate/evaluate.js +255 -0
- package/dist/product-first-done-gate/index.d.ts +11 -0
- package/dist/product-first-done-gate/index.js +11 -0
- package/dist/product-first-done-gate/types.d.ts +64 -0
- package/dist/product-first-done-gate/types.js +61 -0
- package/dist/render/framework-commands.js +4 -0
- package/dist/run-summary/emit.d.ts +56 -0
- package/dist/run-summary/emit.js +171 -0
- package/dist/run-summary/index.d.ts +4 -0
- package/dist/run-summary/index.js +4 -0
- package/dist/run-summary/path.d.ts +25 -0
- package/dist/run-summary/path.js +78 -0
- package/dist/run-summary/types.d.ts +76 -0
- package/dist/run-summary/types.js +21 -0
- package/dist/scope/acceptance-evidence.d.ts +110 -0
- package/dist/scope/acceptance-evidence.js +422 -0
- package/dist/scope/coverage-map.d.ts +98 -0
- package/dist/scope/coverage-map.js +558 -0
- package/dist/scope/decompose.d.ts +5 -0
- package/dist/scope/decompose.js +134 -11
- package/dist/scope/index.d.ts +3 -0
- package/dist/scope/index.js +3 -0
- package/dist/scope/parent-lineage.d.ts +125 -0
- package/dist/scope/parent-lineage.js +626 -0
- package/dist/scope/transition.d.ts +8 -0
- package/dist/scope/transition.js +61 -2
- package/dist/session/ac-pass-banking.d.ts +221 -0
- package/dist/session/ac-pass-banking.js +761 -0
- package/dist/session/active-cli.d.ts +79 -0
- package/dist/session/active-cli.js +382 -0
- package/dist/session/deposit-sha.d.ts +49 -0
- package/dist/session/deposit-sha.js +121 -0
- package/dist/session/effort-budget.d.ts +136 -0
- package/dist/session/effort-budget.js +352 -0
- package/dist/session/index.d.ts +7 -0
- package/dist/session/index.js +7 -0
- package/dist/session/orientation-compression.d.ts +127 -0
- package/dist/session/orientation-compression.js +425 -0
- package/dist/session/orientation-state.d.ts +29 -0
- package/dist/session/orientation-state.js +85 -0
- package/dist/session/session-start.d.ts +31 -0
- package/dist/session/session-start.js +228 -2
- package/dist/session/toolchain-preflight.d.ts +64 -0
- package/dist/session/toolchain-preflight.js +151 -0
- package/dist/session/verify-session-ritual.d.ts +14 -0
- package/dist/session/verify-session-ritual.js +33 -0
- package/dist/story-ready/evaluate.d.ts +11 -0
- package/dist/story-ready/evaluate.js +41 -3
- package/dist/triage/actions/candidates-log.d.ts +1 -2
- package/dist/triage/actions/candidates-log.js +37 -6
- package/dist/triage/bootstrap/gitignore.d.ts +1 -1
- package/dist/triage/bootstrap/gitignore.js +8 -2
- package/dist/triage/bootstrap/index.js +15 -3
- package/dist/triage/classify/index.d.ts +1 -0
- package/dist/triage/classify/index.js +2 -0
- package/dist/triage/classify/label-mirror.js +16 -0
- package/dist/triage/classify/mirror-discovery-tip.d.ts +95 -0
- package/dist/triage/classify/mirror-discovery-tip.js +234 -0
- package/dist/triage/reconcile/reconcile.js +28 -6
- package/dist/triage/summary/index.js +12 -4
- package/dist/triage/welcome/default-mode.js +16 -0
- package/dist/ts-check-lane/run-lane.js +21 -4
- package/dist/vbrief-validate/conformance.js +7 -0
- package/dist/vitest-runner/coverage-debt-teardown.js +16 -4
- package/dist/xbrief-migrate/migrate-project.d.ts +4 -0
- package/dist/xbrief-migrate/migrate-project.js +92 -3
- package/package.json +15 -3
|
@@ -14,6 +14,7 @@ import { humanMergeDisclosureLine, resolveHumanMergePolicy, } from "../policy/re
|
|
|
14
14
|
import { resolvePolicy } from "../policy/resolve.js";
|
|
15
15
|
import { maybeFormatProductSignalConsentPrompt } from "../product-signal/consent-prompt.js";
|
|
16
16
|
import { formatFrameworkCommand } from "../render/framework-commands.js";
|
|
17
|
+
import { RunSummaryEmitter } from "../run-summary/emit.js";
|
|
17
18
|
import { formatScmReadinessLines, probeScmReadiness, scmReadinessToDict, } from "../scm/readiness.js";
|
|
18
19
|
import { maybeRunStalenessTickler } from "../staleness-tickler/run.js";
|
|
19
20
|
import { runDefaultMode } from "../triage/welcome/default-mode.js";
|
|
@@ -21,11 +22,14 @@ import { resolveUserMdPath } from "../user-config/resolve-user-md.js";
|
|
|
21
22
|
import { emitSessionValueReadback } from "../value/readback.js";
|
|
22
23
|
import { verifyRequiredTools } from "../verify-env/verify-tools.js";
|
|
23
24
|
import { maybeFormatCoverageCheckResumeNudge } from "./coverage-check-resume-nudge.js";
|
|
25
|
+
import { effortBudgetToDict, maybeFormatEffortBudgetLines, resolveProductionHostEffortDescriptor, } from "./effort-budget.js";
|
|
24
26
|
import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
|
|
27
|
+
import { runOrientationCompression, } from "./orientation-compression.js";
|
|
25
28
|
import { emitSessionStartProcessCost } from "./process-cost.js";
|
|
26
29
|
import { probeSessionReleaseAvailability, } from "./release-availability.js";
|
|
27
30
|
import { newRitualStatePayload, readRitualState, ritualStatePath, ritualStep, writeRitualState, } from "./ritual-sentinel.js";
|
|
28
31
|
import { timestampIso } from "./time.js";
|
|
32
|
+
import { runToolchainPreflight, toolchainPreflightToDict, } from "./toolchain-preflight.js";
|
|
29
33
|
export const SESSION_POSTURES = ["read-only", "mutation"];
|
|
30
34
|
export const READ_ONLY_POSTURE = "read-only";
|
|
31
35
|
export const MUTATION_POSTURE = "mutation";
|
|
@@ -383,6 +387,38 @@ function resolveHostContentSurface(projectRoot, options, runtimeMode) {
|
|
|
383
387
|
};
|
|
384
388
|
}
|
|
385
389
|
}
|
|
390
|
+
function resolveEffortBudget(options) {
|
|
391
|
+
try {
|
|
392
|
+
const seams = options.effortBudgetSeams ?? {};
|
|
393
|
+
const environ = seams.environ ?? options.env ?? process.env;
|
|
394
|
+
// Production host adapter (#3266 / #1461): always resolve a descriptor from env
|
|
395
|
+
// (and CLI-forwarded seams) so host-native max-turns/budget signals are not lost.
|
|
396
|
+
const productionHost = resolveProductionHostEffortDescriptor(environ);
|
|
397
|
+
const hostDescriptor = seams.hostDescriptor !== undefined && seams.hostDescriptor !== null
|
|
398
|
+
? { ...productionHost, ...seams.hostDescriptor }
|
|
399
|
+
: productionHost;
|
|
400
|
+
return maybeFormatEffortBudgetLines({
|
|
401
|
+
environ,
|
|
402
|
+
hostDescriptor,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
// best-effort — session start must not abort on effort-budget probe failures (#3266)
|
|
407
|
+
return {
|
|
408
|
+
budget: {
|
|
409
|
+
detected: false,
|
|
410
|
+
posture: "unbounded",
|
|
411
|
+
kind: "none",
|
|
412
|
+
maxTurns: null,
|
|
413
|
+
maxBudget: null,
|
|
414
|
+
remainingTurns: null,
|
|
415
|
+
remainingBudget: null,
|
|
416
|
+
sources: [],
|
|
417
|
+
},
|
|
418
|
+
lines: [],
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
386
422
|
function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
387
423
|
const lines = [];
|
|
388
424
|
const resolveUserMd = options.resolveUserMd ?? ((root) => resolveUserMdPath({ projectRoot: root }));
|
|
@@ -396,11 +432,14 @@ function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
|
396
432
|
const scm = resolveSessionScmReadiness(options, false);
|
|
397
433
|
// #3162: host content-surface class + managed drift (advisory).
|
|
398
434
|
const hostSurface = resolveHostContentSurface(projectRoot, options, scm.runtimeMode);
|
|
435
|
+
// #3266: hard effort-budget detection (advisory; bank-the-pass guidance).
|
|
436
|
+
const effortBudget = resolveEffortBudget(options);
|
|
399
437
|
lines.push(READ_ONLY_ALIGNMENT_MESSAGE);
|
|
400
438
|
lines.push(userMdLine);
|
|
401
439
|
lines.push(formatEnvironmentContext(environment));
|
|
402
440
|
lines.push(...formatScmReadinessLines(scm));
|
|
403
441
|
lines.push(...hostSurface.lines);
|
|
442
|
+
lines.push(...effortBudget.lines);
|
|
404
443
|
const resultPayload = {
|
|
405
444
|
ready: true,
|
|
406
445
|
exit_code: 0,
|
|
@@ -423,6 +462,7 @@ function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
|
423
462
|
environment: environmentContextToDict(environment),
|
|
424
463
|
scm: scmReadinessToDict(scm),
|
|
425
464
|
host_content_surface: hostContentSurfaceToDict(hostSurface.report),
|
|
465
|
+
effort_budget: effortBudgetToDict(effortBudget.budget),
|
|
426
466
|
message: READ_ONLY_RESULT_MESSAGE,
|
|
427
467
|
};
|
|
428
468
|
return { code: 0, payload: resultPayload, lines };
|
|
@@ -467,12 +507,15 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
467
507
|
const scm = resolveSessionScmReadiness(options, false);
|
|
468
508
|
// #3162: host content-surface class + managed drift (advisory).
|
|
469
509
|
const hostSurface = resolveHostContentSurface(projectRoot, options, scm.runtimeMode);
|
|
510
|
+
// #3266: hard effort-budget detection (advisory).
|
|
511
|
+
const effortBudget = resolveEffortBudget(options);
|
|
470
512
|
const lines = [
|
|
471
513
|
READ_ONLY_ALIGNMENT_MESSAGE,
|
|
472
514
|
userMdLine,
|
|
473
515
|
formatEnvironmentContext(environment),
|
|
474
516
|
...formatScmReadinessLines(scm),
|
|
475
517
|
...hostSurface.lines,
|
|
518
|
+
...effortBudget.lines,
|
|
476
519
|
REARM_SKIPPED_FAT_PATH_MESSAGE,
|
|
477
520
|
];
|
|
478
521
|
// Light branch-policy disclosure (local only) so re-arm still surfaces policy state.
|
|
@@ -665,6 +708,7 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
665
708
|
environment: environmentContextToDict(environment),
|
|
666
709
|
scm: scmReadinessToDict(scm),
|
|
667
710
|
host_content_surface: hostContentSurfaceToDict(hostSurface.report),
|
|
711
|
+
effort_budget: effortBudgetToDict(effortBudget.budget),
|
|
668
712
|
message: code === 0 ? "session ritual re-armed" : "session ritual re-arm failed",
|
|
669
713
|
},
|
|
670
714
|
lines,
|
|
@@ -749,9 +793,10 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
749
793
|
// #3214 / #3156: select ritual (ceremony) depth before building deferral maps.
|
|
750
794
|
// Rapid/minimal auto-defer informational cold steps only; mutation readiness
|
|
751
795
|
// (doctor, cache_fresh, agent_hooks, verify_tools) stays constant.
|
|
752
|
-
// Two-stage + provisional intake (#3214
|
|
796
|
+
// Two-stage + provisional intake (#3214 / #3263 / #1581 ordering): fill
|
|
753
797
|
// missing size/tier/shape from env/verb/files/deposit BEFORE resolve — never
|
|
754
|
-
// block on plan-item effort (post-planning only). Cold incomplete
|
|
798
|
+
// block on plan-item effort (post-planning only). Cold incomplete size is
|
|
799
|
+
// tier-conditional (#3263): mid/low → standard; frontier/unknown → rapid.
|
|
755
800
|
const { inputs: resolvedDialInputs, provisional: provisionalDial } = resolveSessionCeremonyDialInputs(projectRoot, options.ceremonyDialInputs, {
|
|
756
801
|
...options.ceremonyDialHints,
|
|
757
802
|
env: options.env,
|
|
@@ -837,6 +882,14 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
837
882
|
name: "host_content_surface",
|
|
838
883
|
duration_ms: elapsedMs(hostSurfaceStepStarted),
|
|
839
884
|
});
|
|
885
|
+
// #3266: hard effort-budget detection (advisory; bank-the-pass guidance).
|
|
886
|
+
const effortBudgetStepStarted = performance.now();
|
|
887
|
+
const effortBudget = resolveEffortBudget(options);
|
|
888
|
+
lines.push(...effortBudget.lines);
|
|
889
|
+
stepTimings.push({
|
|
890
|
+
name: "effort_budget",
|
|
891
|
+
duration_ms: elapsedMs(effortBudgetStepStarted),
|
|
892
|
+
});
|
|
840
893
|
if (!quickSteps.branch_policy) {
|
|
841
894
|
const stepStarted = performance.now();
|
|
842
895
|
const result = resolvePolicy(projectRoot);
|
|
@@ -902,6 +955,120 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
902
955
|
});
|
|
903
956
|
stepTimings.push({ name: "verify_tools", duration_ms: durationMs });
|
|
904
957
|
}
|
|
958
|
+
// #3282 / #3286: orientation compression — compose doctor + toolchain preflight
|
|
959
|
+
// (+ agents:refresh / cache-fresh deposit-sha fast-paths) as inline sections with
|
|
960
|
+
// per-section status lines. Composition of existing steps, not a new monolith.
|
|
961
|
+
// Read-only posture never reaches here (#2176). Dual-path Later (`deft orient`)
|
|
962
|
+
// remains open — see orientation bundle.later.
|
|
963
|
+
let toolchainPreflightResult = null;
|
|
964
|
+
let orientationBundle = null;
|
|
965
|
+
{
|
|
966
|
+
const stepStarted = performance.now();
|
|
967
|
+
if (options.orientation === null) {
|
|
968
|
+
// Explicit skip (tests): still honour legacy preflight-only path when set.
|
|
969
|
+
if (options.toolchainPreflight === null) {
|
|
970
|
+
stepTimings.push({ name: "orientation", duration_ms: 0, skipped: true });
|
|
971
|
+
stepTimings.push({ name: "toolchain_preflight", duration_ms: 0, skipped: true });
|
|
972
|
+
}
|
|
973
|
+
else if (options.toolchainPreflight !== undefined) {
|
|
974
|
+
toolchainPreflightResult = options.toolchainPreflight;
|
|
975
|
+
lines.push(...toolchainPreflightResult.lines);
|
|
976
|
+
stepTimings.push({
|
|
977
|
+
name: "toolchain_preflight",
|
|
978
|
+
duration_ms: elapsedMs(stepStarted),
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
stepTimings.push({ name: "orientation", duration_ms: 0, skipped: true });
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
else if (options.orientation !== undefined) {
|
|
986
|
+
orientationBundle = options.orientation;
|
|
987
|
+
toolchainPreflightResult = orientationBundle.preflight;
|
|
988
|
+
lines.push(...orientationBundle.lines);
|
|
989
|
+
for (const section of orientationBundle.sections) {
|
|
990
|
+
stepTimings.push({
|
|
991
|
+
name: section.name,
|
|
992
|
+
duration_ms: section.durationMs,
|
|
993
|
+
...(section.status === "skipped" ? { skipped: true } : {}),
|
|
994
|
+
});
|
|
995
|
+
// Record gated ritual steps so verify:session-ritual can skip re-runs.
|
|
996
|
+
// Do not overwrite explicit --defer (deferred_reason) records.
|
|
997
|
+
if ((section.name === "doctor" || section.name === "cache_fresh") &&
|
|
998
|
+
!gatedSteps[section.name]?.deferred_reason) {
|
|
999
|
+
gatedSteps[section.name] = ritualStep({
|
|
1000
|
+
ok: section.ok,
|
|
1001
|
+
ts: instant,
|
|
1002
|
+
message: section.lines[0] ?? section.status,
|
|
1003
|
+
exitCode: section.exitCode,
|
|
1004
|
+
durationMs: section.durationMs,
|
|
1005
|
+
command: section.name === "doctor" ? ["doctor"] : ["verify:cache-fresh"],
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
stepTimings.push({ name: "orientation", duration_ms: elapsedMs(stepStarted) });
|
|
1010
|
+
}
|
|
1011
|
+
else {
|
|
1012
|
+
try {
|
|
1013
|
+
// Skip composed doctor/cache_fresh work when those gated steps are deferred.
|
|
1014
|
+
const doctorDeferred = Boolean(gatedSteps.doctor?.deferred_reason);
|
|
1015
|
+
const cacheDeferred = Boolean(gatedSteps.cache_fresh?.deferred_reason);
|
|
1016
|
+
orientationBundle = runOrientationCompression({
|
|
1017
|
+
projectRoot,
|
|
1018
|
+
frameworkRoot: options.frameworkRoot ?? projectRoot,
|
|
1019
|
+
compact: options.compact,
|
|
1020
|
+
env: options.env,
|
|
1021
|
+
now: instant,
|
|
1022
|
+
toolchainPreflight: options.toolchainPreflight,
|
|
1023
|
+
toolchainPreflightOptions: options.toolchainPreflightOptions,
|
|
1024
|
+
includeDoctor: !doctorDeferred,
|
|
1025
|
+
includeCacheFresh: !cacheDeferred,
|
|
1026
|
+
...options.orientationOptions,
|
|
1027
|
+
});
|
|
1028
|
+
toolchainPreflightResult = orientationBundle.preflight;
|
|
1029
|
+
lines.push(...orientationBundle.lines);
|
|
1030
|
+
for (const section of orientationBundle.sections) {
|
|
1031
|
+
stepTimings.push({
|
|
1032
|
+
name: section.name,
|
|
1033
|
+
duration_ms: section.durationMs,
|
|
1034
|
+
...(section.status === "skipped" ? { skipped: true } : {}),
|
|
1035
|
+
});
|
|
1036
|
+
if ((section.name === "doctor" || section.name === "cache_fresh") &&
|
|
1037
|
+
!gatedSteps[section.name]?.deferred_reason) {
|
|
1038
|
+
gatedSteps[section.name] = ritualStep({
|
|
1039
|
+
ok: section.ok,
|
|
1040
|
+
ts: instant,
|
|
1041
|
+
message: section.lines[0] ?? section.status,
|
|
1042
|
+
exitCode: section.exitCode,
|
|
1043
|
+
durationMs: section.durationMs,
|
|
1044
|
+
command: section.name === "doctor" ? ["doctor"] : ["verify:cache-fresh"],
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
stepTimings.push({ name: "orientation", duration_ms: elapsedMs(stepStarted) });
|
|
1049
|
+
}
|
|
1050
|
+
catch {
|
|
1051
|
+
// fail-open: orientation composition must not abort session:start —
|
|
1052
|
+
// fall back to preflight-only (#3282).
|
|
1053
|
+
try {
|
|
1054
|
+
if (options.toolchainPreflight !== null) {
|
|
1055
|
+
toolchainPreflightResult =
|
|
1056
|
+
options.toolchainPreflight ??
|
|
1057
|
+
runToolchainPreflight({
|
|
1058
|
+
projectRoot,
|
|
1059
|
+
frameworkRoot: options.frameworkRoot ?? projectRoot,
|
|
1060
|
+
...options.toolchainPreflightOptions,
|
|
1061
|
+
});
|
|
1062
|
+
lines.push(...toolchainPreflightResult.lines);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
catch {
|
|
1066
|
+
// ignore
|
|
1067
|
+
}
|
|
1068
|
+
stepTimings.push({ name: "orientation", duration_ms: elapsedMs(stepStarted) });
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
905
1072
|
// #3214: rapid/minimal skip informational cold-path ceremony only.
|
|
906
1073
|
if (!quickSteps.triage_welcome && !skipFatPath) {
|
|
907
1074
|
const stepStarted = performance.now();
|
|
@@ -1036,6 +1203,7 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1036
1203
|
reasons: [...provisionalDial.reasons],
|
|
1037
1204
|
},
|
|
1038
1205
|
};
|
|
1206
|
+
const preflightDict = toolchainPreflightResult !== null ? toolchainPreflightToDict(toolchainPreflightResult) : null;
|
|
1039
1207
|
const payload = {
|
|
1040
1208
|
...newRitualStatePayload({
|
|
1041
1209
|
sessionId: coldSessionId,
|
|
@@ -1047,6 +1215,8 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1047
1215
|
}),
|
|
1048
1216
|
// #3214: record dial choice on ritual-state for audit / later re-arm context.
|
|
1049
1217
|
ceremony_dial: dialDict,
|
|
1218
|
+
// #3282: durable preflight snapshot for harness / later check degraded mode.
|
|
1219
|
+
...(preflightDict !== null ? { toolchain_preflight: preflightDict } : {}),
|
|
1050
1220
|
};
|
|
1051
1221
|
let statePath;
|
|
1052
1222
|
try {
|
|
@@ -1070,8 +1240,45 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1070
1240
|
.filter(([, step]) => !step.ok && !step.deferred_reason)
|
|
1071
1241
|
.map(([name]) => name);
|
|
1072
1242
|
// verify_tools is recorded on quick_steps; failure makes ready=false.
|
|
1243
|
+
// #3282: toolchain preflight degraded mode does NOT flip ready=false by itself —
|
|
1244
|
+
// agents still proceed with a named skip report at check time.
|
|
1073
1245
|
const code = failed.length > 0 ? 1 : 0;
|
|
1074
1246
|
const totalMs = elapsedMs(overallStarted);
|
|
1247
|
+
// #3282 / #3286: event-driven run-summary (dial + preflight + orientation call
|
|
1248
|
+
// count for dual-path Later graduation trigger) — fail-open, silent when unset.
|
|
1249
|
+
if (options.emitRunSummary !== false) {
|
|
1250
|
+
try {
|
|
1251
|
+
const emitter = new RunSummaryEmitter({
|
|
1252
|
+
projectRoot,
|
|
1253
|
+
sessionId: coldSessionId,
|
|
1254
|
+
env: options.env,
|
|
1255
|
+
});
|
|
1256
|
+
emitter.emitSessionStart({
|
|
1257
|
+
ceremony_dial: dialDict,
|
|
1258
|
+
preflight: preflightDict ?? undefined,
|
|
1259
|
+
ceremony_tier: COLD_CEREMONY_TIER,
|
|
1260
|
+
ready: code === 0,
|
|
1261
|
+
exit_code: code,
|
|
1262
|
+
...(orientationBundle !== null
|
|
1263
|
+
? {
|
|
1264
|
+
orientation_call_count: orientationBundle.orientationCallCount,
|
|
1265
|
+
orientation_compact: orientationBundle.compact,
|
|
1266
|
+
deposit_sha: orientationBundle.depositSha,
|
|
1267
|
+
orientation_later_status: orientationBundle.later.status,
|
|
1268
|
+
orientation_sections: orientationBundle.sections.map((s) => ({
|
|
1269
|
+
name: s.name,
|
|
1270
|
+
status: s.status,
|
|
1271
|
+
ok: s.ok,
|
|
1272
|
+
sha_match: s.shaMatch,
|
|
1273
|
+
})),
|
|
1274
|
+
}
|
|
1275
|
+
: {}),
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
catch {
|
|
1279
|
+
// fail-open
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1075
1282
|
// #3117: bind live deposit generation when payload surfaces load (cold path).
|
|
1076
1283
|
let freshnessBind = null;
|
|
1077
1284
|
try {
|
|
@@ -1103,6 +1310,24 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1103
1310
|
exit_code: code,
|
|
1104
1311
|
ceremony_tier: COLD_CEREMONY_TIER,
|
|
1105
1312
|
ceremony_dial: dialDict,
|
|
1313
|
+
...(preflightDict !== null ? { toolchain_preflight: preflightDict } : {}),
|
|
1314
|
+
...(orientationBundle !== null
|
|
1315
|
+
? {
|
|
1316
|
+
orientation: {
|
|
1317
|
+
deposit_sha: orientationBundle.depositSha,
|
|
1318
|
+
compact: orientationBundle.compact,
|
|
1319
|
+
call_count: orientationBundle.orientationCallCount,
|
|
1320
|
+
later: orientationBundle.later,
|
|
1321
|
+
sections: orientationBundle.sections.map((s) => ({
|
|
1322
|
+
name: s.name,
|
|
1323
|
+
status: s.status,
|
|
1324
|
+
ok: s.ok,
|
|
1325
|
+
sha_match: s.shaMatch,
|
|
1326
|
+
exit_code: s.exitCode,
|
|
1327
|
+
})),
|
|
1328
|
+
},
|
|
1329
|
+
}
|
|
1330
|
+
: {}),
|
|
1106
1331
|
state_path: statePath,
|
|
1107
1332
|
...(freshnessBind ? { freshness: freshnessBind } : {}),
|
|
1108
1333
|
quick_steps: quickSteps,
|
|
@@ -1119,6 +1344,7 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1119
1344
|
environment: environmentContextToDict(environment),
|
|
1120
1345
|
scm: scmReadinessToDict(scm),
|
|
1121
1346
|
host_content_surface: hostContentSurfaceToDict(hostSurface.report),
|
|
1347
|
+
effort_budget: effortBudgetToDict(effortBudget.budget),
|
|
1122
1348
|
message: code === 0 ? "session ritual recorded" : "session ritual failed",
|
|
1123
1349
|
};
|
|
1124
1350
|
// #2994: local process-cost event (best-effort; never blocks ceremony).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Done-gate toolchain preflight at session start (#3282).
|
|
3
|
+
*
|
|
4
|
+
* Verifies the framework done-gate's own toolchain (task binary, package
|
|
5
|
+
* manager, node, optional CLI dist) up front so agents get a named cause +
|
|
6
|
+
* remedy in one turn instead of reverse-engineering `directive check` failures.
|
|
7
|
+
*
|
|
8
|
+
* Never bootstraps tooling the PRODUCT does not need. Failures name cause and
|
|
9
|
+
* remedy without embedding env values.
|
|
10
|
+
*/
|
|
11
|
+
export declare const TOOLCHAIN_PREFLIGHT_TOOLS: readonly ["task", "pnpm", "node", "git"];
|
|
12
|
+
export type ToolchainPreflightTool = (typeof TOOLCHAIN_PREFLIGHT_TOOLS)[number];
|
|
13
|
+
export type ToolchainPreflightStatus = "ok" | "missing" | "degraded";
|
|
14
|
+
export interface ToolchainPreflightFinding {
|
|
15
|
+
readonly tool: ToolchainPreflightTool | "cli_dist";
|
|
16
|
+
readonly present: boolean;
|
|
17
|
+
/** Machine-stable cause code (never embeds env values). */
|
|
18
|
+
readonly cause: string | null;
|
|
19
|
+
/** Operator/agent remedy command or instruction. */
|
|
20
|
+
readonly remedy: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface ToolchainPreflightResult {
|
|
23
|
+
readonly status: ToolchainPreflightStatus;
|
|
24
|
+
readonly ok: boolean;
|
|
25
|
+
/** True when missing tools would force check into degraded/skip mode. */
|
|
26
|
+
readonly degraded: boolean;
|
|
27
|
+
readonly findings: readonly ToolchainPreflightFinding[];
|
|
28
|
+
/** Human lines for session:start stdout (named cause + remedy). */
|
|
29
|
+
readonly lines: readonly string[];
|
|
30
|
+
/**
|
|
31
|
+
* Gate ids that check should skip when this preflight is degraded.
|
|
32
|
+
* Product-ordering of remaining gates is owned by #3284.
|
|
33
|
+
*/
|
|
34
|
+
readonly skipGateIds: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
export interface ToolchainPreflightOptions {
|
|
37
|
+
readonly projectRoot?: string;
|
|
38
|
+
readonly frameworkRoot?: string;
|
|
39
|
+
/** which(name) seam for tests. */
|
|
40
|
+
readonly which?: (name: string) => string | null;
|
|
41
|
+
/** existsSync seam for tests. */
|
|
42
|
+
readonly exists?: (path: string) => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* When true (default), also probe for a built CLI dist under frameworkRoot
|
|
45
|
+
* (framework-source dogfood). Consumers without a local dist are fine when
|
|
46
|
+
* a global `deft`/`directive` is on PATH.
|
|
47
|
+
*/
|
|
48
|
+
readonly probeCliDist?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Gates that specifically need a package manager / built dist.
|
|
52
|
+
* When task/node is missing, the orchestrator skips *all* scheduled gates
|
|
53
|
+
* (dynamic from gate-lists), not this static list — avoids hardcode drift.
|
|
54
|
+
*/
|
|
55
|
+
export declare const PNPM_DEPENDENT_GATE_IDS: readonly string[];
|
|
56
|
+
/** Sentinel skip id meaning "every gate in the active check composition". */
|
|
57
|
+
export declare const SKIP_ALL_GATES = "*";
|
|
58
|
+
/**
|
|
59
|
+
* Run done-gate toolchain preflight. Pure probe — never installs or builds.
|
|
60
|
+
*/
|
|
61
|
+
export declare function runToolchainPreflight(options?: ToolchainPreflightOptions): ToolchainPreflightResult;
|
|
62
|
+
/** Serialize preflight for run-summary / ritual-state (no env values). */
|
|
63
|
+
export declare function toolchainPreflightToDict(result: ToolchainPreflightResult): Record<string, unknown>;
|
|
64
|
+
//# sourceMappingURL=toolchain-preflight.d.ts.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Done-gate toolchain preflight at session start (#3282).
|
|
3
|
+
*
|
|
4
|
+
* Verifies the framework done-gate's own toolchain (task binary, package
|
|
5
|
+
* manager, node, optional CLI dist) up front so agents get a named cause +
|
|
6
|
+
* remedy in one turn instead of reverse-engineering `directive check` failures.
|
|
7
|
+
*
|
|
8
|
+
* Never bootstraps tooling the PRODUCT does not need. Failures name cause and
|
|
9
|
+
* remedy without embedding env values.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { defaultWhich } from "../doctor/which.js";
|
|
14
|
+
export const TOOLCHAIN_PREFLIGHT_TOOLS = ["task", "pnpm", "node", "git"];
|
|
15
|
+
const REMEDY = {
|
|
16
|
+
task: "Install go-task: https://taskfile.dev/installation/ (e.g. winget install Task.Task / brew install go-task)",
|
|
17
|
+
pnpm: "Enable pnpm via corepack: corepack enable && corepack prepare pnpm@latest --activate",
|
|
18
|
+
node: "Install Node 20+ (see .nvmrc); then corepack enable",
|
|
19
|
+
git: "Install Git: https://git-scm.com/downloads",
|
|
20
|
+
};
|
|
21
|
+
const CAUSE = {
|
|
22
|
+
task: "go-task binary not found on PATH",
|
|
23
|
+
pnpm: "pnpm binary not found on PATH",
|
|
24
|
+
node: "node binary not found on PATH",
|
|
25
|
+
git: "git binary not found on PATH",
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Gates that specifically need a package manager / built dist.
|
|
29
|
+
* When task/node is missing, the orchestrator skips *all* scheduled gates
|
|
30
|
+
* (dynamic from gate-lists), not this static list — avoids hardcode drift.
|
|
31
|
+
*/
|
|
32
|
+
export const PNPM_DEPENDENT_GATE_IDS = [
|
|
33
|
+
"toolchain:check",
|
|
34
|
+
"toolchain:check-consumer",
|
|
35
|
+
"ts:check-lane",
|
|
36
|
+
];
|
|
37
|
+
/** Sentinel skip id meaning "every gate in the active check composition". */
|
|
38
|
+
export const SKIP_ALL_GATES = "*";
|
|
39
|
+
function probeTool(tool, which) {
|
|
40
|
+
const present = which(tool) !== null;
|
|
41
|
+
return {
|
|
42
|
+
tool,
|
|
43
|
+
present,
|
|
44
|
+
cause: present ? null : CAUSE[tool],
|
|
45
|
+
remedy: present ? null : REMEDY[tool],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function probeCliDist(frameworkRoot, which, exists) {
|
|
49
|
+
const globalCli = which("deft") !== null || which("directive") !== null;
|
|
50
|
+
if (globalCli) {
|
|
51
|
+
return { tool: "cli_dist", present: true, cause: null, remedy: null };
|
|
52
|
+
}
|
|
53
|
+
if (frameworkRoot) {
|
|
54
|
+
const distBin = join(frameworkRoot, "packages", "cli", "dist", "bin.js");
|
|
55
|
+
if (exists(distBin)) {
|
|
56
|
+
return { tool: "cli_dist", present: true, cause: null, remedy: null };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
tool: "cli_dist",
|
|
60
|
+
present: false,
|
|
61
|
+
cause: "CLI dist missing and no global deft/directive on PATH",
|
|
62
|
+
remedy: "Run `task build` (framework source) or `npm i -g @deftai/directive@latest`",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
tool: "cli_dist",
|
|
67
|
+
present: false,
|
|
68
|
+
cause: "no global deft/directive on PATH",
|
|
69
|
+
remedy: "Install: npm i -g @deftai/directive@latest",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function formatFindingLine(finding) {
|
|
73
|
+
if (finding.present) {
|
|
74
|
+
return `[deft preflight] ${finding.tool}: ok`;
|
|
75
|
+
}
|
|
76
|
+
const cause = finding.cause ?? "missing";
|
|
77
|
+
const remedy = finding.remedy ?? "install the tool";
|
|
78
|
+
return `[deft preflight] ${finding.tool}: MISSING — cause: ${cause}; remedy: ${remedy}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Run done-gate toolchain preflight. Pure probe — never installs or builds.
|
|
82
|
+
*/
|
|
83
|
+
export function runToolchainPreflight(options = {}) {
|
|
84
|
+
const which = options.which ?? defaultWhich;
|
|
85
|
+
const exists = options.exists ?? existsSync;
|
|
86
|
+
const findings = [];
|
|
87
|
+
for (const tool of TOOLCHAIN_PREFLIGHT_TOOLS) {
|
|
88
|
+
findings.push(probeTool(tool, which));
|
|
89
|
+
}
|
|
90
|
+
if (options.probeCliDist !== false) {
|
|
91
|
+
findings.push(probeCliDist(options.frameworkRoot ?? options.projectRoot, which, exists));
|
|
92
|
+
}
|
|
93
|
+
const missingCritical = findings.filter((f) => !f.present && (f.tool === "task" || f.tool === "pnpm" || f.tool === "node"));
|
|
94
|
+
const taskMissing = findings.some((f) => f.tool === "task" && !f.present);
|
|
95
|
+
const pnpmMissing = findings.some((f) => f.tool === "pnpm" && !f.present);
|
|
96
|
+
const nodeMissing = findings.some((f) => f.tool === "node" && !f.present);
|
|
97
|
+
const skip = new Set();
|
|
98
|
+
if (taskMissing || nodeMissing) {
|
|
99
|
+
// Dynamic: orchestrator expands SKIP_ALL_GATES to the live gate list.
|
|
100
|
+
skip.add(SKIP_ALL_GATES);
|
|
101
|
+
}
|
|
102
|
+
else if (pnpmMissing) {
|
|
103
|
+
for (const id of PNPM_DEPENDENT_GATE_IDS) {
|
|
104
|
+
skip.add(id);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const degraded = missingCritical.length > 0;
|
|
108
|
+
const ok = !degraded;
|
|
109
|
+
const status = ok ? "ok" : "degraded";
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push(`[deft preflight] toolchain status: ${status}`);
|
|
112
|
+
for (const finding of findings) {
|
|
113
|
+
if (!finding.present) {
|
|
114
|
+
lines.push(formatFindingLine(finding));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (ok) {
|
|
118
|
+
lines.push("[deft preflight] done-gate toolchain ready (task, pnpm, node)");
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
lines.push("[deft preflight] degraded mode: directive check will skip toolchain-dependent gates " +
|
|
122
|
+
"with a named skip report rather than bootstrapping product-unneeded tooling (#3282)");
|
|
123
|
+
if (skip.size > 0) {
|
|
124
|
+
lines.push(`[deft preflight] gates subject to skip when degraded: ${[...skip].sort().join(", ")}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
status,
|
|
129
|
+
ok,
|
|
130
|
+
degraded,
|
|
131
|
+
findings,
|
|
132
|
+
lines,
|
|
133
|
+
skipGateIds: [...skip].sort(),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/** Serialize preflight for run-summary / ritual-state (no env values). */
|
|
137
|
+
export function toolchainPreflightToDict(result) {
|
|
138
|
+
return {
|
|
139
|
+
status: result.status,
|
|
140
|
+
ok: result.ok,
|
|
141
|
+
degraded: result.degraded,
|
|
142
|
+
findings: result.findings.map((f) => ({
|
|
143
|
+
tool: f.tool,
|
|
144
|
+
present: f.present,
|
|
145
|
+
cause: f.cause,
|
|
146
|
+
remedy: f.remedy,
|
|
147
|
+
})),
|
|
148
|
+
skip_gate_ids: [...result.skipGateIds],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=toolchain-preflight.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ActiveCliCheckResult, type ActiveCliCheckSeams } from "./active-cli.js";
|
|
1
2
|
import { type GitRunner } from "./git.js";
|
|
2
3
|
import { type DirectivePosture } from "./posture.js";
|
|
3
4
|
import { type GatedStepName, type SessionCeremonyTier } from "./session-start.js";
|
|
@@ -39,6 +40,19 @@ export interface VerifySessionRitualOptions {
|
|
|
39
40
|
readonly handoffText?: string | null;
|
|
40
41
|
/** Re-run selected gated prerequisites even when their recorded step is green. */
|
|
41
42
|
readonly forceGatedSteps?: readonly GatedStepName[];
|
|
43
|
+
/**
|
|
44
|
+
* #3233: engine version the post-upgrade / ritual check must match on the
|
|
45
|
+
* shell-active CLI. When null/omitted, still fail closed on multi-prefix
|
|
46
|
+
* version skew (active older than another PATH candidate).
|
|
47
|
+
*/
|
|
48
|
+
readonly targetEngineVersion?: string | null;
|
|
49
|
+
/** Injectable active-CLI seams for hermetic tests (#3233). */
|
|
50
|
+
readonly activeCliSeams?: ActiveCliCheckSeams;
|
|
51
|
+
/**
|
|
52
|
+
* Override the active-CLI probe entirely (tests). Defaults to
|
|
53
|
+
* {@link checkActiveCliAgainstTarget}.
|
|
54
|
+
*/
|
|
55
|
+
readonly checkActiveCli?: (targetVersion: string | null, seams?: ActiveCliCheckSeams) => ActiveCliCheckResult;
|
|
42
56
|
}
|
|
43
57
|
export interface InspectSessionRitualOptions {
|
|
44
58
|
readonly tier?: "quick" | "gated";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
+
import { readCorePackageVersion } from "../engine-version.js";
|
|
2
3
|
import { formatFrameworkCommand } from "../render/framework-commands.js";
|
|
4
|
+
import { checkActiveCliAgainstTarget, } from "./active-cli.js";
|
|
3
5
|
import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
|
|
4
6
|
import { pythonJsonDump } from "./json.js";
|
|
5
7
|
import { ENV_SESSION_POSTURE, readOnlyPostureMessage, resolveSessionPosture, ritualStateIsPostureAuthority, } from "./posture.js";
|
|
@@ -389,6 +391,37 @@ export function verifySessionRitual(projectRoot, options = {}) {
|
|
|
389
391
|
ritualStateRequired,
|
|
390
392
|
};
|
|
391
393
|
}
|
|
394
|
+
// #3233: after gated entrypoints, verify the shell-active deft/directive
|
|
395
|
+
// is not a stale higher-precedence shadow of a multi-prefix install.
|
|
396
|
+
// Independent target = explicit option, else in-process publishable engine
|
|
397
|
+
// (never the active CLI's own version — see resolveDefaultActiveCliTarget).
|
|
398
|
+
const targetEngineVersion = options.targetEngineVersion ?? null;
|
|
399
|
+
const checkActiveCli = options.checkActiveCli ?? checkActiveCliAgainstTarget;
|
|
400
|
+
let inProcessVersion = null;
|
|
401
|
+
try {
|
|
402
|
+
inProcessVersion = readCorePackageVersion();
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
inProcessVersion = null;
|
|
406
|
+
}
|
|
407
|
+
const activeCliSeams = {
|
|
408
|
+
inProcessVersion,
|
|
409
|
+
...options.activeCliSeams,
|
|
410
|
+
};
|
|
411
|
+
const activeCli = checkActiveCli(targetEngineVersion, activeCliSeams);
|
|
412
|
+
if (!activeCli.ok) {
|
|
413
|
+
return {
|
|
414
|
+
code: activeCli.code === 0 ? 1 : activeCli.code,
|
|
415
|
+
message: activeCli.lines.length > 0 ? activeCli.lines.join("\n") : activeCli.message,
|
|
416
|
+
tier,
|
|
417
|
+
statePath,
|
|
418
|
+
bypassed: false,
|
|
419
|
+
wouldFailCode: null,
|
|
420
|
+
posture,
|
|
421
|
+
ritualStateRequired,
|
|
422
|
+
recoveryTier: "cold",
|
|
423
|
+
};
|
|
424
|
+
}
|
|
392
425
|
}
|
|
393
426
|
const evaluated = evaluateLoadedState(projectRoot, state, {
|
|
394
427
|
tier,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type PathLike } from "node:fs";
|
|
2
|
+
import { type ParentLineageResult } from "../scope/parent-lineage.js";
|
|
2
3
|
import { type ParsedAllocation, parseAllocationSection, SOLO_KIND, SWARM_COHORT_KIND } from "./allocation.js";
|
|
3
4
|
export declare const ACTIVE_FOLDER = "active";
|
|
4
5
|
export declare const ELIGIBLE_STATUS = "running";
|
|
@@ -7,17 +8,27 @@ export interface EvaluateResult {
|
|
|
7
8
|
readonly exitCode: 0 | 1 | 2;
|
|
8
9
|
readonly message: string;
|
|
9
10
|
readonly dispatchKind: string | null;
|
|
11
|
+
/** #3241 parent-lineage probe (present when vBRIEF checks ran). */
|
|
12
|
+
readonly parentLineage?: ParentLineageResult;
|
|
10
13
|
}
|
|
11
14
|
export interface EvaluateOptions {
|
|
12
15
|
readonly gitStatus?: string | null;
|
|
13
16
|
readonly allocationContext?: string | null;
|
|
14
17
|
readonly allowDirty?: boolean;
|
|
15
18
|
readonly parsed?: ParsedAllocation;
|
|
19
|
+
/** Project root for resolving child planRef → parent (#3241). */
|
|
20
|
+
readonly projectRoot?: string;
|
|
21
|
+
/** Skip parent-lineage check (tests / opt-out). Default false. */
|
|
22
|
+
readonly skipParentLineage?: boolean;
|
|
16
23
|
}
|
|
17
24
|
/**
|
|
18
25
|
* Pure evaluator — returns exit code + human message. Faithful to
|
|
19
26
|
* `scripts/preflight_story_start.evaluate`.
|
|
27
|
+
*
|
|
28
|
+
* #3241: after structural active+running checks, re-check parent requirement
|
|
29
|
+
* lineage (coverage map + behavioral deltas) when the parent authors IDs.
|
|
20
30
|
*/
|
|
21
31
|
export declare function evaluate(vbriefPath: PathLike, options?: EvaluateOptions): EvaluateResult;
|
|
32
|
+
export { evaluateParentLineage, formatParentLineageLine, type ParentLineageResult, } from "../scope/parent-lineage.js";
|
|
22
33
|
export { parseAllocationSection, SOLO_KIND, SWARM_COHORT_KIND };
|
|
23
34
|
//# sourceMappingURL=evaluate.d.ts.map
|