@deftai/directive 0.119.5 → 0.119.7

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.
@@ -28,6 +28,7 @@ export const SCOPE_LIFECYCLE_VERBS = new Set([
28
28
  "restore",
29
29
  "block",
30
30
  "unblock",
31
+ "stamp-evidence",
31
32
  ]);
32
33
  /** pr:* task names that do not hyphenate 1:1 to handler stems. */
33
34
  export const PR_VERB_MAP = {
package/dist/doctor.js CHANGED
@@ -100,42 +100,45 @@ async function resolveEngineContentRoot() {
100
100
  }
101
101
  }
102
102
  export async function run(argv) {
103
- // #2022: surface pre-cutover (pre-v0.20 document model) migration state alongside the
104
- // core doctor report. Only emit on a valid, human-readable invocation: suppressed under
105
- // --json (so the machine-readable report stays valid), on --help, and when unknown flags
106
- // are present (so an invalid invocation still mirrors the core error path exactly).
103
+ // Human advisory lines stay off --json so the machine report stays one object.
104
+ // Deposit hygiene is still passed into cmdDoctor, including --json (#4812).
107
105
  const flags = parseDoctorFlags(argv);
108
- let depositHygieneExit = 0;
109
106
  const installedRoot = await resolveEngineContentRoot();
110
107
  if (installedRoot !== null) {
111
108
  setDoctorAgentsTemplateRoot(installedRoot);
112
109
  }
113
110
  try {
114
- if (!flags.json && !flags.help && flags.unknown.length === 0) {
115
- const projectRoot = flags.projectRoot ?? process.cwd();
116
- const walkRoot = resolveContentPackageRoot(projectRoot);
117
- const depositResult = evaluateDepositFileSetHygiene(projectRoot, {
118
- contentRoot: installedRoot ?? undefined,
119
- walkRoot,
120
- installedRoot,
121
- });
111
+ if (flags.help || flags.unknown.length > 0) {
112
+ return cmdDoctor(argv);
113
+ }
114
+ const projectRoot = flags.projectRoot ?? process.cwd();
115
+ const walkRoot = resolveContentPackageRoot(projectRoot);
116
+ const depositResult = evaluateDepositFileSetHygiene(projectRoot, {
117
+ contentRoot: installedRoot ?? undefined,
118
+ walkRoot,
119
+ installedRoot,
120
+ });
121
+ const closure = evaluateInstalledDepositClosure(projectRoot);
122
+ // Package-absent files stay diagnostic unless --full. A real hygiene failure
123
+ // (full file-set or declared closure) is the one status cmdDoctor shares.
124
+ const fileSetFailed = flags.full && !depositResult.skipped && depositResult.absent.length > 0;
125
+ const closureFailed = flags.full && !closure.skipped && (closure.missing.length > 0 || closure.error !== null);
126
+ const line = renderDepositFileSetHygieneLine(projectRoot, depositResult);
127
+ if (!flags.json) {
122
128
  process.stdout.write(`${renderPrecutoverLine(projectRoot)}\n`);
123
129
  process.stdout.write(`${renderXbriefMigrationLine(projectRoot)}\n`);
124
130
  process.stdout.write(`${renderStaleHeaderLine(projectRoot)}\n`);
125
- process.stdout.write(`${renderDepositFileSetHygieneLine(projectRoot, depositResult)}\n`);
126
- const closure = evaluateInstalledDepositClosure(projectRoot);
131
+ process.stdout.write(`${line}\n`);
127
132
  process.stdout.write(`${renderDeclaredDepositClosureLine(closure)}\n`);
128
- if (flags.full && !depositResult.skipped && depositResult.absent.length > 0) {
129
- depositHygieneExit = 1;
130
- }
131
- if (flags.full &&
132
- !closure.skipped &&
133
- (closure.missing.length > 0 || closure.error !== null)) {
134
- depositHygieneExit = 1;
135
- }
136
133
  }
137
- const doctorExit = cmdDoctor(argv);
138
- return Math.max(depositHygieneExit, doctorExit);
134
+ const closureLine = renderDeclaredDepositClosureLine(closure);
135
+ return cmdDoctor(argv, {
136
+ depositHygiene: {
137
+ failed: fileSetFailed || closureFailed,
138
+ absent: depositResult.absent,
139
+ line: fileSetFailed ? line : closureFailed ? closureLine : line,
140
+ },
141
+ });
139
142
  }
140
143
  finally {
141
144
  setDoctorAgentsTemplateRoot(undefined);
@@ -5,7 +5,7 @@
5
5
  import { readFileSync } from "node:fs";
6
6
  import { resolve } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
- import { advancePlanSequence, clearPlanSequence, createPlanSequence, parsePlanSequence, readPlanSequence, writePlanSequence, } from "@deftai/directive-core/plan-sequence";
8
+ import { advancePlanSequence, clearPlanSequence, collectTerminalLifecycleOrigins, createPlanSequence, detectTerminalEntryDrift, inspectMissingSequenceKind, missingSequenceKindPayload, parsePlanSequence, readPlanSequence, writePlanSequence, } from "@deftai/directive-core/plan-sequence";
9
9
  export function parseArgs(argv) {
10
10
  const parsed = {
11
11
  projectRoot: ".",
@@ -113,13 +113,40 @@ export function main(argv = process.argv.slice(2)) {
113
113
  return 0;
114
114
  }
115
115
  if (parsed.action === "current") {
116
+ const missingKind = inspectMissingSequenceKind(root);
117
+ if (missingKind !== null) {
118
+ if (parsed.emitJson) {
119
+ process.stdout.write(`${JSON.stringify(missingSequenceKindPayload(missingKind), null, 2)}\n`);
120
+ }
121
+ else {
122
+ process.stderr.write(`${missingKind.message}\n`);
123
+ }
124
+ return 1;
125
+ }
116
126
  const seq = readPlanSequence(root);
117
127
  if (seq === null) {
118
128
  process.stderr.write("No active ordered-plan sequence (.deft/plan-sequence.json missing).\n");
119
129
  return 1;
120
130
  }
131
+ const drift = detectTerminalEntryDrift(seq, collectTerminalLifecycleOrigins(root));
121
132
  if (parsed.emitJson) {
122
- process.stdout.write(`${JSON.stringify(seq, null, 2)}\n`);
133
+ if (drift.drifted) {
134
+ process.stdout.write(`${JSON.stringify({
135
+ ...seq,
136
+ terminal_lifecycle_drift: {
137
+ code: drift.code,
138
+ message: drift.message,
139
+ originPath: drift.originPath,
140
+ folder: drift.folder,
141
+ },
142
+ }, null, 2)}\n`);
143
+ }
144
+ else {
145
+ process.stdout.write(`${JSON.stringify(seq, null, 2)}\n`);
146
+ }
147
+ }
148
+ else if (drift.drifted) {
149
+ process.stderr.write(`${drift.message}\n`);
123
150
  }
124
151
  else {
125
152
  const cur = seq.exhausted ? null : seq.entries[seq.current_index];
@@ -132,7 +159,7 @@ export function main(argv = process.argv.slice(2)) {
132
159
  process.stdout.write("current: (exhausted — fresh approval required)\n");
133
160
  }
134
161
  }
135
- return 0;
162
+ return drift.drifted ? 1 : 0;
136
163
  }
137
164
  if (parsed.action === "clear") {
138
165
  const cleared = clearPlanSequence(root);
package/dist/policy.js CHANGED
@@ -274,7 +274,6 @@ export function parseArgs(argv) {
274
274
  host = parsedHost;
275
275
  }
276
276
  else if (arg === "--") {
277
- continue;
278
277
  }
279
278
  else {
280
279
  return makeSetError(`unrecognized argument: ${arg}`);
@@ -46,7 +46,7 @@ export function parseArgs(argv) {
46
46
  if (nextToken === "--help" || nextToken === "-h") {
47
47
  return { ...parsed, help: true };
48
48
  }
49
- if (nextToken !== undefined && nextToken.startsWith("-")) {
49
+ if (nextToken?.startsWith("-")) {
50
50
  return {
51
51
  ...parsed,
52
52
  error: "argument --vbrief-path: expected one argument",
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- import { readPlanSequence, verifyPlanTarget, } from "@deftai/directive-core/plan-sequence";
7
+ import { collectTerminalLifecycleOrigins, inspectMissingSequenceKind, missingSequenceKindPayload, readPlanSequence, verifyPlanTarget, } from "@deftai/directive-core/plan-sequence";
8
8
  const KINDS = [
9
9
  "pr",
10
10
  "issue",
@@ -94,7 +94,18 @@ export function main(argv = process.argv.slice(2)) {
94
94
  process.stderr.write(`${parsed.error ?? "usage error"}\n`);
95
95
  return 2;
96
96
  }
97
- const seq = readPlanSequence(resolve(parsed.projectRoot));
97
+ const root = resolve(parsed.projectRoot);
98
+ const missingKind = inspectMissingSequenceKind(root);
99
+ if (missingKind !== null) {
100
+ if (parsed.emitJson) {
101
+ process.stdout.write(`${JSON.stringify(missingSequenceKindPayload(missingKind), null, 2)}\n`);
102
+ }
103
+ else {
104
+ process.stderr.write(`${missingKind.message}\n`);
105
+ }
106
+ return 1;
107
+ }
108
+ const seq = readPlanSequence(root);
98
109
  // No sequence: allow (caller may have explicit operator approval); warn on stderr.
99
110
  if (seq === null) {
100
111
  if (parsed.emitJson) {
@@ -108,6 +119,7 @@ export function main(argv = process.argv.slice(2)) {
108
119
  const result = verifyPlanTarget(seq, {
109
120
  targetKind: parsed.targetKind,
110
121
  target: parsed.target,
122
+ terminalOrigins: collectTerminalLifecycleOrigins(root),
111
123
  });
112
124
  if (parsed.emitJson) {
113
125
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive",
3
- "version": "0.119.5",
3
+ "version": "0.119.7",
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.119.5",
38
- "@deftai/directive-content": "^0.119.5"
37
+ "@deftai/directive-core": "^0.119.7",
38
+ "@deftai/directive-content": "^0.119.7"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b"