@deftai/directive 0.104.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authz.d.ts +4 -29
- package/dist/authz.js +16 -181
- package/dist/cli-router/route-argv.js +1 -0
- package/dist/dispatch.d.ts +7 -1
- package/dist/dispatch.js +56 -20
- package/dist/human-presence-mint.d.ts +70 -0
- package/dist/human-presence-mint.js +203 -0
- package/dist/occupancy-steal.d.ts +9 -0
- package/dist/occupancy-steal.js +54 -0
- package/dist/plan-sequence.d.ts +10 -0
- package/dist/plan-sequence.js +3 -1
- package/dist/policy.d.ts +3 -2
- package/dist/policy.js +52 -7
- package/dist/preflight-cache.d.ts +2 -0
- package/dist/preflight-cache.js +7 -0
- package/dist/scm-sync-default.d.ts +34 -0
- package/dist/scm-sync-default.js +210 -0
- package/dist/scope-record-approved-scope.d.ts +6 -1
- package/dist/scope-record-approved-scope.js +72 -24
- package/dist/session-start.d.ts +4 -0
- package/dist/session-start.js +23 -0
- package/dist/triage-actions.js +2 -0
- package/dist/triage-queue.js +4 -1
- package/dist/verify-ac.d.ts +2 -0
- package/dist/verify-ac.js +30 -6
- package/dist/verify-completed-tracked.d.ts +2 -1
- package/dist/verify-completed-tracked.js +31 -1
- package/dist/verify-forward-coverage.d.ts +4 -0
- package/dist/verify-forward-coverage.js +77 -11
- package/dist/verify-lifecycle-visible.d.ts +13 -0
- package/dist/verify-lifecycle-visible.js +68 -0
- package/dist/verify-literal-ac.js +7 -0
- package/dist/verify-orphan-active.d.ts +1 -0
- package/dist/verify-orphan-active.js +30 -0
- package/dist/verify-session-ritual.d.ts +10 -2
- package/dist/verify-session-ritual.js +16 -3
- package/package.json +3 -3
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { evaluateForwardCoverage } from "@deftai/directive-core";
|
|
5
|
+
const HELP_TEXT = "Usage: verify-forward-coverage [--project-root <path>] [--staged|--head] [--allow-list <path>]\n" +
|
|
6
|
+
" [--coverage-dir <path>] [--coverage-report <path>]\n" +
|
|
7
|
+
" [--enforce] [--quiet]\n" +
|
|
8
|
+
" Fail-closed new-source-file existence (#1310) plus warn-first diff coverage of\n" +
|
|
9
|
+
" added/modified branches (#3514). The 90% per-diff threshold is not the 75\n" +
|
|
10
|
+
" global floor. Missing coverage reports skip the diff half.\n" +
|
|
11
|
+
" --enforce: fail closed when uncovered changed branches are below 90%.\n";
|
|
12
|
+
function takeValue(argv, i, flag) {
|
|
13
|
+
const value = argv[i + 1];
|
|
14
|
+
if (value === undefined) {
|
|
15
|
+
return { error: `argument ${flag}: expected one argument` };
|
|
16
|
+
}
|
|
17
|
+
return { value, next: i + 1 };
|
|
18
|
+
}
|
|
5
19
|
/** Parse the verify-forward-coverage CLI args, mirroring the verify-encoding surface. */
|
|
6
20
|
export function parseArgs(argv) {
|
|
7
21
|
const parsed = {
|
|
@@ -9,6 +23,9 @@ export function parseArgs(argv) {
|
|
|
9
23
|
projectRoot: ".",
|
|
10
24
|
allowList: null,
|
|
11
25
|
quiet: false,
|
|
26
|
+
enforce: false,
|
|
27
|
+
coverageReport: null,
|
|
28
|
+
coverageDir: null,
|
|
12
29
|
};
|
|
13
30
|
for (let i = 0; i < argv.length; i += 1) {
|
|
14
31
|
const arg = argv[i];
|
|
@@ -21,48 +38,97 @@ export function parseArgs(argv) {
|
|
|
21
38
|
else if (arg === "--quiet") {
|
|
22
39
|
parsed.quiet = true;
|
|
23
40
|
}
|
|
41
|
+
else if (arg === "--enforce") {
|
|
42
|
+
parsed.enforce = true;
|
|
43
|
+
}
|
|
44
|
+
else if (arg === "--help" || arg === "-h") {
|
|
45
|
+
return { ...parsed, help: true };
|
|
46
|
+
}
|
|
24
47
|
else if (arg === "--project-root") {
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
return { ...parsed, error:
|
|
48
|
+
const taken = takeValue(argv, i, "--project-root");
|
|
49
|
+
if ("error" in taken) {
|
|
50
|
+
return { ...parsed, error: taken.error };
|
|
28
51
|
}
|
|
29
|
-
parsed.projectRoot = value;
|
|
30
|
-
i
|
|
52
|
+
parsed.projectRoot = taken.value;
|
|
53
|
+
i = taken.next;
|
|
31
54
|
}
|
|
32
55
|
else if (arg?.startsWith("--project-root=")) {
|
|
33
56
|
parsed.projectRoot = arg.slice("--project-root=".length);
|
|
34
57
|
}
|
|
35
58
|
else if (arg === "--allow-list") {
|
|
36
|
-
const
|
|
37
|
-
if (
|
|
38
|
-
return { ...parsed, error:
|
|
59
|
+
const taken = takeValue(argv, i, "--allow-list");
|
|
60
|
+
if ("error" in taken) {
|
|
61
|
+
return { ...parsed, error: taken.error };
|
|
39
62
|
}
|
|
40
|
-
parsed.allowList = value;
|
|
41
|
-
i
|
|
63
|
+
parsed.allowList = taken.value;
|
|
64
|
+
i = taken.next;
|
|
42
65
|
}
|
|
43
66
|
else if (arg?.startsWith("--allow-list=")) {
|
|
44
67
|
parsed.allowList = arg.slice("--allow-list=".length);
|
|
45
68
|
}
|
|
69
|
+
else if (arg === "--coverage-report") {
|
|
70
|
+
const taken = takeValue(argv, i, "--coverage-report");
|
|
71
|
+
if ("error" in taken) {
|
|
72
|
+
return { ...parsed, error: taken.error };
|
|
73
|
+
}
|
|
74
|
+
parsed.coverageReport = taken.value;
|
|
75
|
+
i = taken.next;
|
|
76
|
+
}
|
|
77
|
+
else if (arg?.startsWith("--coverage-report=")) {
|
|
78
|
+
parsed.coverageReport = arg.slice("--coverage-report=".length);
|
|
79
|
+
}
|
|
80
|
+
else if (arg === "--coverage-dir") {
|
|
81
|
+
const taken = takeValue(argv, i, "--coverage-dir");
|
|
82
|
+
if ("error" in taken) {
|
|
83
|
+
return { ...parsed, error: taken.error };
|
|
84
|
+
}
|
|
85
|
+
parsed.coverageDir = taken.value;
|
|
86
|
+
i = taken.next;
|
|
87
|
+
}
|
|
88
|
+
else if (arg?.startsWith("--coverage-dir=")) {
|
|
89
|
+
parsed.coverageDir = arg.slice("--coverage-dir=".length);
|
|
90
|
+
}
|
|
46
91
|
else {
|
|
47
92
|
return { ...parsed, error: `unrecognized argument: ${arg}` };
|
|
48
93
|
}
|
|
49
94
|
}
|
|
50
95
|
return parsed;
|
|
51
96
|
}
|
|
97
|
+
function resolveCoverageReport(args) {
|
|
98
|
+
if (args.coverageReport !== null) {
|
|
99
|
+
return resolve(args.coverageReport);
|
|
100
|
+
}
|
|
101
|
+
if (args.coverageDir !== null) {
|
|
102
|
+
return resolve(args.coverageDir, "coverage-final.json");
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
52
106
|
/** Run the gate and return the process exit code (argv parse error -> 2). */
|
|
53
107
|
export function run(argv) {
|
|
54
108
|
const args = parseArgs(argv);
|
|
109
|
+
if (args.help === true) {
|
|
110
|
+
process.stdout.write(HELP_TEXT);
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
55
113
|
if (args.error !== undefined) {
|
|
56
114
|
process.stderr.write(`verify_forward_coverage: ${args.error}\n`);
|
|
57
115
|
return 2;
|
|
58
116
|
}
|
|
59
117
|
const projectRoot = resolve(args.projectRoot);
|
|
60
118
|
const allowListPath = args.allowList !== null ? resolve(args.allowList) : null;
|
|
61
|
-
const result = evaluateForwardCoverage(projectRoot, {
|
|
119
|
+
const result = evaluateForwardCoverage(projectRoot, {
|
|
120
|
+
mode: args.mode,
|
|
121
|
+
allowListPath,
|
|
122
|
+
enforceDiffCoverage: args.enforce,
|
|
123
|
+
coverageReportPath: resolveCoverageReport(args),
|
|
124
|
+
});
|
|
62
125
|
if (result.exitCode === 0) {
|
|
63
126
|
if (!args.quiet) {
|
|
64
127
|
process.stdout.write(`${result.message}\n`);
|
|
65
128
|
}
|
|
129
|
+
else if (result.message.includes("ADVISORY")) {
|
|
130
|
+
process.stdout.write(`${result.message}\n`);
|
|
131
|
+
}
|
|
66
132
|
}
|
|
67
133
|
else {
|
|
68
134
|
process.stderr.write(`${result.message}\n`);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
interface ParsedArgs {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
enforce: boolean;
|
|
5
|
+
help?: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Parse verify-lifecycle-visible CLI args (#3505). */
|
|
9
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
10
|
+
/** Run the gate and return the process exit code. */
|
|
11
|
+
export declare function run(argv: string[]): number;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=verify-lifecycle-visible.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for task verify:lifecycle-visible (#3505).
|
|
4
|
+
* Warn-only by default; pass --enforce to fail closed.
|
|
5
|
+
*/
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { evaluateLifecycleVisible } from "@deftai/directive-core/lifecycle-visible";
|
|
9
|
+
/** Parse verify-lifecycle-visible CLI args (#3505). */
|
|
10
|
+
export function parseArgs(argv) {
|
|
11
|
+
const parsed = { projectRoot: ".", enforce: false };
|
|
12
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
13
|
+
const arg = argv[i];
|
|
14
|
+
if (arg === "--project-root") {
|
|
15
|
+
const value = argv[i + 1];
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
return { ...parsed, error: "argument --project-root: expected one argument" };
|
|
18
|
+
}
|
|
19
|
+
parsed.projectRoot = value;
|
|
20
|
+
i += 1;
|
|
21
|
+
}
|
|
22
|
+
else if (arg?.startsWith("--project-root=")) {
|
|
23
|
+
parsed.projectRoot = arg.slice("--project-root=".length);
|
|
24
|
+
}
|
|
25
|
+
else if (arg === "--enforce") {
|
|
26
|
+
parsed.enforce = true;
|
|
27
|
+
}
|
|
28
|
+
else if (arg === "--help" || arg === "-h") {
|
|
29
|
+
return { ...parsed, help: true };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return { ...parsed, error: `unrecognized argument: ${arg}` };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
const HELP_TEXT = "Usage: verify-lifecycle-visible [--project-root <path>] [--enforce]\n" +
|
|
38
|
+
" Detect ignore/exclude/skip-worktree flags that hide xbrief/vbrief lifecycle roots (#3505).\n" +
|
|
39
|
+
" Default: warn-only (exit 0 with advisory report).\n" +
|
|
40
|
+
" --enforce: fail closed (exit 1) when a lifecycle root is hidden.\n" +
|
|
41
|
+
" Not part of task check — per-clone property, wired from session:start.\n";
|
|
42
|
+
/** Run the gate and return the process exit code. */
|
|
43
|
+
export function run(argv) {
|
|
44
|
+
const args = parseArgs(argv);
|
|
45
|
+
if (args.help === true) {
|
|
46
|
+
process.stdout.write(HELP_TEXT);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
if (args.error !== undefined) {
|
|
50
|
+
process.stderr.write(`verify_lifecycle_visible: ${args.error}\n`);
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
const result = evaluateLifecycleVisible({
|
|
54
|
+
projectRoot: resolve(args.projectRoot),
|
|
55
|
+
enforce: args.enforce,
|
|
56
|
+
});
|
|
57
|
+
if (result.stream === "stdout") {
|
|
58
|
+
process.stdout.write(`${result.message}\n`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
process.stderr.write(`${result.message}\n`);
|
|
62
|
+
}
|
|
63
|
+
return result.code;
|
|
64
|
+
}
|
|
65
|
+
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
66
|
+
process.exit(run(process.argv.slice(2)));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=verify-lifecycle-visible.js.map
|
|
@@ -128,6 +128,13 @@ export function run(argv) {
|
|
|
128
128
|
reason: r.reason,
|
|
129
129
|
sourceSpan: r.sourceSpan ?? null,
|
|
130
130
|
})),
|
|
131
|
+
// Prose-derived captures demoted by structured acceptance commands (#3484).
|
|
132
|
+
advisory_rejected_count: resolved.advisoryRejected.length,
|
|
133
|
+
advisory_rejected: resolved.advisoryRejected.map((r) => ({
|
|
134
|
+
command: r.command,
|
|
135
|
+
reason: r.reason,
|
|
136
|
+
sourceSpan: r.sourceSpan ?? null,
|
|
137
|
+
})),
|
|
131
138
|
};
|
|
132
139
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
133
140
|
if (resolved.rejected.length > 0) {
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { evaluate } from "@deftai/directive-core/orphan-active";
|
|
5
|
+
function parseIssueNumber(raw) {
|
|
6
|
+
const trimmed = raw.startsWith("#") ? raw.slice(1) : raw;
|
|
7
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const value = Number(trimmed);
|
|
11
|
+
return Number.isInteger(value) && value > 0 ? value : null;
|
|
12
|
+
}
|
|
5
13
|
/** Parse verify-orphan-active CLI args. */
|
|
6
14
|
export function parseArgs(argv) {
|
|
7
15
|
const parsed = {
|
|
8
16
|
projectRoot: ".",
|
|
9
17
|
repo: null,
|
|
18
|
+
issue: null,
|
|
10
19
|
quiet: false,
|
|
11
20
|
skipGh: false,
|
|
12
21
|
};
|
|
@@ -40,6 +49,26 @@ export function parseArgs(argv) {
|
|
|
40
49
|
else if (arg?.startsWith("--repo=")) {
|
|
41
50
|
parsed.repo = arg.slice("--repo=".length);
|
|
42
51
|
}
|
|
52
|
+
else if (arg === "--issue") {
|
|
53
|
+
const value = argv[i + 1];
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
return { ...parsed, error: "argument --issue: expected one argument" };
|
|
56
|
+
}
|
|
57
|
+
const issue = parseIssueNumber(value);
|
|
58
|
+
if (issue === null) {
|
|
59
|
+
return { ...parsed, error: `argument --issue: expected a positive integer, got ${value}` };
|
|
60
|
+
}
|
|
61
|
+
parsed.issue = issue;
|
|
62
|
+
i += 1;
|
|
63
|
+
}
|
|
64
|
+
else if (arg?.startsWith("--issue=")) {
|
|
65
|
+
const value = arg.slice("--issue=".length);
|
|
66
|
+
const issue = parseIssueNumber(value);
|
|
67
|
+
if (issue === null) {
|
|
68
|
+
return { ...parsed, error: `argument --issue: expected a positive integer, got ${value}` };
|
|
69
|
+
}
|
|
70
|
+
parsed.issue = issue;
|
|
71
|
+
}
|
|
43
72
|
else {
|
|
44
73
|
return { ...parsed, error: `unrecognized argument: ${arg}` };
|
|
45
74
|
}
|
|
@@ -58,6 +87,7 @@ export function run(argv) {
|
|
|
58
87
|
quiet: args.quiet,
|
|
59
88
|
repo: args.repo,
|
|
60
89
|
skipGh: args.skipGh,
|
|
90
|
+
issue: args.issue,
|
|
61
91
|
});
|
|
62
92
|
if (result.message.length > 0) {
|
|
63
93
|
if (result.stream === "stdout") {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { type DirectivePosture } from "@deftai/directive-core/session";
|
|
2
|
+
import { type DirectivePosture, type VerifyResult } from "@deftai/directive-core/session";
|
|
3
|
+
export interface VerifySessionRitualRunDeps {
|
|
4
|
+
readonly verifySessionRitual?: (projectRoot: string, options: {
|
|
5
|
+
tier: "quick" | "gated";
|
|
6
|
+
posture?: DirectivePosture;
|
|
7
|
+
}) => VerifyResult;
|
|
8
|
+
}
|
|
3
9
|
interface ParsedArgs {
|
|
4
10
|
projectRoot: string;
|
|
5
11
|
tier: "quick" | "gated";
|
|
@@ -9,7 +15,9 @@ interface ParsedArgs {
|
|
|
9
15
|
}
|
|
10
16
|
/** Parse verify-session-ritual CLI args, mirroring scripts/verify_session_ritual.py. */
|
|
11
17
|
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
18
|
+
/** True when the ritual failure is the gated cache_fresh step (#3506 / #3507). */
|
|
19
|
+
export declare function isCacheFreshFailureMessage(message: string): boolean;
|
|
12
20
|
/** Run the gate and return the process exit code. */
|
|
13
|
-
export declare function run(argv: string[]): number;
|
|
21
|
+
export declare function run(argv: string[], deps?: VerifySessionRitualRunDeps): number;
|
|
14
22
|
export {};
|
|
15
23
|
//# sourceMappingURL=verify-session-ritual.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { emitBypassWarning, emitVerifyJson, verifySessionRitual, } from "@deftai/directive-core/session";
|
|
4
|
+
import { emitBypassWarning, emitVerifyJson, formatCacheFreshDeferSoftPath, formatRitualRecoveryInstruction, verifySessionRitual, } from "@deftai/directive-core/session";
|
|
5
5
|
function parsePosture(value) {
|
|
6
6
|
if (value === "read-only")
|
|
7
7
|
return "read-only";
|
|
@@ -86,15 +86,20 @@ export function parseArgs(argv) {
|
|
|
86
86
|
}
|
|
87
87
|
return parsed;
|
|
88
88
|
}
|
|
89
|
+
/** True when the ritual failure is the gated cache_fresh step (#3506 / #3507). */
|
|
90
|
+
export function isCacheFreshFailureMessage(message) {
|
|
91
|
+
return message.includes("cache_fresh") || message.includes("cache-fresh");
|
|
92
|
+
}
|
|
89
93
|
/** Run the gate and return the process exit code. */
|
|
90
|
-
export function run(argv) {
|
|
94
|
+
export function run(argv, deps = {}) {
|
|
91
95
|
const args = parseArgs(argv);
|
|
92
96
|
if (args.error !== undefined) {
|
|
93
97
|
process.stderr.write(`verify_session_ritual: ${args.error}\n`);
|
|
94
98
|
return 2;
|
|
95
99
|
}
|
|
96
100
|
const projectRoot = resolve(args.projectRoot);
|
|
97
|
-
const
|
|
101
|
+
const verify = deps.verifySessionRitual ?? verifySessionRitual;
|
|
102
|
+
const result = verify(projectRoot, {
|
|
98
103
|
tier: args.tier,
|
|
99
104
|
posture: args.posture ?? undefined,
|
|
100
105
|
});
|
|
@@ -108,6 +113,14 @@ export function run(argv) {
|
|
|
108
113
|
process.stdout.write(`${result.message}\n`);
|
|
109
114
|
}
|
|
110
115
|
}
|
|
116
|
+
else if (result.code === 1) {
|
|
117
|
+
const recovery = formatRitualRecoveryInstruction(result.recoveryTier ?? "cold");
|
|
118
|
+
const lines = [result.message, recovery];
|
|
119
|
+
if (isCacheFreshFailureMessage(result.message)) {
|
|
120
|
+
lines.push(formatCacheFreshDeferSoftPath());
|
|
121
|
+
}
|
|
122
|
+
process.stderr.write(`${lines.join("\n")}\n`);
|
|
123
|
+
}
|
|
111
124
|
else {
|
|
112
125
|
process.stderr.write(`${result.message}\n`);
|
|
113
126
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.106.0",
|
|
4
4
|
"description": "Directive CLI — npm install path for the Deft Directive framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://deftai.github.io/directive/",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"provenance": true
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@deftai/directive-core": "^0.
|
|
38
|
-
"@deftai/directive-content": "^0.
|
|
37
|
+
"@deftai/directive-core": "^0.106.0",
|
|
38
|
+
"@deftai/directive-content": "^0.106.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b"
|