@deftai/directive-core 0.100.0 → 0.102.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 +193 -27
- package/dist/authz/decompose-apply.d.ts +14 -0
- package/dist/authz/decompose-apply.js +93 -18
- package/dist/check/cached-orchestrator.d.ts +30 -5
- package/dist/check/cached-orchestrator.js +297 -10
- package/dist/check/cli-native-gates.d.ts +43 -0
- package/dist/check/cli-native-gates.js +84 -0
- package/dist/check/gate-lists.d.ts +10 -4
- package/dist/check/gate-lists.js +19 -5
- package/dist/check/index.d.ts +4 -2
- package/dist/check/index.js +3 -1
- package/dist/check/named-cause.d.ts +45 -0
- package/dist/check/named-cause.js +131 -0
- package/dist/check/orchestrator.js +6 -1
- package/dist/doctor/checks.d.ts +5 -6
- package/dist/doctor/checks.js +13 -56
- 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.js +58 -0
- 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/eval/later-graduation.d.ts +39 -0
- package/dist/eval/later-graduation.js +91 -0
- package/dist/eval/report.d.ts +6 -0
- package/dist/eval/report.js +27 -8
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/init-deposit/gitignore.js +2 -0
- package/dist/intake/issue-ingest.js +49 -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-escalation.d.ts +52 -0
- package/dist/policy/ceremony-dial-escalation.js +92 -0
- package/dist/policy/ceremony-dial.d.ts +32 -1
- package/dist/policy/ceremony-dial.js +128 -1
- package/dist/policy/check-resume.d.ts +9 -38
- package/dist/policy/check-resume.js +18 -156
- package/dist/policy/coverage-debt.d.ts +18 -37
- package/dist/policy/coverage-debt.js +38 -147
- package/dist/policy/index.d.ts +2 -1
- package/dist/policy/index.js +16 -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 +269 -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/empty-resolution.d.ts +26 -0
- package/dist/product-first-done-gate/empty-resolution.js +38 -0
- package/dist/product-first-done-gate/evaluate.d.ts +76 -0
- package/dist/product-first-done-gate/evaluate.js +411 -0
- package/dist/product-first-done-gate/index.d.ts +12 -0
- package/dist/product-first-done-gate/index.js +12 -0
- package/dist/product-first-done-gate/types.d.ts +67 -0
- package/dist/product-first-done-gate/types.js +54 -0
- package/dist/run-summary/emit.d.ts +66 -0
- package/dist/run-summary/emit.js +217 -0
- package/dist/run-summary/index.d.ts +5 -0
- package/dist/run-summary/index.js +5 -0
- package/dist/run-summary/path.d.ts +25 -0
- package/dist/run-summary/path.js +78 -0
- package/dist/run-summary/share.d.ts +25 -0
- package/dist/run-summary/share.js +106 -0
- package/dist/run-summary/types.d.ts +134 -0
- package/dist/run-summary/types.js +28 -0
- package/dist/scope/acceptance-activate-gate.d.ts +23 -0
- package/dist/scope/acceptance-activate-gate.js +70 -0
- package/dist/scope/acceptance-evidence.d.ts +34 -0
- package/dist/scope/acceptance-evidence.js +84 -10
- package/dist/scope/decompose.d.ts +5 -0
- package/dist/scope/decompose.js +11 -2
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/transition.js +5 -0
- package/dist/session/ac-pass-banking.d.ts +221 -0
- package/dist/session/ac-pass-banking.js +761 -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 +6 -0
- package/dist/session/effort-budget.js +21 -3
- package/dist/session/index.d.ts +5 -1
- package/dist/session/index.js +5 -1
- package/dist/session/orientation-compression.d.ts +127 -0
- package/dist/session/orientation-compression.js +435 -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 +219 -22
- package/dist/session/toolchain-preflight.d.ts +79 -0
- package/dist/session/toolchain-preflight.js +211 -0
- 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/verify-ac/clauses.d.ts +51 -0
- package/dist/verify-ac/clauses.js +490 -0
- package/dist/verify-ac/evaluate.d.ts +55 -0
- package/dist/verify-ac/evaluate.js +145 -0
- package/dist/verify-ac/flag.d.ts +35 -0
- package/dist/verify-ac/flag.js +104 -0
- package/dist/verify-ac/index.d.ts +10 -0
- package/dist/verify-ac/index.js +10 -0
- package/dist/vitest-runner/coverage-debt-teardown.js +16 -4
- package/package.json +15 -3
- package/dist/policy/coverage-check-resume-presets.d.ts +0 -46
- package/dist/policy/coverage-check-resume-presets.js +0 -228
- package/dist/session/coverage-check-resume-nudge.d.ts +0 -34
- package/dist/session/coverage-check-resume-nudge.js +0 -66
package/dist/policy/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FIELD_HOST_SKILL_DISCOVERY, FIELD_HOST_SKILL_DISCOVERY_CLI_ALIAS, inspectHostSkillDiscovery, } from "../init-deposit/skill-discovery-hosts.js";
|
|
2
2
|
import { FIELD_OPENCLAW_PRODUCT_COMMANDS, FIELD_OPENCLAW_PRODUCT_COMMANDS_CLI_ALIAS, inspectOpenClawProductCommands, } from "../slash/openclaw-deposit.js";
|
|
3
|
+
import { FIELD_AC_PASS_BANKING, FIELD_AC_PASS_BANKING_CLI_ALIAS, inspectAcPassBanking, } from "./ac-pass-banking.js";
|
|
3
4
|
import { FIELD_CEREMONY_DIAL, FIELD_CEREMONY_DIAL_CLI_ALIAS, inspectCeremonyDial, } from "./ceremony-dial.js";
|
|
4
5
|
import { FIELD_CHECK_RESUME, FIELD_CHECK_RESUME_CLI_ALIAS, inspectCheckResume, } from "./check-resume.js";
|
|
5
6
|
import { FIELD_COVERAGE_DEBT, FIELD_COVERAGE_DEBT_CLI_ALIAS, inspectCoverageDebt, } from "./coverage-debt.js";
|
|
@@ -16,12 +17,13 @@ import { FIELD_RUNTIME_AUTHORITY, FIELD_RUNTIME_AUTHORITY_CLI_ALIAS, inspectRunt
|
|
|
16
17
|
import { FIELD_STALENESS_TICKLER, FIELD_STALENESS_TICKLER_CLI_ALIAS, inspectStalenessTickler, } from "./staleness-tickler.js";
|
|
17
18
|
import { FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, inspectValueFeedback, } from "./value-feedback.js";
|
|
18
19
|
import { DEFAULT_WIP_CAP } from "./wip.js";
|
|
20
|
+
export * from "./ac-pass-banking.js";
|
|
19
21
|
export * from "./agents-md-advisory.js";
|
|
20
22
|
export * from "./autonomy.js";
|
|
21
23
|
export * from "./capacity.js";
|
|
22
24
|
export * from "./ceremony-dial.js";
|
|
25
|
+
export * from "./ceremony-dial-escalation.js";
|
|
23
26
|
export * from "./check-resume.js";
|
|
24
|
-
export * from "./coverage-check-resume-presets.js";
|
|
25
27
|
export * from "./coverage-debt.js";
|
|
26
28
|
export * from "./decisions.js";
|
|
27
29
|
export * from "./deft-directive-disable.js";
|
|
@@ -420,6 +422,15 @@ function inspectCeremonyDialField(data, projectRoot) {
|
|
|
420
422
|
source: field.source,
|
|
421
423
|
};
|
|
422
424
|
}
|
|
425
|
+
function inspectAcPassBankingField(data, projectRoot) {
|
|
426
|
+
const field = inspectAcPassBanking(data, projectRoot);
|
|
427
|
+
return {
|
|
428
|
+
name: field.name,
|
|
429
|
+
current: field.current,
|
|
430
|
+
default: field.default,
|
|
431
|
+
source: field.source,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
423
434
|
const REGISTERED_POLICIES = [
|
|
424
435
|
inspectAllowDirectCommits,
|
|
425
436
|
inspectWipCap,
|
|
@@ -448,6 +459,7 @@ const REGISTERED_POLICIES = [
|
|
|
448
459
|
inspectRequireHumanMergeField,
|
|
449
460
|
inspectHotfixCriteriaField,
|
|
450
461
|
inspectCeremonyDialField,
|
|
462
|
+
inspectAcPassBankingField,
|
|
451
463
|
];
|
|
452
464
|
/** Walk registered inspectors and return one row per field (#1148). */
|
|
453
465
|
export function inspectAllPolicies(projectRoot) {
|
|
@@ -486,7 +498,9 @@ export function inspectOnePolicy(name, projectRoot) {
|
|
|
486
498
|
? FIELD_MIN_GREPTILE_CONFIDENCE
|
|
487
499
|
: name === FIELD_CEREMONY_DIAL_CLI_ALIAS
|
|
488
500
|
? FIELD_CEREMONY_DIAL
|
|
489
|
-
: name
|
|
501
|
+
: name === FIELD_AC_PASS_BANKING_CLI_ALIAS
|
|
502
|
+
? FIELD_AC_PASS_BANKING
|
|
503
|
+
: name;
|
|
490
504
|
for (const field of inspectAllPolicies(projectRoot)) {
|
|
491
505
|
if (field.name === normalized)
|
|
492
506
|
return field;
|
|
@@ -44,6 +44,9 @@ export declare function normaliseRepoUrl(url: string): string | null;
|
|
|
44
44
|
* Evaluate cache freshness for the given project root.
|
|
45
45
|
*
|
|
46
46
|
* Faithful port of scripts/preflight_cache.py::evaluate().
|
|
47
|
+
* #3286 note: deposit-sha orientation no-ops live in session orientation
|
|
48
|
+
* composition (age-gated), not here — triage cache freshness is age/drift based
|
|
49
|
+
* and must not short-circuit solely on payload/templates/engine fingerprints.
|
|
47
50
|
*/
|
|
48
51
|
export declare function evaluate(projectRoot: string, options?: EvaluateOptions): GateResult;
|
|
49
52
|
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -317,6 +317,9 @@ const REMEDIATION_NO_CANDIDATES = [
|
|
|
317
317
|
* Evaluate cache freshness for the given project root.
|
|
318
318
|
*
|
|
319
319
|
* Faithful port of scripts/preflight_cache.py::evaluate().
|
|
320
|
+
* #3286 note: deposit-sha orientation no-ops live in session orientation
|
|
321
|
+
* composition (age-gated), not here — triage cache freshness is age/drift based
|
|
322
|
+
* and must not short-circuit solely on payload/templates/engine fingerprints.
|
|
320
323
|
*/
|
|
321
324
|
export function evaluate(projectRoot, options = {}) {
|
|
322
325
|
return evaluateWithContext(projectRoot, options, { afterEmptyPopulate: false });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plan.acceptance schema helpers (#3284).
|
|
3
|
+
*
|
|
4
|
+
* Captures stated acceptance.commands at intake; empty requires none_stated:true.
|
|
5
|
+
* Interoperates with #3267 plan.metadata.literal_acceptance_commands.
|
|
6
|
+
*/
|
|
7
|
+
import { type AcceptanceCommand, type PlanAcceptance } from "./types.js";
|
|
8
|
+
/** Validation errors for a plan.acceptance object (empty list = valid). */
|
|
9
|
+
export declare function validatePlanAcceptance(value: unknown): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Read plan.acceptance when present; otherwise synthesize from #3267
|
|
12
|
+
* literal_acceptance_commands / empty+none_stated.
|
|
13
|
+
*/
|
|
14
|
+
export declare function readPlanAcceptance(plan: Record<string, unknown> | null | undefined): PlanAcceptance;
|
|
15
|
+
/** Attach a validated PlanAcceptance onto plan.acceptance + mirror to #3267 metadata. */
|
|
16
|
+
export declare function attachPlanAcceptance(plan: Record<string, unknown>, acceptance: PlanAcceptance): Record<string, unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* Build plan.acceptance from intake capture (#3284).
|
|
19
|
+
* Stated commands → none_stated:false, source_rung:stated.
|
|
20
|
+
* No stated commands → none_stated:true, source_rung:project_floor (until agent derives).
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildAcceptanceFromIntakeCapture(capturedCommands: readonly AcceptanceCommand[]): PlanAcceptance;
|
|
23
|
+
/** Stamp plan.acceptance from existing literal capture after issue ingest. */
|
|
24
|
+
export declare function stampAcceptanceFromLiteralCapture(plan: Record<string, unknown>): Record<string, unknown>;
|
|
25
|
+
//# sourceMappingURL=acceptance.d.ts.map
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plan.acceptance schema helpers (#3284).
|
|
3
|
+
*
|
|
4
|
+
* Captures stated acceptance.commands at intake; empty requires none_stated:true.
|
|
5
|
+
* Interoperates with #3267 plan.metadata.literal_acceptance_commands.
|
|
6
|
+
*/
|
|
7
|
+
import { attachLiteralAcceptanceCommands, readStoredLiteralAcceptanceCommands, } from "../literal-acceptance/index.js";
|
|
8
|
+
import { readAcceptanceClauses, serializeAcceptanceClauses } from "../verify-ac/clauses.js";
|
|
9
|
+
import { PLAN_ACCEPTANCE_KEY, } from "./types.js";
|
|
10
|
+
function asRecord(value) {
|
|
11
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function isNonEmptyString(value) {
|
|
17
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
18
|
+
}
|
|
19
|
+
function coerceCommands(raw) {
|
|
20
|
+
if (!Array.isArray(raw))
|
|
21
|
+
return [];
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const entry of raw) {
|
|
24
|
+
if (typeof entry === "string") {
|
|
25
|
+
const command = entry.trim();
|
|
26
|
+
if (command.length > 0)
|
|
27
|
+
out.push({ command });
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const rec = asRecord(entry);
|
|
31
|
+
if (rec === null)
|
|
32
|
+
continue;
|
|
33
|
+
const command = rec.command ?? rec.cmd ?? rec.shell;
|
|
34
|
+
if (!isNonEmptyString(command))
|
|
35
|
+
continue;
|
|
36
|
+
out.push({
|
|
37
|
+
command: command.trim(),
|
|
38
|
+
cwd: isNonEmptyString(rec.cwd) ? rec.cwd.trim() : null,
|
|
39
|
+
expectedStdout: isNonEmptyString(rec.expectedStdout)
|
|
40
|
+
? rec.expectedStdout
|
|
41
|
+
: isNonEmptyString(rec.expected_stdout)
|
|
42
|
+
? rec.expected_stdout
|
|
43
|
+
: null,
|
|
44
|
+
expectedExitCode: typeof rec.expectedExitCode === "number"
|
|
45
|
+
? rec.expectedExitCode
|
|
46
|
+
: typeof rec.expected_exit_code === "number"
|
|
47
|
+
? rec.expected_exit_code
|
|
48
|
+
: 0,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function isAcSourceRung(value) {
|
|
54
|
+
return value === "stated" || value === "derived" || value === "project_floor";
|
|
55
|
+
}
|
|
56
|
+
/** Validation errors for a plan.acceptance object (empty list = valid). */
|
|
57
|
+
export function validatePlanAcceptance(value) {
|
|
58
|
+
if (value === null || value === undefined) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const rec = asRecord(value);
|
|
62
|
+
if (rec === null) {
|
|
63
|
+
return ["plan.acceptance must be an object"];
|
|
64
|
+
}
|
|
65
|
+
const errors = [];
|
|
66
|
+
if ("commands" in rec && rec.commands !== undefined && !Array.isArray(rec.commands)) {
|
|
67
|
+
errors.push("plan.acceptance.commands must be an array");
|
|
68
|
+
}
|
|
69
|
+
if ("none_stated" in rec &&
|
|
70
|
+
rec.none_stated !== undefined &&
|
|
71
|
+
typeof rec.none_stated !== "boolean") {
|
|
72
|
+
errors.push("plan.acceptance.none_stated must be a boolean");
|
|
73
|
+
}
|
|
74
|
+
if ("source_rung" in rec && rec.source_rung !== undefined && !isAcSourceRung(rec.source_rung)) {
|
|
75
|
+
errors.push('plan.acceptance.source_rung must be "stated" | "derived" | "project_floor"');
|
|
76
|
+
}
|
|
77
|
+
if ("clauses" in rec && rec.clauses !== undefined && !Array.isArray(rec.clauses)) {
|
|
78
|
+
errors.push("plan.acceptance.clauses must be an array");
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(rec.clauses)) {
|
|
81
|
+
rec.clauses.forEach((entry, index) => {
|
|
82
|
+
const row = asRecord(entry);
|
|
83
|
+
if (row === null) {
|
|
84
|
+
errors.push(`plan.acceptance.clauses[${index}] must be an object`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const text = isNonEmptyString(row.text) ? row.text.trim() : "";
|
|
88
|
+
if (text.length === 0) {
|
|
89
|
+
errors.push(`plan.acceptance.clauses[${index}].text must be a non-empty string`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const commands = coerceCommands(rec.commands);
|
|
94
|
+
const noneStated = rec.none_stated === true;
|
|
95
|
+
if (commands.length === 0 && !noneStated) {
|
|
96
|
+
errors.push("plan.acceptance.commands is empty but none_stated is not true — " +
|
|
97
|
+
"empty acceptance is only allowed with an explicit none_stated: true marker (#3284)");
|
|
98
|
+
}
|
|
99
|
+
if (commands.length > 0 && noneStated && rec.source_rung === "stated") {
|
|
100
|
+
errors.push("plan.acceptance: none_stated:true with source_rung:stated is contradictory " +
|
|
101
|
+
"(use source_rung:derived when commands are agent-authored under none_stated)");
|
|
102
|
+
}
|
|
103
|
+
return errors;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Read plan.acceptance when present; otherwise synthesize from #3267
|
|
107
|
+
* literal_acceptance_commands / empty+none_stated.
|
|
108
|
+
*/
|
|
109
|
+
export function readPlanAcceptance(plan) {
|
|
110
|
+
if (plan === null || plan === undefined) {
|
|
111
|
+
return { commands: [], none_stated: true, source_rung: "project_floor" };
|
|
112
|
+
}
|
|
113
|
+
const raw = plan[PLAN_ACCEPTANCE_KEY];
|
|
114
|
+
if (raw !== null && raw !== undefined) {
|
|
115
|
+
const rec = asRecord(raw);
|
|
116
|
+
if (rec !== null) {
|
|
117
|
+
const commands = coerceCommands(rec.commands);
|
|
118
|
+
const noneStated = rec.none_stated === true || (commands.length === 0 && rec.none_stated !== false);
|
|
119
|
+
let sourceRung = isAcSourceRung(rec.source_rung)
|
|
120
|
+
? rec.source_rung
|
|
121
|
+
: commands.length > 0
|
|
122
|
+
? "stated"
|
|
123
|
+
: "project_floor";
|
|
124
|
+
if (noneStated && commands.length > 0 && sourceRung === "stated") {
|
|
125
|
+
sourceRung = "derived";
|
|
126
|
+
}
|
|
127
|
+
if (noneStated && commands.length === 0) {
|
|
128
|
+
sourceRung = isAcSourceRung(rec.source_rung) ? rec.source_rung : "project_floor";
|
|
129
|
+
}
|
|
130
|
+
const clauses = readAcceptanceClauses(rec);
|
|
131
|
+
return {
|
|
132
|
+
commands,
|
|
133
|
+
none_stated: noneStated,
|
|
134
|
+
source_rung: sourceRung,
|
|
135
|
+
derived_reason: isNonEmptyString(rec.derived_reason)
|
|
136
|
+
? rec.derived_reason
|
|
137
|
+
: isNonEmptyString(rec.derivedReason)
|
|
138
|
+
? rec.derivedReason
|
|
139
|
+
: null,
|
|
140
|
+
...(clauses.length > 0 ? { clauses } : {}),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Fallback: #3267 metadata ledger.
|
|
145
|
+
const literal = readStoredLiteralAcceptanceCommands(plan);
|
|
146
|
+
if (literal.length > 0) {
|
|
147
|
+
return {
|
|
148
|
+
commands: literal.map(literalToAcceptance),
|
|
149
|
+
none_stated: false,
|
|
150
|
+
source_rung: "stated",
|
|
151
|
+
derived_reason: null,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
commands: [],
|
|
156
|
+
none_stated: true,
|
|
157
|
+
source_rung: "project_floor",
|
|
158
|
+
derived_reason: "no plan.acceptance and no literal_acceptance_commands (#3284 floor)",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function literalToAcceptance(cmd) {
|
|
162
|
+
return {
|
|
163
|
+
command: cmd.command,
|
|
164
|
+
cwd: cmd.cwd ?? null,
|
|
165
|
+
expectedStdout: cmd.expectedStdout ?? null,
|
|
166
|
+
expectedExitCode: cmd.expectedExitCode ?? 0,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function acceptanceToLiteral(cmd, source) {
|
|
170
|
+
return {
|
|
171
|
+
command: cmd.command,
|
|
172
|
+
cwd: cmd.cwd ?? null,
|
|
173
|
+
expectedStdout: cmd.expectedStdout ?? null,
|
|
174
|
+
expectedExitCode: cmd.expectedExitCode ?? 0,
|
|
175
|
+
source,
|
|
176
|
+
sourceSpan: "plan.acceptance.commands",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/** Attach a validated PlanAcceptance onto plan.acceptance + mirror to #3267 metadata. */
|
|
180
|
+
export function attachPlanAcceptance(plan, acceptance) {
|
|
181
|
+
const errors = validatePlanAcceptance(acceptance);
|
|
182
|
+
if (errors.length > 0) {
|
|
183
|
+
throw new Error(`attachPlanAcceptance: ${errors.join("; ")}`);
|
|
184
|
+
}
|
|
185
|
+
const serializable = {
|
|
186
|
+
commands: acceptance.commands.map((c) => {
|
|
187
|
+
const row = { command: c.command };
|
|
188
|
+
if (c.cwd)
|
|
189
|
+
row.cwd = c.cwd;
|
|
190
|
+
if (c.expectedStdout)
|
|
191
|
+
row.expectedStdout = c.expectedStdout;
|
|
192
|
+
if (typeof c.expectedExitCode === "number" && c.expectedExitCode !== 0) {
|
|
193
|
+
row.expectedExitCode = c.expectedExitCode;
|
|
194
|
+
}
|
|
195
|
+
return row;
|
|
196
|
+
}),
|
|
197
|
+
none_stated: acceptance.none_stated,
|
|
198
|
+
source_rung: acceptance.source_rung,
|
|
199
|
+
};
|
|
200
|
+
if (acceptance.derived_reason) {
|
|
201
|
+
serializable.derived_reason = acceptance.derived_reason;
|
|
202
|
+
}
|
|
203
|
+
if (acceptance.clauses !== undefined && acceptance.clauses.length > 0) {
|
|
204
|
+
serializable.clauses = serializeAcceptanceClauses(acceptance.clauses);
|
|
205
|
+
}
|
|
206
|
+
let next = {
|
|
207
|
+
...plan,
|
|
208
|
+
[PLAN_ACCEPTANCE_KEY]: serializable,
|
|
209
|
+
};
|
|
210
|
+
// Mirror executable commands into #3267 ledger for verify:literal-ac interoperability.
|
|
211
|
+
if (acceptance.commands.length > 0) {
|
|
212
|
+
const source = acceptance.source_rung === "stated" ? "task_statement" : "explicit";
|
|
213
|
+
// derived / floor commands are agent-authored → executable source=explicit
|
|
214
|
+
const literalSource = acceptance.source_rung === "stated" ? "task_statement" : "explicit";
|
|
215
|
+
void source;
|
|
216
|
+
next = attachLiteralAcceptanceCommands(next, acceptance.commands.map((c) => acceptanceToLiteral(c, literalSource)));
|
|
217
|
+
}
|
|
218
|
+
return next;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Build plan.acceptance from intake capture (#3284).
|
|
222
|
+
* Stated commands → none_stated:false, source_rung:stated.
|
|
223
|
+
* No stated commands → none_stated:true, source_rung:project_floor (until agent derives).
|
|
224
|
+
*/
|
|
225
|
+
export function buildAcceptanceFromIntakeCapture(capturedCommands) {
|
|
226
|
+
if (capturedCommands.length === 0) {
|
|
227
|
+
return {
|
|
228
|
+
commands: [],
|
|
229
|
+
none_stated: true,
|
|
230
|
+
source_rung: "project_floor",
|
|
231
|
+
derived_reason: "no shell acceptance commands stated in task text; floor until agent derives AC (#3284 ladder)",
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
commands: capturedCommands,
|
|
236
|
+
none_stated: false,
|
|
237
|
+
source_rung: "stated",
|
|
238
|
+
derived_reason: null,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/** Stamp plan.acceptance from existing literal capture after issue ingest. */
|
|
242
|
+
export function stampAcceptanceFromLiteralCapture(plan) {
|
|
243
|
+
const literal = readStoredLiteralAcceptanceCommands(plan);
|
|
244
|
+
const acceptance = buildAcceptanceFromIntakeCapture(literal.map(literalToAcceptance));
|
|
245
|
+
// Avoid re-mirroring task_statement into verify_commands (ingest strips those).
|
|
246
|
+
const serializable = {
|
|
247
|
+
commands: acceptance.commands.map((c) => {
|
|
248
|
+
const row = { command: c.command };
|
|
249
|
+
if (c.cwd)
|
|
250
|
+
row.cwd = c.cwd;
|
|
251
|
+
if (c.expectedStdout)
|
|
252
|
+
row.expectedStdout = c.expectedStdout;
|
|
253
|
+
if (typeof c.expectedExitCode === "number" && c.expectedExitCode !== 0) {
|
|
254
|
+
row.expectedExitCode = c.expectedExitCode;
|
|
255
|
+
}
|
|
256
|
+
return row;
|
|
257
|
+
}),
|
|
258
|
+
none_stated: acceptance.none_stated,
|
|
259
|
+
source_rung: acceptance.source_rung,
|
|
260
|
+
};
|
|
261
|
+
if (acceptance.derived_reason) {
|
|
262
|
+
serializable.derived_reason = acceptance.derived_reason;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
...plan,
|
|
266
|
+
[PLAN_ACCEPTANCE_KEY]: serializable,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=acceptance.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve product-first check composition mode (#3284).
|
|
3
|
+
*
|
|
4
|
+
* Priority (highest wins):
|
|
5
|
+
* 1. DEFT_CHECK_AC_ONLY / DEFT_CHECK_MODE=rapid → rapid (AC-only)
|
|
6
|
+
* 2. DEFT_CHECK_MODE=pressure|degraded or DEFT_HYGIENE_ADVISORY → pressure
|
|
7
|
+
* 3. ceremony dial depth rapid|minimal → rapid
|
|
8
|
+
* 4. hard effort budget (#3266) → pressure
|
|
9
|
+
* 5. default full
|
|
10
|
+
*/
|
|
11
|
+
import { type CeremonyDepth } from "../policy/ceremony-dial.js";
|
|
12
|
+
import { type ProductFirstCheckMode } from "./types.js";
|
|
13
|
+
export interface ResolveProductFirstCheckModeInput {
|
|
14
|
+
readonly environ?: Readonly<Record<string, string | undefined>>;
|
|
15
|
+
readonly projectRoot?: string;
|
|
16
|
+
/** Inject ceremony depth (tests); when unset, reads ritual-state audit. */
|
|
17
|
+
readonly ceremonyDepth?: CeremonyDepth | null;
|
|
18
|
+
/** Inject hard-budget detected flag (tests). */
|
|
19
|
+
readonly hardBudgetDetected?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ProductFirstCheckModeResolution {
|
|
22
|
+
readonly mode: ProductFirstCheckMode;
|
|
23
|
+
readonly sources: readonly string[];
|
|
24
|
+
readonly hygieneAdvisory: boolean;
|
|
25
|
+
readonly acOnly: boolean;
|
|
26
|
+
/** AC remains mandatory whenever mode is not a pure no-op. */
|
|
27
|
+
readonly acMandatory: true;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the active product-first check mode from env + ceremony + budget.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveProductFirstCheckMode(input?: ResolveProductFirstCheckModeInput): ProductFirstCheckModeResolution;
|
|
33
|
+
/** True when this gate id is the product AC gate. */
|
|
34
|
+
export declare function isProductAcGate(gateId: string): boolean;
|
|
35
|
+
/** True when this gate is classified as hygiene (may be advisory under pressure). */
|
|
36
|
+
export declare function isHygieneGate(gateId: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Filter / annotate gate list for the resolved mode.
|
|
39
|
+
* - rapid: only product AC gates
|
|
40
|
+
* - pressure/full: full list (pressure marks hygiene advisory at run time)
|
|
41
|
+
*/
|
|
42
|
+
export declare function applyProductFirstGateMode<T extends string | {
|
|
43
|
+
readonly task: string;
|
|
44
|
+
}>(gates: readonly T[], mode: ProductFirstCheckMode, gateIdOf?: (g: T) => string): readonly T[];
|
|
45
|
+
//# sourceMappingURL=check-mode.d.ts.map
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve product-first check composition mode (#3284).
|
|
3
|
+
*
|
|
4
|
+
* Priority (highest wins):
|
|
5
|
+
* 1. DEFT_CHECK_AC_ONLY / DEFT_CHECK_MODE=rapid → rapid (AC-only)
|
|
6
|
+
* 2. DEFT_CHECK_MODE=pressure|degraded or DEFT_HYGIENE_ADVISORY → pressure
|
|
7
|
+
* 3. ceremony dial depth rapid|minimal → rapid
|
|
8
|
+
* 4. hard effort budget (#3266) → pressure
|
|
9
|
+
* 5. default full
|
|
10
|
+
*/
|
|
11
|
+
import { CEREMONY_DEPTHS, readCeremonyDialAudit, } from "../policy/ceremony-dial.js";
|
|
12
|
+
import { detectHardEffortBudget } from "../session/effort-budget.js";
|
|
13
|
+
import { ENV_CHECK_AC_ONLY, ENV_CHECK_MODE, ENV_HYGIENE_ADVISORY, HYGIENE_GATE_ID_PREFIXES, PRODUCT_AC_GATE_ID, } from "./types.js";
|
|
14
|
+
function asCeremonyDepth(value) {
|
|
15
|
+
return typeof value === "string" && CEREMONY_DEPTHS.includes(value)
|
|
16
|
+
? value
|
|
17
|
+
: null;
|
|
18
|
+
}
|
|
19
|
+
const TRUTHY = new Set(["1", "true", "yes", "on"]);
|
|
20
|
+
function isTruthy(raw) {
|
|
21
|
+
if (raw === undefined)
|
|
22
|
+
return false;
|
|
23
|
+
return TRUTHY.has(raw.trim().toLowerCase());
|
|
24
|
+
}
|
|
25
|
+
function normalizeModeToken(raw) {
|
|
26
|
+
const t = raw.trim().toLowerCase();
|
|
27
|
+
if (t === "full" || t === "standard")
|
|
28
|
+
return "full";
|
|
29
|
+
if (t === "pressure" || t === "degraded" || t === "advisory")
|
|
30
|
+
return "pressure";
|
|
31
|
+
if (t === "rapid" || t === "minimal" || t === "ac-only" || t === "ac_only")
|
|
32
|
+
return "rapid";
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the active product-first check mode from env + ceremony + budget.
|
|
37
|
+
*/
|
|
38
|
+
export function resolveProductFirstCheckMode(input = {}) {
|
|
39
|
+
const env = input.environ ?? process.env;
|
|
40
|
+
const sources = [];
|
|
41
|
+
if (isTruthy(env[ENV_CHECK_AC_ONLY])) {
|
|
42
|
+
sources.push(`${ENV_CHECK_AC_ONLY}=truthy`);
|
|
43
|
+
return {
|
|
44
|
+
mode: "rapid",
|
|
45
|
+
sources,
|
|
46
|
+
hygieneAdvisory: true,
|
|
47
|
+
acOnly: true,
|
|
48
|
+
acMandatory: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const modeEnv = env[ENV_CHECK_MODE];
|
|
52
|
+
if (typeof modeEnv === "string" && modeEnv.trim().length > 0) {
|
|
53
|
+
const parsed = normalizeModeToken(modeEnv);
|
|
54
|
+
if (parsed !== null) {
|
|
55
|
+
sources.push(`${ENV_CHECK_MODE}=${modeEnv.trim()}`);
|
|
56
|
+
return {
|
|
57
|
+
mode: parsed,
|
|
58
|
+
sources,
|
|
59
|
+
hygieneAdvisory: parsed !== "full",
|
|
60
|
+
acOnly: parsed === "rapid",
|
|
61
|
+
acMandatory: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (isTruthy(env[ENV_HYGIENE_ADVISORY])) {
|
|
66
|
+
sources.push(`${ENV_HYGIENE_ADVISORY}=truthy`);
|
|
67
|
+
return {
|
|
68
|
+
mode: "pressure",
|
|
69
|
+
sources,
|
|
70
|
+
hygieneAdvisory: true,
|
|
71
|
+
acOnly: false,
|
|
72
|
+
acMandatory: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
let depth = input.ceremonyDepth;
|
|
76
|
+
if (depth === undefined && input.projectRoot !== undefined) {
|
|
77
|
+
try {
|
|
78
|
+
const audit = readCeremonyDialAudit(input.projectRoot);
|
|
79
|
+
depth = asCeremonyDepth(audit.depth);
|
|
80
|
+
if (depth !== null)
|
|
81
|
+
sources.push(`ceremony_dial.depth=${depth}`);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
depth = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (depth === "rapid" || depth === "minimal") {
|
|
88
|
+
if (!sources.some((s) => s.startsWith("ceremony_dial"))) {
|
|
89
|
+
sources.push(`ceremonyDepth=${depth}`);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
mode: "rapid",
|
|
93
|
+
sources,
|
|
94
|
+
hygieneAdvisory: true,
|
|
95
|
+
acOnly: true,
|
|
96
|
+
acMandatory: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
let hardBudget = input.hardBudgetDetected;
|
|
100
|
+
if (hardBudget === undefined) {
|
|
101
|
+
hardBudget = detectHardEffortBudget({ environ: env }).detected;
|
|
102
|
+
if (hardBudget)
|
|
103
|
+
sources.push("hard_effort_budget");
|
|
104
|
+
}
|
|
105
|
+
else if (hardBudget) {
|
|
106
|
+
sources.push("hard_effort_budget(injected)");
|
|
107
|
+
}
|
|
108
|
+
if (hardBudget === true) {
|
|
109
|
+
return {
|
|
110
|
+
mode: "pressure",
|
|
111
|
+
sources,
|
|
112
|
+
hygieneAdvisory: true,
|
|
113
|
+
acOnly: false,
|
|
114
|
+
acMandatory: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
sources.push("default:full");
|
|
118
|
+
return {
|
|
119
|
+
mode: "full",
|
|
120
|
+
sources,
|
|
121
|
+
hygieneAdvisory: false,
|
|
122
|
+
acOnly: false,
|
|
123
|
+
acMandatory: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** True when this gate id is the product AC gate. */
|
|
127
|
+
export function isProductAcGate(gateId) {
|
|
128
|
+
return gateId === PRODUCT_AC_GATE_ID || gateId === "verify:literal-ac";
|
|
129
|
+
}
|
|
130
|
+
/** True when this gate is classified as hygiene (may be advisory under pressure). */
|
|
131
|
+
export function isHygieneGate(gateId) {
|
|
132
|
+
if (isProductAcGate(gateId))
|
|
133
|
+
return false;
|
|
134
|
+
return HYGIENE_GATE_ID_PREFIXES.includes(gateId);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Filter / annotate gate list for the resolved mode.
|
|
138
|
+
* - rapid: only product AC gates
|
|
139
|
+
* - pressure/full: full list (pressure marks hygiene advisory at run time)
|
|
140
|
+
*/
|
|
141
|
+
export function applyProductFirstGateMode(gates, mode, gateIdOf = (g) => (typeof g === "string" ? g : g.task)) {
|
|
142
|
+
if (mode === "rapid") {
|
|
143
|
+
const ac = gates.filter((g) => isProductAcGate(gateIdOf(g)));
|
|
144
|
+
return ac.length > 0 ? ac : gates.filter((g) => gateIdOf(g) === PRODUCT_AC_GATE_ID);
|
|
145
|
+
}
|
|
146
|
+
return gates;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=check-mode.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empty verify:ac resolution is not a green run when there is no suite floor (#3334).
|
|
3
|
+
*
|
|
4
|
+
* Framework source keeps today's floor-pass (suite gates own the floor).
|
|
5
|
+
* Consumer / no-suite projects fail closed with a distinct soft_empty outcome.
|
|
6
|
+
*/
|
|
7
|
+
import type { PlanAcceptance } from "./types.js";
|
|
8
|
+
export declare const EMPTY_AC_OUTCOME: "soft_empty";
|
|
9
|
+
export declare const EMPTY_AC_CAUSE = "no acceptance stamped \u2014 floor is empty in this project";
|
|
10
|
+
export declare const EMPTY_AC_REMEDY = "stamp plan.acceptance (author commands or run intake capture / task issue:ingest)";
|
|
11
|
+
export type VerifyAcResolution = "verified-pass" | "empty-pass" | "soft_empty" | "fail" | "config" | "skipped";
|
|
12
|
+
/** True when this project check composition includes a suite gate (#3188). */
|
|
13
|
+
export declare function projectHasSuiteFloor(projectRoot: string): boolean;
|
|
14
|
+
export declare function isSoftEmptyAcText(text: string): boolean;
|
|
15
|
+
export interface EmptyAcResolutionInput {
|
|
16
|
+
readonly ok: boolean;
|
|
17
|
+
readonly code: number;
|
|
18
|
+
readonly runsLength: number;
|
|
19
|
+
readonly commandCount: number;
|
|
20
|
+
readonly rejectedCount: number;
|
|
21
|
+
readonly resolution?: VerifyAcResolution;
|
|
22
|
+
}
|
|
23
|
+
/** Zero executable commands, no rejected/unpromoted ledger, not already classified. */
|
|
24
|
+
export declare function isEmptyAcResolution(input: EmptyAcResolutionInput): boolean;
|
|
25
|
+
export declare function formatSoftEmptyMessage(acceptance: PlanAcceptance, quiet?: boolean): string;
|
|
26
|
+
//# sourceMappingURL=empty-resolution.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empty verify:ac resolution is not a green run when there is no suite floor (#3334).
|
|
3
|
+
*
|
|
4
|
+
* Framework source keeps today's floor-pass (suite gates own the floor).
|
|
5
|
+
* Consumer / no-suite projects fail closed with a distinct soft_empty outcome.
|
|
6
|
+
*/
|
|
7
|
+
import { isFrameworkRepoRoot } from "../check/context.js";
|
|
8
|
+
export const EMPTY_AC_OUTCOME = "soft_empty";
|
|
9
|
+
export const EMPTY_AC_CAUSE = "no acceptance stamped — floor is empty in this project";
|
|
10
|
+
export const EMPTY_AC_REMEDY = "stamp plan.acceptance (author commands or run intake capture / task issue:ingest)";
|
|
11
|
+
/** True when this project check composition includes a suite gate (#3188). */
|
|
12
|
+
export function projectHasSuiteFloor(projectRoot) {
|
|
13
|
+
return isFrameworkRepoRoot(projectRoot);
|
|
14
|
+
}
|
|
15
|
+
export function isSoftEmptyAcText(text) {
|
|
16
|
+
return /soft_empty\s*\(#3334\)/i.test(text);
|
|
17
|
+
}
|
|
18
|
+
/** Zero executable commands, no rejected/unpromoted ledger, not already classified. */
|
|
19
|
+
export function isEmptyAcResolution(input) {
|
|
20
|
+
if (input.resolution === "config" || input.resolution === "skipped") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (input.code === 2) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (input.rejectedCount > 0 || input.commandCount > 0 || input.runsLength > 0) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
export function formatSoftEmptyMessage(acceptance, quiet) {
|
|
32
|
+
if (quiet) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
return (`verify:ac ${EMPTY_AC_OUTCOME} (#3334) [rung=${acceptance.source_rung}]: ` +
|
|
36
|
+
`${EMPTY_AC_CAUSE}. ${EMPTY_AC_REMEDY}.`);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=empty-resolution.js.map
|