@deftai/directive-core 0.105.0 → 0.107.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 +591 -34
- package/dist/check/gate-lists.js +2 -0
- package/dist/check/named-cause.js +1 -1
- package/dist/design-critique/exclusive-chip.d.ts +33 -0
- package/dist/design-critique/exclusive-chip.js +68 -0
- package/dist/design-critique/parent-audit.d.ts +59 -0
- package/dist/design-critique/parent-audit.js +121 -0
- package/dist/doctor/checks.d.ts +6 -0
- package/dist/doctor/checks.js +35 -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/hooks/dest-form.d.ts +46 -0
- package/dist/hooks/dest-form.js +575 -0
- package/dist/hooks/dispatcher.d.ts +17 -1
- package/dist/hooks/dispatcher.js +82 -11
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/init-deposit/agent-hooks.d.ts +1 -1
- package/dist/init-deposit/agent-hooks.js +1 -1
- package/dist/intake/clause-derivation.d.ts +9 -0
- package/dist/intake/clause-derivation.js +30 -3
- package/dist/intake/github-auth-modes-cli.js +14 -2
- package/dist/intake/github-auth-modes.d.ts +54 -9
- package/dist/intake/github-auth-modes.js +326 -123
- package/dist/lifecycle/completed-tracked-on-delivery.d.ts +26 -0
- package/dist/lifecycle/completed-tracked-on-delivery.js +37 -14
- package/dist/lifecycle/completed-write-guard.d.ts +48 -0
- package/dist/lifecycle/completed-write-guard.js +373 -0
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.js +1 -0
- 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 +16 -0
- package/dist/literal-acceptance/capture.js +78 -10
- package/dist/literal-acceptance/evaluate.js +25 -3
- package/dist/literal-acceptance/index.d.ts +2 -2
- package/dist/literal-acceptance/index.js +2 -2
- package/dist/literal-acceptance/run.js +9 -3
- package/dist/literal-acceptance/types.d.ts +6 -0
- package/dist/literal-acceptance/types.js +6 -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/policy/ceremony-dial.js +7 -7
- package/dist/policy/host-hooks.d.ts +20 -0
- package/dist/policy/host-hooks.js +121 -2
- 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/require-human-merge.js +8 -6
- package/dist/policy/resolve.d.ts +7 -2
- package/dist/policy/resolve.js +25 -8
- package/dist/policy/runtime-authority.d.ts +18 -0
- package/dist/policy/runtime-authority.js +11 -0
- package/dist/policy/value-feedback.js +7 -8
- package/dist/policy/write-fence.js +3 -0
- package/dist/preflight-cache/evaluate.d.ts +12 -0
- package/dist/preflight-cache/evaluate.js +24 -4
- package/dist/preflight-cache/index.d.ts +1 -1
- package/dist/preflight-cache/index.js +1 -1
- package/dist/product-first-done-gate/evaluate.d.ts +4 -0
- package/dist/product-first-done-gate/evaluate.js +82 -10
- 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/types.d.ts +4 -0
- package/dist/scm/design-critique-chip.d.ts +37 -0
- package/dist/scm/design-critique-chip.js +171 -0
- package/dist/scm/index.d.ts +1 -0
- package/dist/scm/index.js +1 -0
- package/dist/scm/main.d.ts +3 -0
- package/dist/scm/main.js +15 -1
- package/dist/scm/readiness-cli.d.ts +2 -0
- package/dist/scm/readiness-cli.js +42 -1
- package/dist/scm/readiness.d.ts +2 -1
- package/dist/scm/readiness.js +7 -1
- package/dist/scope/decompose.js +2 -1
- package/dist/scope/delivery-evidence.d.ts +27 -1
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/lifecycle-write.d.ts +24 -0
- package/dist/scope/lifecycle-write.js +64 -0
- package/dist/scope/main.js +18 -6
- package/dist/scope/promote-from-issue.js +5 -5
- package/dist/scope/transition.js +90 -11
- package/dist/scope-provenance/evaluate.js +8 -4
- package/dist/session/ac-pass-banking.d.ts +5 -0
- package/dist/session/ac-pass-banking.js +3 -2
- package/dist/session/git.d.ts +18 -0
- package/dist/session/git.js +81 -1
- package/dist/session/occupancy.d.ts +2 -1
- package/dist/session/occupancy.js +11 -4
- package/dist/session/process-cost.d.ts +32 -10
- package/dist/session/process-cost.js +189 -1
- package/dist/session/product-state-hash.js +41 -24
- package/dist/session/ritual-entrypoint.js +16 -1
- package/dist/session/session-start.d.ts +18 -0
- package/dist/session/session-start.js +49 -2
- package/dist/session/verify-session-ritual.d.ts +46 -4
- package/dist/session/verify-session-ritual.js +118 -10
- 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 +14 -2
- package/dist/swarm/launch.d.ts +69 -0
- package/dist/swarm/launch.js +191 -1
- package/dist/swarm/routing-set-cli.js +2 -0
- package/dist/swarm/routing-verify.d.ts +1 -1
- package/dist/swarm/routing-verify.js +2 -2
- package/dist/triage/actions/index.d.ts +4 -0
- package/dist/triage/actions/index.js +6 -0
- package/dist/triage/bootstrap/index.js +6 -6
- package/dist/triage/evaluate/evaluate.d.ts +11 -0
- package/dist/triage/evaluate/evaluate.js +169 -0
- package/dist/triage/evaluate/github.d.ts +16 -0
- package/dist/triage/evaluate/github.js +153 -0
- package/dist/triage/evaluate/index.d.ts +9 -0
- package/dist/triage/evaluate/index.js +8 -0
- package/dist/triage/evaluate/paths.d.ts +7 -0
- package/dist/triage/evaluate/paths.js +25 -0
- package/dist/triage/evaluate/sink.d.ts +5 -0
- package/dist/triage/evaluate/sink.js +52 -0
- package/dist/triage/evaluate/types.d.ts +93 -0
- package/dist/triage/evaluate/types.js +13 -0
- package/dist/triage/evaluate/validity.d.ts +8 -0
- package/dist/triage/evaluate/validity.js +87 -0
- package/dist/triage/evaluate/value.d.ts +12 -0
- package/dist/triage/evaluate/value.js +33 -0
- package/dist/triage/evaluate/wip-census.d.ts +5 -0
- package/dist/triage/evaluate/wip-census.js +39 -0
- package/dist/triage/evaluate/worktrees.d.ts +8 -0
- package/dist/triage/evaluate/worktrees.js +68 -0
- package/dist/triage/evaluate/xbrief-refs.d.ts +8 -0
- package/dist/triage/evaluate/xbrief-refs.js +60 -0
- package/dist/triage/help/registry-data.d.ts +22 -8
- package/dist/triage/help/registry-data.js +54 -6
- package/dist/triage/index.d.ts +1 -0
- package/dist/triage/index.js +1 -0
- package/dist/triage/welcome/writers.d.ts +1 -1
- package/dist/triage/welcome/writers.js +10 -5
- package/dist/value/feedback-file.d.ts +17 -2
- package/dist/value/feedback-file.js +80 -6
- package/dist/value/readback.d.ts +4 -1
- package/dist/value/readback.js +51 -12
- package/dist/vbrief-reconcile/labels.d.ts +1 -0
- package/dist/vbrief-reconcile/labels.js +30 -0
- package/dist/vbrief-validate/schema.d.ts +4 -0
- package/dist/vbrief-validate/schema.js +1 -1
- package/dist/vbrief-validation/story-quality.d.ts +7 -0
- package/dist/vbrief-validation/story-quality.js +8 -1
- 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/xbrief-migrate/agents-header.js +69 -7
- package/package.json +7 -3
|
@@ -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";
|
|
@@ -23,8 +24,20 @@ export type SessionCeremonyTier = (typeof SESSION_CEREMONY_TIERS)[number];
|
|
|
23
24
|
export declare const COLD_CEREMONY_TIER: SessionCeremonyTier;
|
|
24
25
|
export declare const REARM_CEREMONY_TIER: SessionCeremonyTier;
|
|
25
26
|
export declare const QUICK_STEPS: readonly ["alignment", "branch_policy", "triage_welcome", "verify_tools"];
|
|
27
|
+
/** Session / full gated ritual set. Write dispatch uses a per-surface subset (#3738). */
|
|
26
28
|
export declare const GATED_STEPS: readonly ["agent_hooks", "doctor", "cache_fresh"];
|
|
27
29
|
export type GatedStepName = (typeof GATED_STEPS)[number];
|
|
30
|
+
/**
|
|
31
|
+
* Gated steps a write/spawn mutation must prove from recorded ritual state (#3738).
|
|
32
|
+
* `cache_fresh` is a work-selection precondition, not a write-authorization one.
|
|
33
|
+
*/
|
|
34
|
+
export declare const WRITE_GATED_REQUIRED_STEPS: readonly ["agent_hooks", "doctor"];
|
|
35
|
+
/**
|
|
36
|
+
* Gated steps the write path may execute (#3738).
|
|
37
|
+
* Hook readiness is deliberately non-cacheable; doctor and cache_fresh stay
|
|
38
|
+
* session-surface only.
|
|
39
|
+
*/
|
|
40
|
+
export declare const WRITE_GATED_EXECUTE_STEPS: readonly ["agent_hooks"];
|
|
28
41
|
/** Env opt-in for optional session:start network (release probe + triage cache hydrate) (#2991). */
|
|
29
42
|
export declare const ENV_SESSION_START_NETWORK = "DEFT_SESSION_START_NETWORK";
|
|
30
43
|
/** Human-readable skip notice when optional network is off the hot path (#2991). */
|
|
@@ -117,6 +130,11 @@ export interface SessionStartOptions {
|
|
|
117
130
|
* network is enabled. Inject in tests.
|
|
118
131
|
*/
|
|
119
132
|
readonly probeScm?: (options: ProbeScmReadinessOptions) => ScmReadinessReport;
|
|
133
|
+
/**
|
|
134
|
+
* #3505: per-clone lifecycle-root visibility (ignore / skip-worktree).
|
|
135
|
+
* Warn-only; never blocks session:start. Inject in tests.
|
|
136
|
+
*/
|
|
137
|
+
readonly probeLifecycleVisible?: (projectRoot: string, runGit: GitRunner) => LifecycleVisibleResult;
|
|
120
138
|
/**
|
|
121
139
|
* #3214: ceremony dial inputs (task size × model tier × project shape).
|
|
122
140
|
* Missing fields are filled by the headless provisional classifier
|
|
@@ -3,6 +3,7 @@ import { emitSessionEvalReadback } from "../eval/readback.js";
|
|
|
3
3
|
import { bindSessionGeneration } from "../freshness/bind.js";
|
|
4
4
|
import { readLiveGeneration } from "../freshness/generation.js";
|
|
5
5
|
import { MIGRATE_COMPLETION_NUDGE, shouldEmitMigrateNudge } from "../init-deposit/migrate.js";
|
|
6
|
+
import { evaluateLifecycleVisible, formatLifecycleVisibleSessionLines, } from "../lifecycle-visible/evaluate.js";
|
|
6
7
|
import { hostContentSurfaceToDict, maybeFormatHostContentSurfaceLines, } from "../platform/host-content-surface.js";
|
|
7
8
|
import { detectEnvironmentContext, environmentContextToDict, formatEnvironmentContext, } from "../platform/shell-context.js";
|
|
8
9
|
import { ceremonyDialToDict, formatCeremonyDialStatusLine, mergeCeremonyDialDeferrals, resolveCeremonyDial, resolveSessionCeremonyDialInputs, } from "../policy/ceremony-dial.js";
|
|
@@ -26,8 +27,8 @@ import { ceremonyDialEvidenceToDict, collectCeremonyDialConsumerEvidence, format
|
|
|
26
27
|
import { effortBudgetToDict, maybeFormatEffortBudgetLines, resolveProductionHostEffortDescriptor, } from "./effort-budget.js";
|
|
27
28
|
import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
|
|
28
29
|
import { applyWorktreeOccupancy, } from "./occupancy.js";
|
|
29
|
-
import { runOrientationCompression, } from "./orientation-compression.js";
|
|
30
|
-
import { emitSessionStartProcessCost } from "./process-cost.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";
|
|
@@ -49,7 +50,36 @@ export const QUICK_STEPS = [
|
|
|
49
50
|
"triage_welcome",
|
|
50
51
|
"verify_tools",
|
|
51
52
|
];
|
|
53
|
+
/** Session / full gated ritual set. Write dispatch uses a per-surface subset (#3738). */
|
|
52
54
|
export const GATED_STEPS = ["agent_hooks", "doctor", "cache_fresh"];
|
|
55
|
+
/**
|
|
56
|
+
* Gated steps a write/spawn mutation must prove from recorded ritual state (#3738).
|
|
57
|
+
* `cache_fresh` is a work-selection precondition, not a write-authorization one.
|
|
58
|
+
*/
|
|
59
|
+
export const WRITE_GATED_REQUIRED_STEPS = [
|
|
60
|
+
"agent_hooks",
|
|
61
|
+
"doctor",
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Gated steps the write path may execute (#3738).
|
|
65
|
+
* Hook readiness is deliberately non-cacheable; doctor and cache_fresh stay
|
|
66
|
+
* session-surface only.
|
|
67
|
+
*/
|
|
68
|
+
export const WRITE_GATED_EXECUTE_STEPS = [
|
|
69
|
+
"agent_hooks",
|
|
70
|
+
];
|
|
71
|
+
/** Per-clone ignore/index hide of lifecycle roots — warn-only (#3505). */
|
|
72
|
+
function pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit) {
|
|
73
|
+
try {
|
|
74
|
+
const probe = options.probeLifecycleVisible ??
|
|
75
|
+
((root, git) => evaluateLifecycleVisible({ projectRoot: root, runGit: git }));
|
|
76
|
+
const result = probe(projectRoot, runGit);
|
|
77
|
+
lines.push(...formatLifecycleVisibleSessionLines(result));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// best-effort — session:start must not abort on a clone-local advisory
|
|
81
|
+
}
|
|
82
|
+
}
|
|
53
83
|
/** Standing one-liner when coverageDebt/checkResume is non-default (#3314). */
|
|
54
84
|
function pushCoverageCheckResumeDisclosure(lines, projectRoot) {
|
|
55
85
|
try {
|
|
@@ -494,6 +524,8 @@ function runReadOnlySessionStart(projectRoot, options, instant, environment) {
|
|
|
494
524
|
lines.push(...formatScmReadinessLines(scm));
|
|
495
525
|
lines.push(...hostSurface.lines);
|
|
496
526
|
lines.push(...effortBudget.lines);
|
|
527
|
+
const runGit = options.runGit ?? defaultGitRunner;
|
|
528
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
497
529
|
const resultPayload = {
|
|
498
530
|
ready: true,
|
|
499
531
|
exit_code: 0,
|
|
@@ -576,6 +608,7 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
576
608
|
...effortBudget.lines,
|
|
577
609
|
REARM_SKIPPED_FAT_PATH_MESSAGE,
|
|
578
610
|
];
|
|
611
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
579
612
|
// Light branch-policy disclosure (local only) so re-arm still surfaces policy state.
|
|
580
613
|
const policyResult = resolvePolicy(projectRoot);
|
|
581
614
|
const policyMessage = disclosureLine(policyResult);
|
|
@@ -739,6 +772,10 @@ function runSessionRearm(projectRoot, options, instant, environment) {
|
|
|
739
772
|
optionalNetwork: false,
|
|
740
773
|
steps: stepTimings,
|
|
741
774
|
}, { projectRoot });
|
|
775
|
+
// #3508: operator-visible CLI process time. ⊗ not #3286 Later graduation input.
|
|
776
|
+
if (!resolveSessionCompact({ compact: options.compact, env: options.env })) {
|
|
777
|
+
lines.push(formatSessionStartCeremonyCostLine(REARM_CEREMONY_TIER, totalMs));
|
|
778
|
+
}
|
|
742
779
|
return {
|
|
743
780
|
code,
|
|
744
781
|
payload: {
|
|
@@ -976,6 +1013,12 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
976
1013
|
name: "effort_budget",
|
|
977
1014
|
duration_ms: elapsedMs(effortBudgetStepStarted),
|
|
978
1015
|
});
|
|
1016
|
+
const lifecycleVisibleStarted = performance.now();
|
|
1017
|
+
pushLifecycleVisibleAdvisory(lines, projectRoot, options, runGit);
|
|
1018
|
+
stepTimings.push({
|
|
1019
|
+
name: "lifecycle_visible",
|
|
1020
|
+
duration_ms: elapsedMs(lifecycleVisibleStarted),
|
|
1021
|
+
});
|
|
979
1022
|
if (!quickSteps.branch_policy) {
|
|
980
1023
|
const stepStarted = performance.now();
|
|
981
1024
|
const result = resolvePolicy(projectRoot);
|
|
@@ -1461,6 +1504,10 @@ export function runSessionStart(projectRoot, options = {}) {
|
|
|
1461
1504
|
optionalNetwork: allowOptionalNetwork,
|
|
1462
1505
|
steps: stepTimings,
|
|
1463
1506
|
}, { projectRoot });
|
|
1507
|
+
// #3508: operator-visible CLI process time. ⊗ not #3286 Later graduation input.
|
|
1508
|
+
if (!resolveSessionCompact({ compact: options.compact, env: options.env })) {
|
|
1509
|
+
lines.push(formatSessionStartCeremonyCostLine(COLD_CEREMONY_TIER, totalMs));
|
|
1510
|
+
}
|
|
1464
1511
|
return { code, payload: resultPayload, lines };
|
|
1465
1512
|
}
|
|
1466
1513
|
export { ritualStatePath };
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import { type ActiveCliCheckResult, type ActiveCliCheckSeams } from "./active-cli.js";
|
|
2
2
|
import { type GitRunner } from "./git.js";
|
|
3
3
|
import { type DirectivePosture } from "./posture.js";
|
|
4
|
-
import { type GatedStepName, type SessionCeremonyTier } from "./session-start.js";
|
|
4
|
+
import { type GatedStepName, type SessionCeremonyTier, WRITE_GATED_EXECUTE_STEPS, WRITE_GATED_REQUIRED_STEPS } from "./session-start.js";
|
|
5
5
|
export { formatCacheFetchAllRecoveryCommand, recoveryHintForStaleFailure, } from "./cache-recovery.js";
|
|
6
|
+
export { WRITE_GATED_EXECUTE_STEPS, WRITE_GATED_REQUIRED_STEPS };
|
|
6
7
|
export declare const ENV_SKIP = "DEFT_SESSION_RITUAL_SKIP";
|
|
7
8
|
export { ENTRYPOINT_TIMEOUT_EXIT_CODE, ENTRYPOINT_TIMEOUT_SECONDS, } from "./ritual-entrypoint.js";
|
|
8
9
|
export declare const GATED_ENTRYPOINT_COMMANDS: Readonly<Record<GatedStepName, readonly string[]>>;
|
|
10
|
+
/** Explicit skip flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
11
|
+
export declare const SKIP_DRIFT_PROBE_FLAG = "--skip-drift-probe";
|
|
12
|
+
/** Explicit work-selection flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
13
|
+
export declare const WORK_SELECTION_FLAG = "--work-selection";
|
|
14
|
+
/** Distinct ritual-state field — never `deferred_reason` (#3507). */
|
|
15
|
+
export declare const DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION = "skipped-no-work-selection";
|
|
16
|
+
export type WorkSelectionKind = "none" | "active-story" | "triage-queue" | "ordered-plan" | "for-issue" | "explicit-flag";
|
|
17
|
+
export interface WorkSelectionSignal {
|
|
18
|
+
readonly inPlay: boolean;
|
|
19
|
+
readonly kind: WorkSelectionKind;
|
|
20
|
+
}
|
|
21
|
+
export type DetectWorkSelection = (projectRoot: string) => WorkSelectionSignal;
|
|
22
|
+
/**
|
|
23
|
+
* Default work-selection detector for the gated `cache_fresh` seam (#3507).
|
|
24
|
+
* Active story xBRIEF (scope:activate residue), unexhausted ordered-plan /
|
|
25
|
+
* triage sequence. `--for-issue` is a positive evaluate override, not this
|
|
26
|
+
* detector — the gated argv never carries it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectWorkSelection(projectRoot: string): WorkSelectionSignal;
|
|
29
|
+
export declare function resolveGatedEntrypointCommand(stepName: GatedStepName, projectRoot: string, detect?: DetectWorkSelection): string[];
|
|
9
30
|
export interface VerifyResult {
|
|
10
31
|
readonly code: number;
|
|
11
32
|
readonly message: string;
|
|
@@ -30,7 +51,8 @@ export type RitualRunner = (command: readonly string[], projectRoot: string) =>
|
|
|
30
51
|
export declare function formatRitualRecoveryInstruction(tier?: SessionCeremonyTier): string;
|
|
31
52
|
/**
|
|
32
53
|
* Sanctioned audited defer copy for gated `cache_fresh` failure (#3506 / #3507).
|
|
33
|
-
*
|
|
54
|
+
* Independent of the #3507 work-selection argv seam — defer is still the
|
|
55
|
+
* operator-audited escape, not the drift-probe skip.
|
|
34
56
|
*/
|
|
35
57
|
export declare function formatCacheFreshDeferSoftPath(): string;
|
|
36
58
|
export interface VerifySessionRitualOptions {
|
|
@@ -58,7 +80,26 @@ export interface VerifySessionRitualOptions {
|
|
|
58
80
|
* {@link checkActiveCliAgainstTarget}.
|
|
59
81
|
*/
|
|
60
82
|
readonly checkActiveCli?: (targetVersion: string | null, seams?: ActiveCliCheckSeams) => ActiveCliCheckResult;
|
|
83
|
+
/** Injectable work-selection detector for gated `cache_fresh` (#3507). */
|
|
84
|
+
readonly detectWorkSelection?: DetectWorkSelection;
|
|
85
|
+
/**
|
|
86
|
+
* Required gated steps for this surface. Defaults to all {@link GATED_STEPS}
|
|
87
|
+
* (session / full gated verify). Write dispatch uses
|
|
88
|
+
* {@link WRITE_GATED_REQUIRED_STEPS} (#3738).
|
|
89
|
+
*/
|
|
90
|
+
readonly requiredGatedSteps?: readonly GatedStepName[];
|
|
91
|
+
/**
|
|
92
|
+
* Gated steps this surface may execute. Defaults to all {@link GATED_STEPS}.
|
|
93
|
+
* Write dispatch uses {@link WRITE_GATED_EXECUTE_STEPS} so `cache_fresh` and
|
|
94
|
+
* `doctor` cannot run as write-path repair (#3738).
|
|
95
|
+
*/
|
|
96
|
+
readonly executeGatedSteps?: readonly GatedStepName[];
|
|
61
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Options for the write/spawn mutation verifier (#3738).
|
|
100
|
+
* Required set omits `cache_fresh`; execution authority is `agent_hooks` only.
|
|
101
|
+
*/
|
|
102
|
+
export declare function writeGateRitualOptions(extras?: Omit<VerifySessionRitualOptions, "requiredGatedSteps" | "executeGatedSteps" | "tier">): VerifySessionRitualOptions;
|
|
62
103
|
export interface InspectSessionRitualOptions {
|
|
63
104
|
readonly tier?: "quick" | "gated";
|
|
64
105
|
readonly now?: Date;
|
|
@@ -71,8 +112,9 @@ export interface InspectSessionRitualOptions {
|
|
|
71
112
|
* Read-only ritual-state inspection for host hooks.
|
|
72
113
|
*
|
|
73
114
|
* Unlike {@link verifySessionRitual}, this never runs missing gated entrypoints
|
|
74
|
-
* and never rewrites `.deft/ritual-state.json`.
|
|
75
|
-
*
|
|
115
|
+
* and never rewrites `.deft/ritual-state.json`. Write dispatch does **not** use
|
|
116
|
+
* this function: it must still execute `agent_hooks` (#3738). A PreToolUse
|
|
117
|
+
* decision must not become a hidden `doctor` / cache-refresh mutation boundary.
|
|
76
118
|
*/
|
|
77
119
|
export declare function inspectSessionRitual(projectRoot: string, options?: InspectSessionRitualOptions): VerifyResult;
|
|
78
120
|
export declare function verifySessionRitual(projectRoot: string, options?: VerifySessionRitualOptions): VerifyResult;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
2
3
|
import { readCorePackageVersion } from "../engine-version.js";
|
|
4
|
+
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
5
|
+
import { readPlanSequence } from "../plan-sequence/store.js";
|
|
3
6
|
import { formatFrameworkCommand } from "../render/framework-commands.js";
|
|
4
7
|
import { checkActiveCliAgainstTarget, } from "./active-cli.js";
|
|
5
8
|
import { defaultGitRunner, gitHead, gitIsAncestor, worktreePath } from "./git.js";
|
|
@@ -7,9 +10,10 @@ import { pythonJsonDump } from "./json.js";
|
|
|
7
10
|
import { ENV_SESSION_POSTURE, readOnlyPostureMessage, resolveSessionPosture, ritualStateIsPostureAuthority, } from "./posture.js";
|
|
8
11
|
import { defaultRitualRunner } from "./ritual-entrypoint.js";
|
|
9
12
|
import { readRitualState, ritualStateMarksRearmNeeded, ritualStatePath, ritualStep, writeRitualState, } from "./ritual-sentinel.js";
|
|
10
|
-
import { formatSessionStartRecoveryCommand, GATED_STEPS, QUICK_STEPS, } from "./session-start.js";
|
|
13
|
+
import { formatSessionStartRecoveryCommand, GATED_STEPS, QUICK_STEPS, WRITE_GATED_EXECUTE_STEPS, WRITE_GATED_REQUIRED_STEPS, } from "./session-start.js";
|
|
11
14
|
import { resolveSessionRitualStalenessHours } from "./staleness.js";
|
|
12
15
|
export { formatCacheFetchAllRecoveryCommand, recoveryHintForStaleFailure, } from "./cache-recovery.js";
|
|
16
|
+
export { WRITE_GATED_EXECUTE_STEPS, WRITE_GATED_REQUIRED_STEPS };
|
|
13
17
|
export const ENV_SKIP = "DEFT_SESSION_RITUAL_SKIP";
|
|
14
18
|
export { ENTRYPOINT_TIMEOUT_EXIT_CODE, ENTRYPOINT_TIMEOUT_SECONDS, } from "./ritual-entrypoint.js";
|
|
15
19
|
export const GATED_ENTRYPOINT_COMMANDS = {
|
|
@@ -17,6 +21,64 @@ export const GATED_ENTRYPOINT_COMMANDS = {
|
|
|
17
21
|
doctor: ["doctor"],
|
|
18
22
|
cache_fresh: ["verify:cache-fresh"],
|
|
19
23
|
};
|
|
24
|
+
/** Explicit skip flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
25
|
+
export const SKIP_DRIFT_PROBE_FLAG = "--skip-drift-probe";
|
|
26
|
+
/** Explicit work-selection flag threaded through the gated `cache_fresh` argv (#3507). */
|
|
27
|
+
export const WORK_SELECTION_FLAG = "--work-selection";
|
|
28
|
+
/** Distinct ritual-state field — never `deferred_reason` (#3507). */
|
|
29
|
+
export const DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION = "skipped-no-work-selection";
|
|
30
|
+
function hasActiveStoryArtifact(projectRoot) {
|
|
31
|
+
for (const dirName of ["xbrief", "vbrief"]) {
|
|
32
|
+
const activeDir = join(projectRoot, dirName, "active");
|
|
33
|
+
try {
|
|
34
|
+
for (const entry of readdirSync(activeDir, { withFileTypes: true })) {
|
|
35
|
+
if (entry.isFile() && hasArtifactSuffix(entry.name))
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
/* missing or unreadable active folder is not work selection */
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
function hasUnexhaustedPlanSequence(projectRoot) {
|
|
46
|
+
try {
|
|
47
|
+
const sequence = readPlanSequence(projectRoot);
|
|
48
|
+
if (sequence === null || sequence.exhausted === true)
|
|
49
|
+
return null;
|
|
50
|
+
return sequence.sequence_kind === "triage" ? "triage-queue" : "ordered-plan";
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Default work-selection detector for the gated `cache_fresh` seam (#3507).
|
|
58
|
+
* Active story xBRIEF (scope:activate residue), unexhausted ordered-plan /
|
|
59
|
+
* triage sequence. `--for-issue` is a positive evaluate override, not this
|
|
60
|
+
* detector — the gated argv never carries it.
|
|
61
|
+
*/
|
|
62
|
+
export function detectWorkSelection(projectRoot) {
|
|
63
|
+
if (hasActiveStoryArtifact(projectRoot)) {
|
|
64
|
+
return { inPlay: true, kind: "active-story" };
|
|
65
|
+
}
|
|
66
|
+
const planKind = hasUnexhaustedPlanSequence(projectRoot);
|
|
67
|
+
if (planKind !== null) {
|
|
68
|
+
return { inPlay: true, kind: planKind };
|
|
69
|
+
}
|
|
70
|
+
return { inPlay: false, kind: "none" };
|
|
71
|
+
}
|
|
72
|
+
export function resolveGatedEntrypointCommand(stepName, projectRoot, detect = detectWorkSelection) {
|
|
73
|
+
const base = [...GATED_ENTRYPOINT_COMMANDS[stepName]];
|
|
74
|
+
if (stepName !== "cache_fresh")
|
|
75
|
+
return base;
|
|
76
|
+
const selection = detect(projectRoot);
|
|
77
|
+
if (selection.inPlay) {
|
|
78
|
+
return [...base, WORK_SELECTION_FLAG];
|
|
79
|
+
}
|
|
80
|
+
return [...base, SKIP_DRIFT_PROBE_FLAG];
|
|
81
|
+
}
|
|
20
82
|
function truthy(raw) {
|
|
21
83
|
return new Set(["1", "true", "yes", "on"]).has((raw ?? "").trim().toLowerCase());
|
|
22
84
|
}
|
|
@@ -25,6 +87,7 @@ function stepPasses(step) {
|
|
|
25
87
|
return false;
|
|
26
88
|
if (step.deferred_reason)
|
|
27
89
|
return true;
|
|
90
|
+
// `drift_probe` is a distinct diagnostic; it must never satisfy a step (#3507).
|
|
28
91
|
return step.ok === true;
|
|
29
92
|
}
|
|
30
93
|
function failedStepMessage(tierName, stepName, step) {
|
|
@@ -52,14 +115,29 @@ export function formatRitualRecoveryInstruction(tier = "cold") {
|
|
|
52
115
|
}
|
|
53
116
|
/**
|
|
54
117
|
* Sanctioned audited defer copy for gated `cache_fresh` failure (#3506 / #3507).
|
|
55
|
-
*
|
|
118
|
+
* Independent of the #3507 work-selection argv seam — defer is still the
|
|
119
|
+
* operator-audited escape, not the drift-probe skip.
|
|
56
120
|
*/
|
|
57
121
|
export function formatCacheFreshDeferSoftPath() {
|
|
58
122
|
const cmd = formatFrameworkCommand(["session:start", "--", "--defer", "cache_fresh=<reason>"]);
|
|
59
123
|
return `Soft path (audited): \`${cmd}\`.`;
|
|
60
124
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
125
|
+
function applyCacheFreshDriftProbeField(payload, command) {
|
|
126
|
+
if (command.includes(SKIP_DRIFT_PROBE_FLAG)) {
|
|
127
|
+
payload.drift_probe = DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (payload.drift_probe === DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION) {
|
|
131
|
+
delete payload.drift_probe;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function shouldRearmDriftProbe(payload, projectRoot, detect) {
|
|
135
|
+
if (payload.drift_probe !== DRIFT_PROBE_SKIPPED_NO_WORK_SELECTION)
|
|
136
|
+
return false;
|
|
137
|
+
return detect(projectRoot).inPlay;
|
|
138
|
+
}
|
|
139
|
+
function runGatedStep(projectRoot, payload, stepName, runner, now, detect = detectWorkSelection) {
|
|
140
|
+
const command = resolveGatedEntrypointCommand(stepName, projectRoot, detect);
|
|
63
141
|
const { code, stdout, stderr } = runner(command, projectRoot);
|
|
64
142
|
const message = stdout.trim() || stderr.trim() || `${command[0]} exited ${code}`;
|
|
65
143
|
const gated = payload.gated_steps ?? {};
|
|
@@ -71,6 +149,9 @@ function runGatedStep(projectRoot, payload, stepName, runner, now) {
|
|
|
71
149
|
command,
|
|
72
150
|
});
|
|
73
151
|
payload.gated_steps = gated;
|
|
152
|
+
if (stepName === "cache_fresh") {
|
|
153
|
+
applyCacheFreshDriftProbeField(payload, command);
|
|
154
|
+
}
|
|
74
155
|
try {
|
|
75
156
|
writeRitualState(projectRoot, payload);
|
|
76
157
|
}
|
|
@@ -164,7 +245,8 @@ function evaluateLoadedState(projectRoot, state, input) {
|
|
|
164
245
|
}
|
|
165
246
|
}
|
|
166
247
|
if (input.tier === "gated") {
|
|
167
|
-
|
|
248
|
+
const requiredGated = input.requiredGatedSteps ?? GATED_STEPS;
|
|
249
|
+
for (const stepName of requiredGated) {
|
|
168
250
|
const step = state.gatedSteps[stepName];
|
|
169
251
|
if (!stepPasses(step)) {
|
|
170
252
|
return {
|
|
@@ -181,12 +263,31 @@ function evaluateLoadedState(projectRoot, state, input) {
|
|
|
181
263
|
recoveryTier: null,
|
|
182
264
|
};
|
|
183
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Options for the write/spawn mutation verifier (#3738).
|
|
268
|
+
* Required set omits `cache_fresh`; execution authority is `agent_hooks` only.
|
|
269
|
+
*/
|
|
270
|
+
export function writeGateRitualOptions(extras = {}) {
|
|
271
|
+
return {
|
|
272
|
+
...extras,
|
|
273
|
+
tier: "gated",
|
|
274
|
+
posture: extras.posture ?? "mutation",
|
|
275
|
+
requiredGatedSteps: WRITE_GATED_REQUIRED_STEPS,
|
|
276
|
+
executeGatedSteps: WRITE_GATED_EXECUTE_STEPS,
|
|
277
|
+
// Write dispatch already refuses skip (dispatcher passes bypass: false).
|
|
278
|
+
// Default the same here so CI DEFT_SESSION_RITUAL_SKIP=1 cannot empty
|
|
279
|
+
// the execute loop in tests that use this helper (#3738).
|
|
280
|
+
bypass: extras.bypass ?? false,
|
|
281
|
+
envSkip: extras.envSkip ?? "",
|
|
282
|
+
};
|
|
283
|
+
}
|
|
184
284
|
/**
|
|
185
285
|
* Read-only ritual-state inspection for host hooks.
|
|
186
286
|
*
|
|
187
287
|
* Unlike {@link verifySessionRitual}, this never runs missing gated entrypoints
|
|
188
|
-
* and never rewrites `.deft/ritual-state.json`.
|
|
189
|
-
*
|
|
288
|
+
* and never rewrites `.deft/ritual-state.json`. Write dispatch does **not** use
|
|
289
|
+
* this function: it must still execute `agent_hooks` (#3738). A PreToolUse
|
|
290
|
+
* decision must not become a hidden `doctor` / cache-refresh mutation boundary.
|
|
190
291
|
*/
|
|
191
292
|
export function inspectSessionRitual(projectRoot, options = {}) {
|
|
192
293
|
const tier = options.tier ?? "quick";
|
|
@@ -361,16 +462,22 @@ export function verifySessionRitual(projectRoot, options = {}) {
|
|
|
361
462
|
payload.gated_steps = gated;
|
|
362
463
|
const runCmd = options.runner ?? defaultRitualRunner;
|
|
363
464
|
const forced = new Set(options.forceGatedSteps ?? []);
|
|
465
|
+
const detect = options.detectWorkSelection ?? detectWorkSelection;
|
|
466
|
+
const executable = new Set(options.executeGatedSteps ?? [...GATED_STEPS]);
|
|
364
467
|
for (const stepName of GATED_STEPS) {
|
|
468
|
+
if (!executable.has(stepName))
|
|
469
|
+
continue;
|
|
365
470
|
const step = gated[stepName];
|
|
366
471
|
if (step?.deferred_reason && stepName !== "agent_hooks")
|
|
367
472
|
continue;
|
|
368
473
|
// Hook readiness is a live mutation prerequisite, not a cacheable doctor
|
|
369
474
|
// result. Re-run it at every gated boundary so registration/shim drift
|
|
370
475
|
// cannot remain hidden behind an earlier green ritual record.
|
|
371
|
-
|
|
476
|
+
const rearmDrift = stepName === "cache_fresh" && shouldRearmDriftProbe(payload, projectRoot, detect);
|
|
477
|
+
if (stepName !== "agent_hooks" && stepPasses(step) && !forced.has(stepName) && !rearmDrift) {
|
|
372
478
|
continue;
|
|
373
|
-
|
|
479
|
+
}
|
|
480
|
+
const writeError = runGatedStep(projectRoot, payload, stepName, runCmd, instant, detect);
|
|
374
481
|
if (writeError !== null) {
|
|
375
482
|
return {
|
|
376
483
|
code: 2,
|
|
@@ -436,6 +543,7 @@ export function verifySessionRitual(projectRoot, options = {}) {
|
|
|
436
543
|
now: instant,
|
|
437
544
|
runGit: options.runGit,
|
|
438
545
|
rebindForwardHead: true,
|
|
546
|
+
requiredGatedSteps: options.requiredGatedSteps,
|
|
439
547
|
});
|
|
440
548
|
if (isBypassed) {
|
|
441
549
|
return {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
export
|
|
2
|
+
import { type FinalizeCohortArgs } from "./finalize-cohort.js";
|
|
3
|
+
export interface ParsedFinalizeCohortArgv extends FinalizeCohortArgs {
|
|
4
|
+
readonly help: boolean;
|
|
5
|
+
readonly error: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const FINALIZE_COHORT_USAGE = "Usage: task swarm:finalize-cohort -- [--pr <n>[,<n>...]] [--stories <ids|paths>] [options]\n\nAfter cohort PRs merge, sweep story briefs active/ -> completed/ and open the lifecycle PR.\n\nOptions:\n --pr <n>[,<n>...] Merged PR numbers (closing issues map to active stories)\n --stories <ids|paths> Explicit story tokens (repeatable)\n --repo OWNER/REPO GitHub repo (or $GH_REPO)\n --project-root <path> Project root (default: cwd)\n --base-branch <name> Sweep/PR base (default: resolved delivery branch)\n --delivery-branch <name> Delivery-branch override when policy is untyped\n --label <name> Feature-branch label\n --dry-run Print plan; no git mutation\n --no-commit Sweep without committing / opening a PR\n --no-open-pr Commit without opening a PR\n --json Machine-readable result\n -h, --help Show this help\n";
|
|
8
|
+
export declare function parseFinalizeCohortArgv(argv: readonly string[]): ParsedFinalizeCohortArgv;
|
|
4
9
|
export declare function finalizeCohortMain(argv?: string[]): number;
|
|
5
10
|
//# sourceMappingURL=finalize-cohort-cli.d.ts.map
|