@deftai/directive 0.105.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/cli-router/route-argv.js +1 -0
- package/dist/dispatch.d.ts +7 -1
- package/dist/dispatch.js +43 -20
- package/dist/human-presence-mint.d.ts +9 -0
- package/dist/human-presence-mint.js +15 -4
- 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/triage-actions.js +2 -0
- package/dist/triage-queue.js +4 -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/package.json +3 -3
|
@@ -83,6 +83,7 @@ export const SUBCOMMAND_ROUTES = {
|
|
|
83
83
|
"policy:allow-direct-commits": ["policy", "allow-direct-commits"],
|
|
84
84
|
"policy:allow-bot-merge": ["policy", "allow-bot-merge"],
|
|
85
85
|
"policy:enable-value-feedback": ["policy", "enable-value-feedback"],
|
|
86
|
+
"policy:disable-host-hooks": ["policy", "disable-host-hooks"],
|
|
86
87
|
"policy:set-ceremony-dial": ["policy", "set-ceremony-dial"],
|
|
87
88
|
"policy:clear-value-feedback": ["policy", "clear-value-feedback"],
|
|
88
89
|
"authz:show": ["authz", "show"],
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface DispatchIo {
|
|
|
10
10
|
writeErr: (text: string) => void;
|
|
11
11
|
}
|
|
12
12
|
/** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
|
|
13
|
-
export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "coverage-hotspots", "policy", "authz", "escalation-cli", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "pr-finish-loop", "directive-finish-loop", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "scope-record-approved-scope", "scm-sync-default", "lifecycle-event", "lifecycle-stats", "session-start", "session-ready", "occupancy-steal", "plan-sequence", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "xbrief-create", "xbrief-verify", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-test-boundary", "verify-scope-provenance", "verify-consumer-check-contract", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-contained-writes", "verify-telemetry-coverage", "verify-content-manifest", "verify-skill-external-fetch-gate", "verify-contract-drift", "verify-cursor-tier1", "verify-openclaw-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "verify-l4-owner", "verify-subagent-alive", "review-monitor-register", "review-monitor-release", "verify-tools", "verify-wip-cap", "verify-orphan-active", "verify-completed-tracked", "verify-literal-ac", "verify-ac", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
|
|
13
|
+
export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "coverage-hotspots", "policy", "authz", "escalation-cli", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "pr-finish-loop", "directive-finish-loop", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "scope-record-approved-scope", "scm-sync-default", "lifecycle-event", "lifecycle-stats", "session-start", "session-ready", "occupancy-steal", "plan-sequence", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "xbrief-create", "xbrief-verify", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-test-boundary", "verify-scope-provenance", "verify-consumer-check-contract", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-contained-writes", "verify-telemetry-coverage", "verify-content-manifest", "verify-skill-external-fetch-gate", "verify-contract-drift", "verify-cursor-tier1", "verify-openclaw-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "verify-l4-owner", "verify-subagent-alive", "review-monitor-register", "review-monitor-release", "verify-tools", "verify-wip-cap", "verify-orphan-active", "verify-lifecycle-visible", "verify-completed-tracked", "verify-literal-ac", "verify-ac", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
|
|
14
14
|
/** Core-only CLI entrypoints without a packages/cli wrapper. */
|
|
15
15
|
export declare const CORE_MODULE_VERBS: readonly ["scm", "scm-readiness", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "issue-sync-from-xbrief", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-pre-dispatch", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "project-render", "roadmap-render", "rule-map", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor", "feedback-file", "value-readback", "product-signal", "freshness-report", "decision-write", "decision-list"];
|
|
16
16
|
/** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
|
|
@@ -177,6 +177,12 @@ export declare function printCommandsList(io?: DispatchIo): void;
|
|
|
177
177
|
* (#2172). Preserves the init/update/doctor first-run guidance from #2273.
|
|
178
178
|
*/
|
|
179
179
|
export declare function printHelp(io?: DispatchIo): void;
|
|
180
|
+
/**
|
|
181
|
+
* Unknown-colon-verb remediation (#3439 / #2652).
|
|
182
|
+
* Agent-facing spelling is `deft <verb>` (works on consumer CLI and source).
|
|
183
|
+
* Bare `task <verb>` is not consumer-runnable on include-only Taskfiles.
|
|
184
|
+
*/
|
|
185
|
+
export declare function unknownColonVerbHint(verb: string): string;
|
|
180
186
|
/** Dispatch argv to a registered verb; returns the handler exit code. */
|
|
181
187
|
export declare function dispatch(argv: string[], io?: DispatchIo): Promise<number>;
|
|
182
188
|
/** Test seam: reset lazy handler cache between cases. */
|
package/dist/dispatch.js
CHANGED
|
@@ -10,7 +10,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:pat
|
|
|
10
10
|
import { engineInfo, userConfig } from "@deftai/directive-core";
|
|
11
11
|
import { assertWriteTargetSafe } from "@deftai/directive-core/dist/fs/projection-containment.js";
|
|
12
12
|
import { parseInitArgv, runInitDepositCli } from "@deftai/directive-core/init-deposit";
|
|
13
|
-
import { appendAuditLog, disclosureLine, migrateLegacyPolicyKey, PLAN_POLICY_KEY, policyColonInvocation, policySetInvocation, projectDefinitionPath, resolvePolicy, resolveWipCap, setPolicy, } from "@deftai/directive-core/policy";
|
|
13
|
+
import { appendAuditLog, disclosureLine, migrateLegacyPolicyKey, PLAN_POLICY_KEY, POLICY_AUDIT_NOOP_STDOUT, policyColonInvocation, policySetInvocation, projectDefinitionPath, resolvePolicy, resolveWipCap, setPolicy, stampChangedToken, } from "@deftai/directive-core/policy";
|
|
14
14
|
import { defaultWhich } from "@deftai/directive-core/scm";
|
|
15
15
|
import { KNOWN_SUBAGENT_BACKEND_IDS, probeSubagentBackends, resolveSwarmSubagentBackend, } from "@deftai/directive-core/swarm";
|
|
16
16
|
import { atomicWriteProjectDefinition } from "@deftai/directive-core/vbrief-build";
|
|
@@ -140,6 +140,7 @@ export const CLI_MODULE_VERBS = [
|
|
|
140
140
|
"verify-tools",
|
|
141
141
|
"verify-wip-cap",
|
|
142
142
|
"verify-orphan-active",
|
|
143
|
+
"verify-lifecycle-visible",
|
|
143
144
|
"verify-completed-tracked",
|
|
144
145
|
"verify-literal-ac",
|
|
145
146
|
"verify-ac",
|
|
@@ -220,6 +221,7 @@ export const POLICY_ACTION_ALIAS_SUBCOMMANDS = {
|
|
|
220
221
|
"policy:allow-direct-commits": "allow-direct-commits",
|
|
221
222
|
"policy:allow-bot-merge": "allow-bot-merge",
|
|
222
223
|
"policy:enable-value-feedback": "enable-value-feedback",
|
|
224
|
+
"policy:disable-host-hooks": "disable-host-hooks",
|
|
223
225
|
"policy:set-ceremony-dial": "set-ceremony-dial",
|
|
224
226
|
"policy:clear-value-feedback": "clear-value-feedback",
|
|
225
227
|
"policy:disable-directive": "disable-directive",
|
|
@@ -282,6 +284,7 @@ export const VERB_ALIASES = {
|
|
|
282
284
|
"verify:vbrief-conformance": "vbrief-validate",
|
|
283
285
|
"verify:wip-cap": "verify-wip-cap",
|
|
284
286
|
"verify:orphan-active": "verify-orphan-active",
|
|
287
|
+
"verify:lifecycle-visible": "verify-lifecycle-visible",
|
|
285
288
|
"verify:completed-tracked": "verify-completed-tracked",
|
|
286
289
|
"verify:literal-ac": "verify-literal-ac",
|
|
287
290
|
"verify:literal-acceptance": "verify-literal-ac",
|
|
@@ -2122,7 +2125,7 @@ function loadProjectDefinitionForWrite(projectRoot) {
|
|
|
2122
2125
|
throw new PolicySetError("PROJECT-DEFINITION 'plan' is not an object", "config");
|
|
2123
2126
|
}
|
|
2124
2127
|
const planObj = plan;
|
|
2125
|
-
migrateLegacyPolicyKey(planObj);
|
|
2128
|
+
const legacyMigrated = migrateLegacyPolicyKey(planObj);
|
|
2126
2129
|
let policy = planObj[PLAN_POLICY_KEY];
|
|
2127
2130
|
if (policy === undefined) {
|
|
2128
2131
|
policy = {};
|
|
@@ -2131,31 +2134,31 @@ function loadProjectDefinitionForWrite(projectRoot) {
|
|
|
2131
2134
|
if (typeof policy !== "object" || policy === null || Array.isArray(policy)) {
|
|
2132
2135
|
throw new PolicySetError("plan.policy is not an object", "config");
|
|
2133
2136
|
}
|
|
2134
|
-
return { path, data, policyBlock: policy };
|
|
2137
|
+
return { path, data, policyBlock: policy, legacyMigrated };
|
|
2135
2138
|
}
|
|
2136
2139
|
/** Write plan.policy.wipCap in place + append the audit row (mirrors set_wip_cap). */
|
|
2137
2140
|
function writeWipCap(projectRoot, cap, actor, note) {
|
|
2138
|
-
const { path, data, policyBlock } = loadProjectDefinitionForWrite(projectRoot);
|
|
2141
|
+
const { path, data, policyBlock, legacyMigrated } = loadProjectDefinitionForWrite(projectRoot);
|
|
2139
2142
|
const previous = policyBlock.wipCap;
|
|
2140
2143
|
policyBlock.wipCap = cap;
|
|
2141
|
-
|
|
2142
|
-
atomicWriteProjectDefinition(path, data);
|
|
2143
|
-
const changed = previous !== cap;
|
|
2144
|
+
const changed = previous !== cap || legacyMigrated;
|
|
2144
2145
|
const parts = [`actor=${actor}`, `wipCap=${cap}`, `previous=${pyRepr(previous)}`];
|
|
2145
2146
|
if (note)
|
|
2146
2147
|
parts.push(`note=${sanitizeNote(note)}`);
|
|
2147
|
-
const auditEntry = parts.join(" ");
|
|
2148
|
-
|
|
2148
|
+
const auditEntry = stampChangedToken(parts.join(" "), changed);
|
|
2149
|
+
if (changed) {
|
|
2150
|
+
assertWriteTargetSafe(projectRoot, path);
|
|
2151
|
+
atomicWriteProjectDefinition(path, data);
|
|
2152
|
+
}
|
|
2153
|
+
appendAuditLog(projectRoot, auditEntry, changed);
|
|
2149
2154
|
return { changed, auditEntry };
|
|
2150
2155
|
}
|
|
2151
2156
|
/** Write plan.policy.swarmSubagentBackend in place + append the audit row. */
|
|
2152
2157
|
function writeSubagentBackend(projectRoot, backendId, actor, note) {
|
|
2153
|
-
const { path, data, policyBlock } = loadProjectDefinitionForWrite(projectRoot);
|
|
2158
|
+
const { path, data, policyBlock, legacyMigrated } = loadProjectDefinitionForWrite(projectRoot);
|
|
2154
2159
|
const previous = policyBlock.swarmSubagentBackend;
|
|
2155
2160
|
policyBlock.swarmSubagentBackend = backendId;
|
|
2156
|
-
|
|
2157
|
-
atomicWriteProjectDefinition(path, data);
|
|
2158
|
-
const changed = previous !== backendId;
|
|
2161
|
+
const changed = previous !== backendId || legacyMigrated;
|
|
2159
2162
|
const parts = [
|
|
2160
2163
|
`actor=${actor}`,
|
|
2161
2164
|
`swarmSubagentBackend=${backendId}`,
|
|
@@ -2163,8 +2166,12 @@ function writeSubagentBackend(projectRoot, backendId, actor, note) {
|
|
|
2163
2166
|
];
|
|
2164
2167
|
if (note)
|
|
2165
2168
|
parts.push(`note=${sanitizeNote(note)}`);
|
|
2166
|
-
const auditEntry = parts.join(" ");
|
|
2167
|
-
|
|
2169
|
+
const auditEntry = stampChangedToken(parts.join(" "), changed);
|
|
2170
|
+
if (changed) {
|
|
2171
|
+
assertWriteTargetSafe(projectRoot, path);
|
|
2172
|
+
atomicWriteProjectDefinition(path, data);
|
|
2173
|
+
}
|
|
2174
|
+
appendAuditLog(projectRoot, auditEntry, changed);
|
|
2168
2175
|
return { changed, auditEntry };
|
|
2169
2176
|
}
|
|
2170
2177
|
/** Serialise the probe output for `subagent-backends --format json`. */
|
|
@@ -2229,7 +2236,7 @@ function applyBranchPolicy(args, io) {
|
|
|
2229
2236
|
io.writeOut(` audit: meta/policy-changes.log :: ${result.auditEntry}\n`);
|
|
2230
2237
|
}
|
|
2231
2238
|
else {
|
|
2232
|
-
io.writeOut(
|
|
2239
|
+
io.writeOut(`${POLICY_AUDIT_NOOP_STDOUT}\n`);
|
|
2233
2240
|
}
|
|
2234
2241
|
io.writeOut(`${disclosureLine(resolvePolicy(args.projectRoot))}\n`);
|
|
2235
2242
|
return 0;
|
|
@@ -2258,7 +2265,7 @@ function applyWipCap(args, io) {
|
|
|
2258
2265
|
io.writeOut(` audit: meta/policy-changes.log :: ${res.auditEntry}\n`);
|
|
2259
2266
|
}
|
|
2260
2267
|
else {
|
|
2261
|
-
io.writeOut(
|
|
2268
|
+
io.writeOut(`${POLICY_AUDIT_NOOP_STDOUT}\n`);
|
|
2262
2269
|
}
|
|
2263
2270
|
const result = resolveWipCap(args.projectRoot);
|
|
2264
2271
|
io.writeOut(`[deft policy] plan.policy.wipCap=${result.cap} (source: ${result.source}).\n`);
|
|
@@ -2278,7 +2285,7 @@ function applySubagentBackend(args, io) {
|
|
|
2278
2285
|
io.writeOut(` audit: meta/policy-changes.log :: ${res.auditEntry}\n`);
|
|
2279
2286
|
}
|
|
2280
2287
|
else {
|
|
2281
|
-
io.writeOut(
|
|
2288
|
+
io.writeOut(`${POLICY_AUDIT_NOOP_STDOUT}\n`);
|
|
2282
2289
|
}
|
|
2283
2290
|
const result = resolveSwarmSubagentBackend(args.projectRoot);
|
|
2284
2291
|
io.writeOut(`[deft policy] plan.policy.swarmSubagentBackend=${pyRepr(result.backend_id)} ` +
|
|
@@ -2720,6 +2727,23 @@ async function invokeHandler(handler, argv) {
|
|
|
2720
2727
|
return typeof code === "number" ? code : 0;
|
|
2721
2728
|
}
|
|
2722
2729
|
const CLI_PACKAGE = "@deftai/directive";
|
|
2730
|
+
const PLAN_SEQUENCE_VERBS = "set|current|clear|advance";
|
|
2731
|
+
/**
|
|
2732
|
+
* Unknown-colon-verb remediation (#3439 / #2652).
|
|
2733
|
+
* Agent-facing spelling is `deft <verb>` (works on consumer CLI and source).
|
|
2734
|
+
* Bare `task <verb>` is not consumer-runnable on include-only Taskfiles.
|
|
2735
|
+
*/
|
|
2736
|
+
export function unknownColonVerbHint(verb) {
|
|
2737
|
+
if (verb.startsWith("plan-sequence:") && !(verb in PLAN_SEQUENCE_ALIAS_SUBCOMMANDS)) {
|
|
2738
|
+
return (`hint: plan-sequence verbs are ${PLAN_SEQUENCE_VERBS} ` +
|
|
2739
|
+
`(e.g. \`deft plan-sequence:current\`). '${verb}' is not a verb. ` +
|
|
2740
|
+
`Do not run bare \`task ${verb}\` -- consumer include-only Taskfiles cannot resolve it.\n`);
|
|
2741
|
+
}
|
|
2742
|
+
const hyphen = verb.replaceAll(":", "-");
|
|
2743
|
+
return (`hint: try \`deft ${verb}\` (CLI) or \`task deft:${verb}\` (consumer Taskfile). ` +
|
|
2744
|
+
`Bare \`task ${verb}\` does not exist on include-only deposits. ` +
|
|
2745
|
+
`Hyphen stem: ${hyphen}.\n`);
|
|
2746
|
+
}
|
|
2723
2747
|
function versionBanner() {
|
|
2724
2748
|
const info = engineInfo();
|
|
2725
2749
|
return `${CLI_PACKAGE} (engine: ${info.name}@${info.version})\n`;
|
|
@@ -2743,8 +2767,7 @@ export async function dispatch(argv, io = defaultIo()) {
|
|
|
2743
2767
|
if (canonical === null) {
|
|
2744
2768
|
io.writeErr(`directive: unknown verb '${verb}'\n`);
|
|
2745
2769
|
if (verb?.includes(":")) {
|
|
2746
|
-
io.writeErr(
|
|
2747
|
-
`(e.g. pr:watch → pr-watch / \`task pr:watch\`)\n`);
|
|
2770
|
+
io.writeErr(unknownColonVerbHint(verb));
|
|
2748
2771
|
}
|
|
2749
2772
|
return 1;
|
|
2750
2773
|
}
|
|
@@ -27,6 +27,15 @@ export interface HumanPresenceMintSeams {
|
|
|
27
27
|
readonly readInteractiveConfirm?: () => string | null;
|
|
28
28
|
}
|
|
29
29
|
export declare function looksLikeAgentShell(environ: NodeJS.ProcessEnv): boolean;
|
|
30
|
+
/** Platform controlling-terminal path (`CONIN$` on win32, `/dev/tty` elsewhere). */
|
|
31
|
+
export declare function controllingTerminalPath(platform?: NodeJS.Platform): string;
|
|
32
|
+
/**
|
|
33
|
+
* Open flag for the platform controlling-terminal device (#3596).
|
|
34
|
+
*
|
|
35
|
+
* Windows `CONIN$` generally requires read/write (`r+`); `r` (O_RDONLY) fails
|
|
36
|
+
* in a real interactive console and made operator mint unreachable on win32.
|
|
37
|
+
*/
|
|
38
|
+
export declare function controllingTerminalOpenFlag(platform?: NodeJS.Platform): "r" | "r+";
|
|
30
39
|
export declare function resolveHumanPresenceMintSeams(seams?: HumanPresenceMintSeams): Required<HumanPresenceMintSeams>;
|
|
31
40
|
/** Active UAT campaign id, or null when no lease is active. */
|
|
32
41
|
export declare function activeUatCampaignId(projectRoot: string): string | null;
|
|
@@ -67,10 +67,22 @@ export function looksLikeAgentShell(environ) {
|
|
|
67
67
|
function defaultIsTty() {
|
|
68
68
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
69
69
|
}
|
|
70
|
+
/** Platform controlling-terminal path (`CONIN$` on win32, `/dev/tty` elsewhere). */
|
|
71
|
+
export function controllingTerminalPath(platform = process.platform) {
|
|
72
|
+
return platform === "win32" ? "CONIN$" : "/dev/tty";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Open flag for the platform controlling-terminal device (#3596).
|
|
76
|
+
*
|
|
77
|
+
* Windows `CONIN$` generally requires read/write (`r+`); `r` (O_RDONLY) fails
|
|
78
|
+
* in a real interactive console and made operator mint unreachable on win32.
|
|
79
|
+
*/
|
|
80
|
+
export function controllingTerminalOpenFlag(platform = process.platform) {
|
|
81
|
+
return platform === "win32" ? "r+" : "r";
|
|
82
|
+
}
|
|
70
83
|
function defaultHasControllingTerminal() {
|
|
71
84
|
try {
|
|
72
|
-
const
|
|
73
|
-
const fd = openSync(path, "r");
|
|
85
|
+
const fd = openSync(controllingTerminalPath(), controllingTerminalOpenFlag());
|
|
74
86
|
closeSync(fd);
|
|
75
87
|
return true;
|
|
76
88
|
}
|
|
@@ -83,8 +95,7 @@ function defaultReadInteractiveConfirm() {
|
|
|
83
95
|
// so agent-controlled stdin alone cannot supply the confirm phrase (#3110).
|
|
84
96
|
let fd = null;
|
|
85
97
|
try {
|
|
86
|
-
|
|
87
|
-
fd = openSync(path, "r");
|
|
98
|
+
fd = openSync(controllingTerminalPath(), controllingTerminalOpenFlag());
|
|
88
99
|
const buf = Buffer.alloc(256);
|
|
89
100
|
const n = readSync(fd, buf, 0, buf.length, null);
|
|
90
101
|
if (n <= 0)
|
package/dist/plan-sequence.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
interface Parsed {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
action: "set" | "current" | "clear" | "advance" | null;
|
|
5
|
+
file: string | null;
|
|
6
|
+
jsonInline: string | null;
|
|
7
|
+
emitJson: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseArgs(argv: string[]): Parsed;
|
|
2
11
|
export declare function main(argv?: string[]): number;
|
|
12
|
+
export {};
|
|
3
13
|
//# sourceMappingURL=plan-sequence.d.ts.map
|
package/dist/plan-sequence.js
CHANGED
|
@@ -6,7 +6,7 @@ import { readFileSync } from "node:fs";
|
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { advancePlanSequence, clearPlanSequence, createPlanSequence, parsePlanSequence, readPlanSequence, writePlanSequence, } from "@deftai/directive-core/plan-sequence";
|
|
9
|
-
function parseArgs(argv) {
|
|
9
|
+
export function parseArgs(argv) {
|
|
10
10
|
const parsed = {
|
|
11
11
|
projectRoot: ".",
|
|
12
12
|
action: null,
|
|
@@ -19,6 +19,8 @@ function parseArgs(argv) {
|
|
|
19
19
|
const arg = argv[i];
|
|
20
20
|
if (arg === undefined)
|
|
21
21
|
continue;
|
|
22
|
+
if (arg === "--")
|
|
23
|
+
continue;
|
|
22
24
|
if (arg === "--json") {
|
|
23
25
|
parsed.emitJson = true;
|
|
24
26
|
}
|
package/dist/policy.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { type CeremonyDepth } from "@deftai/directive-core/policy";
|
|
2
|
+
import { type CeremonyDepth, type HookHost } from "@deftai/directive-core/policy";
|
|
3
3
|
interface ShowArgs {
|
|
4
4
|
format: "text" | "json";
|
|
5
5
|
changedOnly: boolean;
|
|
@@ -8,10 +8,11 @@ interface ShowArgs {
|
|
|
8
8
|
error?: string;
|
|
9
9
|
}
|
|
10
10
|
interface SetArgs {
|
|
11
|
-
cmd: "show" | "enforce-branches" | "allow-direct-commits" | "allow-bot-merge" | "enable-value-feedback" | "clear-value-feedback" | "set-ceremony-dial" | "disable-directive" | "enable-directive" | "resolve";
|
|
11
|
+
cmd: "show" | "enforce-branches" | "allow-direct-commits" | "allow-bot-merge" | "enable-value-feedback" | "clear-value-feedback" | "set-ceremony-dial" | "disable-host-hooks" | "disable-directive" | "enable-directive" | "resolve";
|
|
12
12
|
confirm: boolean;
|
|
13
13
|
actor: string;
|
|
14
14
|
note: string;
|
|
15
|
+
host?: HookHost;
|
|
15
16
|
projectRoot: string;
|
|
16
17
|
format: "text" | "json";
|
|
17
18
|
changedOnly: boolean;
|
package/dist/policy.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { resolve as pathResolve, relative } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { ALLOW_BOT_MERGE_CAPABILITY_COST, CEREMONY_DEPTHS, clearValueFeedback, createNoDeftDirectiveFlag, describeShadowedPlanExtension, detectNoDeftDirective, detectShadowedPlanExtensions, disclosureLine, enableValueFeedback, FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, formatValueFeedbackStatusLine, humanMergeDisclosureLine, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, NO_DEFT_DIRECTIVE_DISABLED_MESSAGE, NO_DEFT_DIRECTIVE_FLAG_NAME, NO_DEFT_DIRECTIVE_INCONSISTENT_MESSAGE, policyColonInvocation, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, removeNoDeftDirectiveFlag, renderJson, renderText, resolveHumanMergePolicy, resolvePolicy, resolveValueFeedback, setCeremonyDial, setPolicy, setRequireHumanMerge, } from "@deftai/directive-core/policy";
|
|
9
|
+
import { ALLOW_BOT_MERGE_CAPABILITY_COST, CEREMONY_DEPTHS, clearValueFeedback, createNoDeftDirectiveFlag, describeShadowedPlanExtension, detectNoDeftDirective, detectShadowedPlanExtensions, disableHostHooks, disclosureLine, enableValueFeedback, FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, formatValueFeedbackStatusLine, humanMergeDisclosureLine, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, NO_DEFT_DIRECTIVE_DISABLED_MESSAGE, NO_DEFT_DIRECTIVE_FLAG_NAME, NO_DEFT_DIRECTIVE_INCONSISTENT_MESSAGE, POLICY_AUDIT_NOOP_STDOUT, parseHookHost, policyColonInvocation, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, removeNoDeftDirectiveFlag, renderJson, renderText, resolveHumanMergePolicy, resolvePolicy, resolveValueFeedback, setCeremonyDial, setPolicy, setRequireHumanMerge, } from "@deftai/directive-core/policy";
|
|
10
10
|
const CAPABILITY_COST_DISCLOSURE = "\u26a0 Capability-cost disclosure -- enabling direct commits to the default " +
|
|
11
11
|
"branch turns OFF the deft branch-protection policy.\n" +
|
|
12
12
|
" \u2022 Pre-commit + pre-push hooks will no longer block default-branch " +
|
|
@@ -114,7 +114,7 @@ export function parseShowArgs(argv) {
|
|
|
114
114
|
/** Parse argv for the policy CLI (show + set subcommands). */
|
|
115
115
|
export function parseArgs(argv) {
|
|
116
116
|
if (argv.length === 0) {
|
|
117
|
-
const usage = "usage: policy [show|enforce-branches|allow-direct-commits|allow-bot-merge|enable-value-feedback|clear-value-feedback|set-ceremony-dial|disable-directive|enable-directive|resolve] ...";
|
|
117
|
+
const usage = "usage: policy [show|enforce-branches|allow-direct-commits|allow-bot-merge|enable-value-feedback|clear-value-feedback|set-ceremony-dial|disable-host-hooks|disable-directive|enable-directive|resolve] ...";
|
|
118
118
|
return makeSetError(usage);
|
|
119
119
|
}
|
|
120
120
|
const cmd = argv[0];
|
|
@@ -152,6 +152,7 @@ export function parseArgs(argv) {
|
|
|
152
152
|
cmd === "enable-value-feedback" ||
|
|
153
153
|
cmd === "clear-value-feedback" ||
|
|
154
154
|
cmd === "set-ceremony-dial" ||
|
|
155
|
+
cmd === "disable-host-hooks" ||
|
|
155
156
|
cmd === "disable-directive" ||
|
|
156
157
|
cmd === "enable-directive") {
|
|
157
158
|
let confirm = false;
|
|
@@ -167,11 +168,14 @@ export function parseArgs(argv) {
|
|
|
167
168
|
? policyColonInvocation("clear-value-feedback")
|
|
168
169
|
: cmd === "set-ceremony-dial"
|
|
169
170
|
? policyColonInvocation("set-ceremony-dial")
|
|
170
|
-
: cmd === "disable-
|
|
171
|
-
? policyColonInvocation("disable-
|
|
172
|
-
:
|
|
171
|
+
: cmd === "disable-host-hooks"
|
|
172
|
+
? policyColonInvocation("disable-host-hooks")
|
|
173
|
+
: cmd === "disable-directive"
|
|
174
|
+
? policyColonInvocation("disable-directive")
|
|
175
|
+
: policyColonInvocation("enable-directive");
|
|
173
176
|
let note = "";
|
|
174
177
|
let projectRoot = ".";
|
|
178
|
+
let host;
|
|
175
179
|
let ceremonyOverride;
|
|
176
180
|
let ceremonyEnabled;
|
|
177
181
|
for (let i = 1; i < argv.length; i += 1) {
|
|
@@ -253,10 +257,32 @@ export function parseArgs(argv) {
|
|
|
253
257
|
}
|
|
254
258
|
ceremonyEnabled = v === "true";
|
|
255
259
|
}
|
|
260
|
+
else if (cmd === "disable-host-hooks" && arg === "--host") {
|
|
261
|
+
const v = argv[i + 1];
|
|
262
|
+
const parsedHost = parseHookHost(v);
|
|
263
|
+
if (parsedHost === null) {
|
|
264
|
+
return makeSetError("argument --host: expected claude|cursor|grok|codex");
|
|
265
|
+
}
|
|
266
|
+
host = parsedHost;
|
|
267
|
+
i += 1;
|
|
268
|
+
}
|
|
269
|
+
else if (cmd === "disable-host-hooks" && arg?.startsWith("--host=")) {
|
|
270
|
+
const parsedHost = parseHookHost(arg.slice("--host=".length));
|
|
271
|
+
if (parsedHost === null) {
|
|
272
|
+
return makeSetError("argument --host: expected claude|cursor|grok|codex");
|
|
273
|
+
}
|
|
274
|
+
host = parsedHost;
|
|
275
|
+
}
|
|
276
|
+
else if (arg === "--") {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
256
279
|
else {
|
|
257
280
|
return makeSetError(`unrecognized argument: ${arg}`);
|
|
258
281
|
}
|
|
259
282
|
}
|
|
283
|
+
if (cmd === "disable-host-hooks" && host === undefined) {
|
|
284
|
+
return makeSetError("disable-host-hooks requires --host claude|cursor|grok|codex");
|
|
285
|
+
}
|
|
260
286
|
return {
|
|
261
287
|
cmd,
|
|
262
288
|
confirm,
|
|
@@ -266,6 +292,7 @@ export function parseArgs(argv) {
|
|
|
266
292
|
format: "text",
|
|
267
293
|
changedOnly: false,
|
|
268
294
|
field: null,
|
|
295
|
+
host,
|
|
269
296
|
ceremonyOverride,
|
|
270
297
|
ceremonyEnabled,
|
|
271
298
|
};
|
|
@@ -352,6 +379,21 @@ function runEnableValueFeedback(args) {
|
|
|
352
379
|
process.stdout.write(result.stdout);
|
|
353
380
|
return result.exitCode;
|
|
354
381
|
}
|
|
382
|
+
function runDisableHostHooks(args) {
|
|
383
|
+
const host = args.host;
|
|
384
|
+
if (host === undefined) {
|
|
385
|
+
process.stderr.write("policy: disable-host-hooks requires --host claude|cursor|grok|codex\n");
|
|
386
|
+
return 2;
|
|
387
|
+
}
|
|
388
|
+
const result = disableHostHooks(pathResolve(args.projectRoot), {
|
|
389
|
+
host,
|
|
390
|
+
confirm: args.confirm,
|
|
391
|
+
actor: args.actor,
|
|
392
|
+
note: args.note,
|
|
393
|
+
});
|
|
394
|
+
process.stdout.write(result.stdout);
|
|
395
|
+
return result.exitCode;
|
|
396
|
+
}
|
|
355
397
|
function runSet(args) {
|
|
356
398
|
const projectRoot = pathResolve(args.projectRoot);
|
|
357
399
|
if (args.cmd === "allow-direct-commits" && !args.confirm) {
|
|
@@ -373,7 +415,7 @@ function runSet(args) {
|
|
|
373
415
|
process.stdout.write(` audit: meta/policy-changes.log :: ${auditEntry}\n`);
|
|
374
416
|
}
|
|
375
417
|
else {
|
|
376
|
-
process.stdout.write(
|
|
418
|
+
process.stdout.write(`${POLICY_AUDIT_NOOP_STDOUT}\n`);
|
|
377
419
|
}
|
|
378
420
|
process.stdout.write(`${disclosureLine(resolvePolicy(projectRoot))}\n`);
|
|
379
421
|
return 0;
|
|
@@ -454,7 +496,7 @@ function runAllowBotMerge(args) {
|
|
|
454
496
|
process.stdout.write(` audit: meta/policy-changes.log :: ${auditEntry}\n`);
|
|
455
497
|
}
|
|
456
498
|
else {
|
|
457
|
-
process.stdout.write(
|
|
499
|
+
process.stdout.write(`${POLICY_AUDIT_NOOP_STDOUT}\n`);
|
|
458
500
|
}
|
|
459
501
|
const line = humanMergeDisclosureLine(resolveHumanMergePolicy(projectRoot));
|
|
460
502
|
if (line !== null) {
|
|
@@ -504,6 +546,9 @@ export function run(argv) {
|
|
|
504
546
|
if (args.cmd === "enable-value-feedback") {
|
|
505
547
|
return runEnableValueFeedback(args);
|
|
506
548
|
}
|
|
549
|
+
if (args.cmd === "disable-host-hooks") {
|
|
550
|
+
return runDisableHostHooks(args);
|
|
551
|
+
}
|
|
507
552
|
if (args.cmd === "clear-value-feedback") {
|
|
508
553
|
return runClearValueFeedback(args);
|
|
509
554
|
}
|
package/dist/preflight-cache.js
CHANGED
|
@@ -58,6 +58,12 @@ export function parseArgs(argv) {
|
|
|
58
58
|
else if (arg === "--allow-missing-bootstrap") {
|
|
59
59
|
parsed.allowMissingBootstrap = true;
|
|
60
60
|
}
|
|
61
|
+
else if (arg === "--skip-drift-probe") {
|
|
62
|
+
parsed.skipDriftProbe = true;
|
|
63
|
+
}
|
|
64
|
+
else if (arg === "--work-selection") {
|
|
65
|
+
parsed.workSelection = true;
|
|
66
|
+
}
|
|
61
67
|
else if (arg === "--quiet") {
|
|
62
68
|
parsed.quiet = true;
|
|
63
69
|
}
|
|
@@ -81,6 +87,7 @@ export function run(argv) {
|
|
|
81
87
|
forIssue: args.forIssue ?? null,
|
|
82
88
|
allowStale: args.allowStale ?? false,
|
|
83
89
|
allowMissingBootstrap: args.allowMissingBootstrap ?? false,
|
|
90
|
+
skipDriftProbe: (args.skipDriftProbe ?? false) && !args.workSelection,
|
|
84
91
|
});
|
|
85
92
|
const quiet = args.quiet ?? false;
|
|
86
93
|
if (result.code === 0) {
|
package/dist/triage-actions.js
CHANGED
package/dist/triage-queue.js
CHANGED
|
@@ -88,7 +88,7 @@ export function parseArgs(argv) {
|
|
|
88
88
|
};
|
|
89
89
|
for (let i = 0; i < argv.length; i += 1) {
|
|
90
90
|
const arg = argv[i];
|
|
91
|
-
if (arg === "queue") {
|
|
91
|
+
if (arg === "queue" || arg === "--") {
|
|
92
92
|
continue;
|
|
93
93
|
}
|
|
94
94
|
if (arg === "--include-blocked") {
|
|
@@ -197,6 +197,9 @@ export function parseShowArgs(argv) {
|
|
|
197
197
|
}
|
|
198
198
|
for (let i = start; i < argv.length; i += 1) {
|
|
199
199
|
const arg = argv[i];
|
|
200
|
+
if (arg === "--") {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
200
203
|
const commonHit = parseCommonFlag(arg, argv, i, parsed);
|
|
201
204
|
if (commonHit !== null) {
|
|
202
205
|
if (commonHit.error !== undefined) {
|
|
@@ -5,6 +5,10 @@ interface ParsedArgs {
|
|
|
5
5
|
projectRoot: string;
|
|
6
6
|
allowList: string | null;
|
|
7
7
|
quiet: boolean;
|
|
8
|
+
enforce: boolean;
|
|
9
|
+
coverageReport: string | null;
|
|
10
|
+
coverageDir: string | null;
|
|
11
|
+
help?: boolean;
|
|
8
12
|
error?: string;
|
|
9
13
|
}
|
|
10
14
|
/** Parse the verify-forward-coverage CLI args, mirroring the verify-encoding surface. */
|
|
@@ -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
|
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"
|