@deftai/directive-core 0.85.0 → 0.86.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/doctor/constants.d.ts +2 -2
- package/dist/doctor/constants.js +2 -2
- package/dist/doctor/main.d.ts +2 -1
- package/dist/doctor/main.js +70 -18
- package/dist/doctor/types.d.ts +3 -0
- package/dist/init-deposit/agent-hooks.js +14 -6
- package/dist/init-deposit/gitignore.js +5 -0
- package/dist/policy/org-force-on-migration.js +2 -0
- package/dist/render/framework-commands.d.ts +1 -1
- package/dist/render/framework-commands.js +6 -6
- package/dist/render/roadmap-render.d.ts +5 -1
- package/dist/render/roadmap-render.js +20 -2
- package/dist/render/rule-map.js +5 -0
- package/dist/verify-env/agent-hooks-live-probe.d.ts +32 -0
- package/dist/verify-env/agent-hooks-live-probe.js +216 -0
- package/dist/verify-env/index.d.ts +1 -0
- package/dist/verify-env/index.js +1 -0
- package/dist/xbrief-migrate/migrate-project.js +26 -17
- package/package.json +3 -3
|
@@ -14,9 +14,9 @@ export declare const PUBLIC_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
|
14
14
|
export declare const NPM_REGISTRY_MIRROR_DOC_URL = "https://github.com/deftai/directive/blob/master/content/UPGRADING.md#corporate-or-mirrored-npm-registry";
|
|
15
15
|
export declare const NETWORK_DISCLOSURE_LINE: string;
|
|
16
16
|
export declare const PAYLOAD_STALENESS_OFFLINE_SKIP_MESSAGE: string;
|
|
17
|
-
export declare const EXPECTED_FRAMEWORK_DIRS: readonly ["tasks", "scripts", "
|
|
17
|
+
export declare const EXPECTED_FRAMEWORK_DIRS: readonly ["tasks", "scripts", "xbrief"];
|
|
18
18
|
/** npm consumer deposit after #2022 Phase 3 -- Python scripts/ tree is intentionally absent. */
|
|
19
|
-
export declare const CONSUMER_FRAMEWORK_DIRS: readonly ["tasks", "
|
|
19
|
+
export declare const CONSUMER_FRAMEWORK_DIRS: readonly ["tasks", "xbrief"];
|
|
20
20
|
export declare const DEFT_REPO_POSITIVE_MARKERS: readonly ["content/templates/agents-entry.md", "content/skills/deft-directive-build/SKILL.md"];
|
|
21
21
|
export declare const EXPECTED_CONTENT_DIRS: readonly ["languages", "strategies", "skills", "templates"];
|
|
22
22
|
/** Post-freeze canonical upgrade path (#1997 / #2003 / #1912). */
|
package/dist/doctor/constants.js
CHANGED
|
@@ -46,9 +46,9 @@ export const PAYLOAD_STALENESS_OFFLINE_SKIP_MESSAGE = "skip -- offline tier (def
|
|
|
46
46
|
"(discloses tool + registry before contacting either).";
|
|
47
47
|
// Engine / lifecycle dirs that stay at the framework root (NOT relocated by
|
|
48
48
|
// #1875). Shippable-content dirs moved under content/ -- see EXPECTED_CONTENT_DIRS.
|
|
49
|
-
export const EXPECTED_FRAMEWORK_DIRS = ["tasks", "scripts", "
|
|
49
|
+
export const EXPECTED_FRAMEWORK_DIRS = ["tasks", "scripts", "xbrief"];
|
|
50
50
|
/** npm consumer deposit after #2022 Phase 3 -- Python scripts/ tree is intentionally absent. */
|
|
51
|
-
export const CONSUMER_FRAMEWORK_DIRS = ["tasks", "
|
|
51
|
+
export const CONSUMER_FRAMEWORK_DIRS = ["tasks", "xbrief"];
|
|
52
52
|
// Post-#1875 content/ move: these framework-internal markers now live under
|
|
53
53
|
// content/ in the SOURCE repo. They identify a deft source checkout (a consumer
|
|
54
54
|
// would never reproduce them); the C1 flatten means a consumer deposit has no
|
package/dist/doctor/main.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { type ResolutionFacts } from "../resolution/index.js";
|
|
|
2
2
|
import { createPlainSink } from "./output.js";
|
|
3
3
|
import type { DoctorSeams, Finding, ResolutionSummary } from "./types.js";
|
|
4
4
|
export declare function cmdDoctor(args: readonly string[], seams?: DoctorSeams): number;
|
|
5
|
-
export declare function runAgentHooksHealthCheck(projectRoot: string, consumerContext: boolean, sink: ReturnType<typeof createPlainSink>, addFinding: (finding: Finding) => void, seams: DoctorSeams):
|
|
5
|
+
export declare function runAgentHooksHealthCheck(projectRoot: string, consumerContext: boolean, sink: ReturnType<typeof createPlainSink>, addFinding: (finding: Finding) => void, seams: DoctorSeams): boolean;
|
|
6
|
+
export declare function runAgentHooksLiveProbeCheck(projectRoot: string, sink: ReturnType<typeof createPlainSink>, addFinding: (finding: Finding) => void, seams: DoctorSeams): void;
|
|
6
7
|
/**
|
|
7
8
|
* Never emit a bare `task ...` remediation in a project without Taskfile wiring
|
|
8
9
|
* (#2267). The `directive` surface always works; `task deft:X` is optional and
|
package/dist/doctor/main.js
CHANGED
|
@@ -7,6 +7,7 @@ import { loadProjectDefinition } from "../policy/resolve.js";
|
|
|
7
7
|
import { checkLocalEngineIntegrity, classify, detectPackageManager, evaluateSkew, reconcileVersions, plan as resolvePlan, } from "../resolution/index.js";
|
|
8
8
|
import { resolveUserMdPath } from "../user-config/resolve-user-md.js";
|
|
9
9
|
import { evaluateAgentHooks } from "../verify-env/agent-hooks.js";
|
|
10
|
+
import { probeAgentHooksLive } from "../verify-env/agent-hooks-live-probe.js";
|
|
10
11
|
import { agentsRefreshPlan, hasV3ManagedMarker } from "./agents-md.js";
|
|
11
12
|
import { runChecks } from "./checks.js";
|
|
12
13
|
import { CONSUMER_FRAMEWORK_DIRS, EXPECTED_CONTENT_DIRS, EXPECTED_FRAMEWORK_DIRS, NETWORK_DISCLOSURE_LINE, PAYLOAD_STALENESS_OFFLINE_SKIP_MESSAGE, TASKFILE_INCLUDE_SNIPPET, UV_INSTALL_URL, } from "./constants.js";
|
|
@@ -16,7 +17,7 @@ import { pythonJsonDump } from "./json.js";
|
|
|
16
17
|
import { parseInstallRootFromAgentsMd } from "./manifest.js";
|
|
17
18
|
import { runNpmRegistryMirrorCheck } from "./npm-registry.js";
|
|
18
19
|
import { createPlainSink } from "./output.js";
|
|
19
|
-
import { readTextSafe,
|
|
20
|
+
import { readTextSafe, resolveFrameworkRootForProject, resolvePath, resolveVersion, runningInsideDeftRepo, } from "./paths.js";
|
|
20
21
|
import { runPayloadStalenessCheck } from "./payload-staleness.js";
|
|
21
22
|
import { runLocalSignpostChecks } from "./signpost-checks.js";
|
|
22
23
|
import { classifyTaskfileInclude, formatMissingIncludeSnippet, includesBlockHasDeftTaskfile, resolveConsumerTaskfile, } from "./taskfile.js";
|
|
@@ -57,7 +58,7 @@ export function cmdDoctor(args, seams = {}) {
|
|
|
57
58
|
const quietMode = flags.quiet;
|
|
58
59
|
const fullMode = flags.full;
|
|
59
60
|
const projectRoot = resolvePath(flags.projectRoot ?? process.cwd());
|
|
60
|
-
const frameworkRoot = seams.frameworkRoot ??
|
|
61
|
+
const frameworkRoot = seams.frameworkRoot ?? resolveFrameworkRootForProject(projectRoot);
|
|
61
62
|
const consumerContext = resolve(projectRoot) !== resolve(frameworkRoot);
|
|
62
63
|
const whichFn = seams.whichFn ?? defaultWhich;
|
|
63
64
|
const nowFn = seams.now ?? (() => new Date());
|
|
@@ -165,7 +166,17 @@ export function cmdDoctor(args, seams = {}) {
|
|
|
165
166
|
sink.blank();
|
|
166
167
|
}
|
|
167
168
|
sink.info("Checking agent-host hook registration...");
|
|
168
|
-
|
|
169
|
+
const findingCountBeforeHooks = findings.length;
|
|
170
|
+
const hooksHealthy = runAgentHooksHealthCheck(projectRoot, consumerContext, sink, addFinding, seams);
|
|
171
|
+
if (fullMode && hooksHealthy) {
|
|
172
|
+
const lastFinding = findings[findings.length - 1];
|
|
173
|
+
if (findings.length > findingCountBeforeHooks &&
|
|
174
|
+
lastFinding?.check === "agent-hooks-registration" &&
|
|
175
|
+
lastFinding?.status === "registered") {
|
|
176
|
+
findings.pop();
|
|
177
|
+
}
|
|
178
|
+
runAgentHooksLiveProbeCheck(projectRoot, sink, addFinding, seams);
|
|
179
|
+
}
|
|
169
180
|
if (consumerContext) {
|
|
170
181
|
if (!jsonMode) {
|
|
171
182
|
sink.blank();
|
|
@@ -353,40 +364,81 @@ export function runAgentHooksHealthCheck(projectRoot, consumerContext, sink, add
|
|
|
353
364
|
const reason = "maintainer source checkout; project hook deposit is consumer-only";
|
|
354
365
|
sink.info(`${checkName}: skip -- ${reason}`);
|
|
355
366
|
addFinding({ severity: "skip", message: reason, check: checkName, status: "skip" });
|
|
356
|
-
return;
|
|
367
|
+
return false;
|
|
357
368
|
}
|
|
358
369
|
try {
|
|
359
370
|
const result = (seams.evaluateAgentHooks ?? evaluateAgentHooks)(projectRoot);
|
|
360
|
-
if (result.code
|
|
361
|
-
const message = `${checkName}:
|
|
362
|
-
|
|
363
|
-
sink.success(message);
|
|
371
|
+
if (result.code !== 0) {
|
|
372
|
+
const message = `${checkName}: ${result.message.replace(/\s+/g, " ").trim()}`;
|
|
373
|
+
sink.warn(message);
|
|
364
374
|
addFinding({
|
|
365
|
-
severity: "
|
|
375
|
+
severity: "warning",
|
|
366
376
|
message,
|
|
367
377
|
check: checkName,
|
|
368
|
-
status: "
|
|
378
|
+
status: result.code === 2 ? "unavailable" : "incomplete",
|
|
369
379
|
registrations: result.registrations,
|
|
370
|
-
|
|
371
|
-
trust_review: "Open `/hooks` in Codex and review the project hook commands.",
|
|
380
|
+
suggestion: "deft update",
|
|
372
381
|
});
|
|
373
|
-
return;
|
|
382
|
+
return false;
|
|
374
383
|
}
|
|
375
|
-
const message = `${checkName}:
|
|
376
|
-
|
|
384
|
+
const message = `${checkName}: registered and structurally valid; ` +
|
|
385
|
+
"Codex runtime trust is user-controlled and must be reviewed with `/hooks`";
|
|
386
|
+
sink.success(message);
|
|
377
387
|
addFinding({
|
|
378
|
-
severity: "
|
|
388
|
+
severity: "skip",
|
|
379
389
|
message,
|
|
380
390
|
check: checkName,
|
|
381
|
-
status:
|
|
391
|
+
status: "registered",
|
|
382
392
|
registrations: result.registrations,
|
|
383
|
-
|
|
393
|
+
trust_status: "not-verifiable",
|
|
394
|
+
trust_review: "Open `/hooks` in Codex and review the project hook commands.",
|
|
384
395
|
});
|
|
396
|
+
return true;
|
|
385
397
|
}
|
|
386
398
|
catch (cause) {
|
|
387
399
|
const message = `${checkName}: probe failed -- ${String(cause)}`;
|
|
388
400
|
sink.warn(message);
|
|
389
401
|
addFinding({ severity: "warning", message, check: checkName, suggestion: "deft update" });
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
export function runAgentHooksLiveProbeCheck(projectRoot, sink, addFinding, seams) {
|
|
406
|
+
const checkName = "agent-hooks-registration";
|
|
407
|
+
const liveCheckName = "agent-hooks-live-probe";
|
|
408
|
+
try {
|
|
409
|
+
const result = (seams.evaluateAgentHooks ?? evaluateAgentHooks)(projectRoot);
|
|
410
|
+
const liveResult = (seams.probeAgentHooksLive ?? probeAgentHooksLive)(projectRoot);
|
|
411
|
+
if (liveResult.code !== 0) {
|
|
412
|
+
const message = `${liveCheckName}: ${liveResult.message.replace(/\s+/g, " ").trim()}`;
|
|
413
|
+
sink.warn(message);
|
|
414
|
+
addFinding({
|
|
415
|
+
severity: "warning",
|
|
416
|
+
message,
|
|
417
|
+
check: liveCheckName,
|
|
418
|
+
status: liveResult.code === 2 ? "unavailable" : "non-functional",
|
|
419
|
+
cases: liveResult.cases,
|
|
420
|
+
suggestion: "npm i -g @deftai/directive@latest && deft update",
|
|
421
|
+
});
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const message = `${checkName}: registered, structurally valid, and live probe passed; ` +
|
|
425
|
+
"Codex runtime trust is user-controlled and must be reviewed with `/hooks`";
|
|
426
|
+
sink.success(message);
|
|
427
|
+
addFinding({
|
|
428
|
+
severity: "skip",
|
|
429
|
+
message,
|
|
430
|
+
check: liveCheckName,
|
|
431
|
+
status: "registered-and-functional",
|
|
432
|
+
registrations: result.registrations,
|
|
433
|
+
trust_status: "not-verifiable",
|
|
434
|
+
trust_review: "Open `/hooks` in Codex and review the project hook commands.",
|
|
435
|
+
live_probe: "passed",
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
catch (cause) {
|
|
439
|
+
const message = `${liveCheckName}: probe failed -- ${String(cause)}`;
|
|
440
|
+
sink.warn(message);
|
|
441
|
+
addFinding({ severity: "warning", message, check: liveCheckName, suggestion: "deft update" });
|
|
390
442
|
}
|
|
391
443
|
}
|
|
392
444
|
function runInstallIntegrityChecks(projectRoot, sink, addFinding, seams) {
|
package/dist/doctor/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { EngineProbeResult } from "../resolution/classify.js";
|
|
|
4
4
|
import type { ResolutionMode } from "../resolution/index.js";
|
|
5
5
|
import type { ResolveUserMdResult } from "../user-config/resolve-user-md.js";
|
|
6
6
|
import type { AgentHookHealthResult } from "../verify-env/agent-hooks.js";
|
|
7
|
+
import type { AgentHookLiveProbeResult } from "../verify-env/agent-hooks-live-probe.js";
|
|
7
8
|
export declare const EXIT_CLEAN = 0;
|
|
8
9
|
export declare const EXIT_DRIFT = 1;
|
|
9
10
|
export declare const EXIT_CONFIG_ERROR = 2;
|
|
@@ -147,5 +148,7 @@ export interface DoctorSeams {
|
|
|
147
148
|
readonly detectPlanExtensionShadows?: (projectRoot: string) => readonly ShadowedPlanExtension[];
|
|
148
149
|
/** Read-only agent-host hook registration probe (#2438). */
|
|
149
150
|
readonly evaluateAgentHooks?: (projectRoot: string) => AgentHookHealthResult;
|
|
151
|
+
/** Live hook spawn probe for doctor --full (#2852). */
|
|
152
|
+
readonly probeAgentHooksLive?: (projectRoot: string) => AgentHookLiveProbeResult;
|
|
150
153
|
}
|
|
151
154
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -238,14 +238,22 @@ export function writeAgentHookDeposit(projectRoot, io = { printf: () => undefine
|
|
|
238
238
|
changedPaths.push(item.path);
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
241
|
+
const legacyAdapterPaths = [
|
|
242
|
+
".cursor/hooks/deft-cursor-hook-adapter.mjs",
|
|
243
|
+
".cursor/hooks/deft-cursor-hook-adapter.test.mjs",
|
|
244
|
+
];
|
|
245
|
+
let removedLegacyAdapter = false;
|
|
246
|
+
for (const relative of legacyAdapterPaths) {
|
|
247
|
+
const absolute = join(projectRoot, relative);
|
|
248
|
+
assertDepositContained(projectRoot, absolute);
|
|
249
|
+
if (existsSync(absolute)) {
|
|
250
|
+
rmSync(absolute, { force: true });
|
|
251
|
+
removedLegacyAdapter = true;
|
|
247
252
|
}
|
|
248
253
|
}
|
|
254
|
+
if (removedLegacyAdapter && !changedPaths.includes(AGENT_HOOK_PATHS[2])) {
|
|
255
|
+
changedPaths.push(AGENT_HOOK_PATHS[2]);
|
|
256
|
+
}
|
|
249
257
|
if (changedPaths.length > 0) {
|
|
250
258
|
io.printf(`Installed Directive agent hooks: ${changedPaths.join(", ")}\n`);
|
|
251
259
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { execFileSync } from "node:child_process";
|
|
12
12
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
|
+
import { assertWriteTargetSafe, ProjectionContainmentError } from "../fs/projection-containment.js";
|
|
14
15
|
import { FORBIDDEN_BLANKET_EVAL_LINES, stripGitignoreInlineComment, } from "../triage/bootstrap/gitignore.js";
|
|
15
16
|
/** Directory ignore entry for the hybrid deposit (greenfield only). */
|
|
16
17
|
export const GITIGNORE_DEFT_CORE_LINE = ".deft/core/";
|
|
@@ -195,9 +196,13 @@ function reconcileGitignoreFile(projectDir, targetLines, includeDeftCoreRational
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
try {
|
|
199
|
+
assertWriteTargetSafe(projectDir, path);
|
|
198
200
|
writeFileSync(path, body, { encoding: "utf8", mode: 0o644 });
|
|
199
201
|
}
|
|
200
202
|
catch (cause) {
|
|
203
|
+
if (cause instanceof ProjectionContainmentError) {
|
|
204
|
+
throw cause;
|
|
205
|
+
}
|
|
201
206
|
throw new Error(`could not write .gitignore: ${String(cause)}`);
|
|
202
207
|
}
|
|
203
208
|
const finalPresent = collectPresentGitignoreLines(body);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { readCorePackageVersion } from "../engine-version.js";
|
|
4
|
+
import { assertWriteTargetSafe } from "../fs/projection-containment.js";
|
|
4
5
|
import { atomicWriteProjectDefinition, projectDefinitionMutationLock, } from "../vbrief-build/project-definition-io.js";
|
|
5
6
|
import { migrateLegacyPolicyKey, PLAN_POLICY_KEY, readPlanPolicy } from "./plan-extensions.js";
|
|
6
7
|
import { appendAuditLog, loadProjectDefinition, projectDefinitionPath } from "./resolve.js";
|
|
@@ -56,6 +57,7 @@ export function readOrgForceOnMarker(projectRoot) {
|
|
|
56
57
|
}
|
|
57
58
|
function writeOrgForceOnMarker(projectRoot, marker) {
|
|
58
59
|
const path = markerPath(projectRoot);
|
|
60
|
+
assertWriteTargetSafe(projectRoot, path);
|
|
59
61
|
mkdirSync(join(path, ".."), { recursive: true });
|
|
60
62
|
writeFileSync(path, `${JSON.stringify(marker, null, 2)}\n`, "utf8");
|
|
61
63
|
}
|
|
@@ -25,7 +25,7 @@ export declare function formatFrameworkCommand(args: readonly string[], options?
|
|
|
25
25
|
surface?: string;
|
|
26
26
|
taskPrefix?: string | null;
|
|
27
27
|
}): string;
|
|
28
|
-
export declare function cmdCoreValidate(argv: readonly string[]): number;
|
|
28
|
+
export declare function cmdCoreValidate(argv: readonly string[], root?: string): number;
|
|
29
29
|
export declare function cmdCoreLint(_argv: readonly string[]): number;
|
|
30
30
|
export declare function cmdCoreTest(_argv: readonly string[]): number;
|
|
31
31
|
export declare function resolveFrameworkRoot(): string;
|
|
@@ -154,7 +154,7 @@ export function formatFrameworkCommand(args, options = {}) {
|
|
|
154
154
|
}
|
|
155
155
|
return [surface, ...parts].join(" ");
|
|
156
156
|
}
|
|
157
|
-
const EXCLUDE_PARTS = new Set([".git", "backup"]);
|
|
157
|
+
const EXCLUDE_PARTS = new Set([".git", "backup", "node_modules", ".deft-scratch"]);
|
|
158
158
|
function collectMarkdownFiles(root) {
|
|
159
159
|
const out = [];
|
|
160
160
|
const walk = (dir, parts) => {
|
|
@@ -189,12 +189,12 @@ function collectMarkdownFiles(root) {
|
|
|
189
189
|
walk(root, []);
|
|
190
190
|
return out.sort();
|
|
191
191
|
}
|
|
192
|
-
export function cmdCoreValidate(argv) {
|
|
192
|
+
export function cmdCoreValidate(argv, root = ".") {
|
|
193
193
|
if (argv.length > 0) {
|
|
194
194
|
process.stderr.write(`error: core:validate does not accept arguments: ${argv.join(" ")}\n`);
|
|
195
195
|
return 2;
|
|
196
196
|
}
|
|
197
|
-
const files = collectMarkdownFiles(
|
|
197
|
+
const files = collectMarkdownFiles(root);
|
|
198
198
|
for (const path of files)
|
|
199
199
|
process.stdout.write(`✓ ${path}\n`);
|
|
200
200
|
process.stdout.write(`✓ All ${files.length} markdown files validated\n`);
|
|
@@ -271,7 +271,7 @@ function runBuildDistArgv(argv) {
|
|
|
271
271
|
return result.status ?? 1;
|
|
272
272
|
}
|
|
273
273
|
const TS_INLINE = {
|
|
274
|
-
"framework_commands:_cmd_core_validate": (argv) => cmdCoreValidate(argv),
|
|
274
|
+
"framework_commands:_cmd_core_validate": (argv, cwd) => cmdCoreValidate(argv, cwd),
|
|
275
275
|
"doctor:cmd_doctor": (argv) => cmdDoctor(argv),
|
|
276
276
|
"build_dist:main": (argv) => runBuildDistArgv(argv),
|
|
277
277
|
};
|
|
@@ -349,7 +349,7 @@ function invokeEntrypoint(entrypoint, argv, cwd, frameworkRoot, noArgv, capture)
|
|
|
349
349
|
};
|
|
350
350
|
let code;
|
|
351
351
|
try {
|
|
352
|
-
code = inline(argv);
|
|
352
|
+
code = inline(argv, cwd);
|
|
353
353
|
}
|
|
354
354
|
finally {
|
|
355
355
|
process.stdout.write = prevOut;
|
|
@@ -357,7 +357,7 @@ function invokeEntrypoint(entrypoint, argv, cwd, frameworkRoot, noArgv, capture)
|
|
|
357
357
|
}
|
|
358
358
|
return { code, stdout: chunks.out, stderr: chunks.err };
|
|
359
359
|
}
|
|
360
|
-
return { code: inline(argv), stdout: "", stderr: "" };
|
|
360
|
+
return { code: inline(argv, cwd), stdout: "", stderr: "" };
|
|
361
361
|
}
|
|
362
362
|
const verb = ENTRYPOINT_VERB[entrypoint];
|
|
363
363
|
if (verb) {
|
|
@@ -3,7 +3,11 @@ export declare function renderRoadmapToBuffer(pendingDir: string, completedDir?:
|
|
|
3
3
|
/** @deprecated Prefer ``renderRoadmapToBuffer`` — kept for existing imports and parity harnesses. */
|
|
4
4
|
export declare function generateRoadmapContent(pendingDir: string, completedDir?: string): string;
|
|
5
5
|
export type RenderRoadmapResult = readonly [boolean, string];
|
|
6
|
-
export
|
|
6
|
+
export type RenderRoadmapOptions = {
|
|
7
|
+
completedDir?: string;
|
|
8
|
+
projectRoot?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function renderRoadmap(pendingDir: string, outPath: string, completedDirOrOptions?: string | RenderRoadmapOptions): RenderRoadmapResult;
|
|
7
11
|
export declare function checkDrift(pendingDir: string, roadmapPath: string, completedDir?: string): RenderRoadmapResult;
|
|
8
12
|
/** CLI entry (mirrors ``scripts/roadmap_render.main``). */
|
|
9
13
|
export declare function main(argv: readonly string[]): number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { assertWriteTargetSafe } from "../fs/projection-containment.js";
|
|
3
4
|
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
5
|
import { MIGRATOR_METADATA_KEY, ROADMAP_BANNER } from "./constants.js";
|
|
5
6
|
import { phaseSortKey } from "./text-utils.js";
|
|
@@ -351,9 +352,22 @@ export function renderRoadmapToBuffer(pendingDir, completedDir) {
|
|
|
351
352
|
export function generateRoadmapContent(pendingDir, completedDir) {
|
|
352
353
|
return renderRoadmapToBuffer(pendingDir, completedDir);
|
|
353
354
|
}
|
|
354
|
-
export function renderRoadmap(pendingDir, outPath,
|
|
355
|
+
export function renderRoadmap(pendingDir, outPath, completedDirOrOptions) {
|
|
356
|
+
let completedDir;
|
|
357
|
+
let projectRoot;
|
|
358
|
+
if (typeof completedDirOrOptions === "string") {
|
|
359
|
+
completedDir = completedDirOrOptions;
|
|
360
|
+
}
|
|
361
|
+
else if (completedDirOrOptions !== undefined) {
|
|
362
|
+
completedDir = completedDirOrOptions.completedDir;
|
|
363
|
+
projectRoot = completedDirOrOptions.projectRoot;
|
|
364
|
+
}
|
|
355
365
|
try {
|
|
356
366
|
const content = renderRoadmapToBuffer(pendingDir, completedDir);
|
|
367
|
+
// Trust boundary is the project root — never dirname(outPath), which follows a
|
|
368
|
+
// diverted parent symlink and would make containment pass outside the checkout.
|
|
369
|
+
const projectDir = projectRoot !== undefined ? resolve(projectRoot) : resolve(pendingDir, "..", "..");
|
|
370
|
+
assertWriteTargetSafe(projectDir, resolve(outPath));
|
|
357
371
|
writeFileSync(outPath, content, "utf8");
|
|
358
372
|
return [true, `✓ Rendered ROADMAP.md to ${outPath}`];
|
|
359
373
|
}
|
|
@@ -415,7 +429,11 @@ export function main(argv) {
|
|
|
415
429
|
process.stdout.write(`${msg}\n`);
|
|
416
430
|
return ok ? 0 : 1;
|
|
417
431
|
}
|
|
418
|
-
|
|
432
|
+
// When --project-root is set, use it; otherwise renderRoadmap derives from pendingDir
|
|
433
|
+
// (…/xbrief|vbrief/pending → project root). Never use dirname(outPath).
|
|
434
|
+
const [ok, msg] = renderRoadmap(pendingDir, outPath, {
|
|
435
|
+
projectRoot: projectRoot !== undefined ? resolve(projectRoot) : undefined,
|
|
436
|
+
});
|
|
419
437
|
process.stdout.write(`${msg}\n`);
|
|
420
438
|
return ok ? 0 : 1;
|
|
421
439
|
}
|
package/dist/render/rule-map.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { assertWriteTargetSafe } from "../fs/projection-containment.js";
|
|
16
17
|
import { TEMPLATE } from "./rule-map-template.js";
|
|
17
18
|
const MARKER_RE = /^\s*[-*]\s*([!~⊗≉?])\s/;
|
|
18
19
|
const MARKER_LABEL = {
|
|
@@ -684,6 +685,10 @@ export function main(argv) {
|
|
|
684
685
|
process.stdout.write("ok: docs/RULE-MAP.md is up to date\n");
|
|
685
686
|
return 0;
|
|
686
687
|
}
|
|
688
|
+
// Preflight both destinations before either write so a later HTML refusal
|
|
689
|
+
// cannot leave RULE-MAP.md updated while docs/rule-map/index.html stays stale.
|
|
690
|
+
assertWriteTargetSafe(repo, mdPath);
|
|
691
|
+
assertWriteTargetSafe(repo, htmlPath);
|
|
687
692
|
mkdirSync(dirname(mdPath), { recursive: true });
|
|
688
693
|
writeFileSync(mdPath, md, "utf8");
|
|
689
694
|
mkdirSync(htmlDir, { recursive: true });
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HookEvent, HookHost } from "../hooks/dispatcher.js";
|
|
2
|
+
export type AgentHookLiveProbeIssue = "hook-command-missing" | "spawn-failed" | "empty-stdout" | "unparseable-json" | "missing-allow" | "missing-deny";
|
|
3
|
+
export interface AgentHookLiveProbeCase {
|
|
4
|
+
readonly host: HookHost;
|
|
5
|
+
readonly event: HookEvent;
|
|
6
|
+
readonly fixture: "allow" | "deny";
|
|
7
|
+
readonly issue: AgentHookLiveProbeIssue;
|
|
8
|
+
readonly detail: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AgentHookLiveProbeResult {
|
|
11
|
+
readonly code: 0 | 1 | 2;
|
|
12
|
+
readonly message: string;
|
|
13
|
+
readonly cases: readonly AgentHookLiveProbeCase[];
|
|
14
|
+
}
|
|
15
|
+
export interface AgentHookLiveProbeSeams {
|
|
16
|
+
readonly resolveCommand?: (name: string) => string | null;
|
|
17
|
+
readonly spawnHook?: (input: {
|
|
18
|
+
readonly command: string;
|
|
19
|
+
readonly args: readonly string[];
|
|
20
|
+
readonly stdin: string;
|
|
21
|
+
readonly cwd: string;
|
|
22
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
23
|
+
}) => {
|
|
24
|
+
readonly status: number;
|
|
25
|
+
readonly stdout: string;
|
|
26
|
+
readonly stderr: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function quoteWindowsCmdArg(value: string): string;
|
|
30
|
+
/** Spawn the configured hook command and assert Cursor tool.before allow/deny behavior. */
|
|
31
|
+
export declare function probeAgentHooksLive(projectRoot: string, seams?: AgentHookLiveProbeSeams): AgentHookLiveProbeResult;
|
|
32
|
+
//# sourceMappingURL=agent-hooks-live-probe.d.ts.map
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { READ_ONLY_HOOK_ENV } from "../hooks/tools.js";
|
|
4
|
+
import { DEFT_HOOK_COMMAND_MARKER } from "../init-deposit/agent-hooks.js";
|
|
5
|
+
import { SUBPROCESS_MAX_BUFFER } from "../subprocess/max-buffer.js";
|
|
6
|
+
import { quoteWin32CommandForShell, resolveCommandOnPath, shouldUseShellForCommand, } from "./command-spawn.js";
|
|
7
|
+
const LIVE_PROBE_HOST = "cursor";
|
|
8
|
+
const LIVE_PROBE_EVENT = "tool.before";
|
|
9
|
+
function resolveHookCommand(seams) {
|
|
10
|
+
const resolveCommand = seams.resolveCommand ?? resolveCommandOnPath;
|
|
11
|
+
const deftHook = resolveCommand(DEFT_HOOK_COMMAND_MARKER);
|
|
12
|
+
if (deftHook !== null) {
|
|
13
|
+
return { command: deftHook, argsPrefix: [] };
|
|
14
|
+
}
|
|
15
|
+
const deft = resolveCommand("deft");
|
|
16
|
+
if (deft !== null) {
|
|
17
|
+
return { command: deft, argsPrefix: ["hook:dispatch"] };
|
|
18
|
+
}
|
|
19
|
+
const directive = resolveCommand("directive");
|
|
20
|
+
if (directive !== null) {
|
|
21
|
+
return { command: directive, argsPrefix: ["hook:dispatch"] };
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
export function quoteWindowsCmdArg(value) {
|
|
26
|
+
const escaped = value.replace(/%/g, "%%");
|
|
27
|
+
if (!/[\s"&|<>^()]/.test(escaped)) {
|
|
28
|
+
return escaped;
|
|
29
|
+
}
|
|
30
|
+
return `"${escaped.replace(/"/g, '""')}"`;
|
|
31
|
+
}
|
|
32
|
+
function spawnHookWithStdin(command, args, stdin, cwd, env = process.env) {
|
|
33
|
+
const shell = shouldUseShellForCommand(command);
|
|
34
|
+
if (shell && process.platform === "win32") {
|
|
35
|
+
const cmdLine = [quoteWin32CommandForShell(command), ...args.map(quoteWindowsCmdArg)].join(" ");
|
|
36
|
+
const proc = spawnSync(cmdLine, [], {
|
|
37
|
+
input: stdin,
|
|
38
|
+
cwd,
|
|
39
|
+
env,
|
|
40
|
+
encoding: "utf8",
|
|
41
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
42
|
+
shell: true,
|
|
43
|
+
windowsHide: true,
|
|
44
|
+
maxBuffer: SUBPROCESS_MAX_BUFFER,
|
|
45
|
+
});
|
|
46
|
+
const status = proc.status ?? (proc.error ? 2 : proc.signal ? 128 : 0);
|
|
47
|
+
return {
|
|
48
|
+
status,
|
|
49
|
+
stdout: typeof proc.stdout === "string" ? proc.stdout : "",
|
|
50
|
+
stderr: typeof proc.stderr === "string" ? proc.stderr : "",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const spawnCmd = shell && process.platform === "win32" ? quoteWin32CommandForShell(command) : command;
|
|
54
|
+
const proc = spawnSync(spawnCmd, [...args], {
|
|
55
|
+
input: stdin,
|
|
56
|
+
cwd,
|
|
57
|
+
env,
|
|
58
|
+
encoding: "utf8",
|
|
59
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
60
|
+
shell,
|
|
61
|
+
windowsHide: true,
|
|
62
|
+
maxBuffer: SUBPROCESS_MAX_BUFFER,
|
|
63
|
+
});
|
|
64
|
+
const status = proc.status ?? (proc.error ? 2 : proc.signal ? 128 : 0);
|
|
65
|
+
return {
|
|
66
|
+
status,
|
|
67
|
+
stdout: typeof proc.stdout === "string" ? proc.stdout : "",
|
|
68
|
+
stderr: typeof proc.stderr === "string" ? proc.stderr : "",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function allowFixture(projectRoot) {
|
|
72
|
+
return JSON.stringify({
|
|
73
|
+
tool_name: "Read",
|
|
74
|
+
cwd: projectRoot,
|
|
75
|
+
workspace_roots: [projectRoot],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function denyFixture(projectRoot) {
|
|
79
|
+
return JSON.stringify({
|
|
80
|
+
tool_name: "Task",
|
|
81
|
+
cwd: projectRoot,
|
|
82
|
+
workspace_roots: [projectRoot],
|
|
83
|
+
tool_input: { subagent_type: "generalPurpose", prompt: "implement" },
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function denyProbeEnv() {
|
|
87
|
+
return { ...process.env, [READ_ONLY_HOOK_ENV]: "1" };
|
|
88
|
+
}
|
|
89
|
+
function parseCursorDecision(stdout) {
|
|
90
|
+
const trimmed = stdout.trim();
|
|
91
|
+
if (trimmed.length === 0) {
|
|
92
|
+
return { ok: false, detail: "empty stdout" };
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(trimmed);
|
|
96
|
+
if (parsed !== null &&
|
|
97
|
+
typeof parsed === "object" &&
|
|
98
|
+
!Array.isArray(parsed) &&
|
|
99
|
+
parsed.permission === "allow") {
|
|
100
|
+
return { ok: true, permission: "allow", detail: "permission allow" };
|
|
101
|
+
}
|
|
102
|
+
if (parsed !== null &&
|
|
103
|
+
typeof parsed === "object" &&
|
|
104
|
+
!Array.isArray(parsed) &&
|
|
105
|
+
parsed.permission === "deny") {
|
|
106
|
+
return { ok: true, permission: "deny", detail: "permission deny" };
|
|
107
|
+
}
|
|
108
|
+
return { ok: false, detail: "stdout JSON missing permission allow/deny" };
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return { ok: false, detail: "stdout is not valid JSON" };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function runFixtureProbe(resolved, projectRoot, fixture, stdin, env, spawnHook) {
|
|
115
|
+
const args = [
|
|
116
|
+
...resolved.argsPrefix,
|
|
117
|
+
"--host",
|
|
118
|
+
LIVE_PROBE_HOST,
|
|
119
|
+
"--event",
|
|
120
|
+
LIVE_PROBE_EVENT,
|
|
121
|
+
"--project-root",
|
|
122
|
+
projectRoot,
|
|
123
|
+
];
|
|
124
|
+
const spawned = spawnHook({
|
|
125
|
+
command: resolved.command,
|
|
126
|
+
args,
|
|
127
|
+
stdin,
|
|
128
|
+
cwd: projectRoot,
|
|
129
|
+
env,
|
|
130
|
+
});
|
|
131
|
+
if (spawned.status !== 0) {
|
|
132
|
+
return {
|
|
133
|
+
host: LIVE_PROBE_HOST,
|
|
134
|
+
event: LIVE_PROBE_EVENT,
|
|
135
|
+
fixture,
|
|
136
|
+
issue: "spawn-failed",
|
|
137
|
+
detail: `hook command exited ${spawned.status}${spawned.stderr.trim() ? `: ${spawned.stderr.trim()}` : ""}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const decision = parseCursorDecision(spawned.stdout);
|
|
141
|
+
if (!decision.ok) {
|
|
142
|
+
return {
|
|
143
|
+
host: LIVE_PROBE_HOST,
|
|
144
|
+
event: LIVE_PROBE_EVENT,
|
|
145
|
+
fixture,
|
|
146
|
+
issue: decision.detail.includes("JSON") ? "unparseable-json" : "empty-stdout",
|
|
147
|
+
detail: decision.detail,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (fixture === "allow" && decision.permission !== "allow") {
|
|
151
|
+
return {
|
|
152
|
+
host: LIVE_PROBE_HOST,
|
|
153
|
+
event: LIVE_PROBE_EVENT,
|
|
154
|
+
fixture,
|
|
155
|
+
issue: "missing-allow",
|
|
156
|
+
detail: `expected permission allow, got ${decision.permission ?? "none"}`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (fixture === "deny" && decision.permission !== "deny") {
|
|
160
|
+
return {
|
|
161
|
+
host: LIVE_PROBE_HOST,
|
|
162
|
+
event: LIVE_PROBE_EVENT,
|
|
163
|
+
fixture,
|
|
164
|
+
issue: "missing-deny",
|
|
165
|
+
detail: `expected permission deny, got ${decision.permission ?? "none"}`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
/** Spawn the configured hook command and assert Cursor tool.before allow/deny behavior. */
|
|
171
|
+
export function probeAgentHooksLive(projectRoot, seams = {}) {
|
|
172
|
+
const root = resolve(projectRoot);
|
|
173
|
+
const resolved = resolveHookCommand(seams);
|
|
174
|
+
if (resolved === null) {
|
|
175
|
+
return {
|
|
176
|
+
code: 2,
|
|
177
|
+
message: "deft agent hooks live probe unavailable: neither deft-hook nor deft/directive hook:dispatch is on PATH.",
|
|
178
|
+
cases: [
|
|
179
|
+
{
|
|
180
|
+
host: LIVE_PROBE_HOST,
|
|
181
|
+
event: LIVE_PROBE_EVENT,
|
|
182
|
+
fixture: "allow",
|
|
183
|
+
issue: "hook-command-missing",
|
|
184
|
+
detail: `${DEFT_HOOK_COMMAND_MARKER} not found on PATH`,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const spawnHook = seams.spawnHook ??
|
|
190
|
+
((input) => spawnHookWithStdin(input.command, input.args, input.stdin, input.cwd, input.env ?? process.env));
|
|
191
|
+
const failures = [];
|
|
192
|
+
for (const [fixture, stdin, env] of [
|
|
193
|
+
["allow", allowFixture(root), process.env],
|
|
194
|
+
["deny", denyFixture(root), denyProbeEnv()],
|
|
195
|
+
]) {
|
|
196
|
+
const failure = runFixtureProbe(resolved, root, fixture, stdin, env, spawnHook);
|
|
197
|
+
if (failure !== null)
|
|
198
|
+
failures.push(failure);
|
|
199
|
+
}
|
|
200
|
+
if (failures.length === 0) {
|
|
201
|
+
return {
|
|
202
|
+
code: 0,
|
|
203
|
+
message: "deft agent hooks live probe passed for Cursor tool.before allow and deny fixtures.",
|
|
204
|
+
cases: [],
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const summary = failures
|
|
208
|
+
.map((entry) => `${entry.fixture}: ${entry.issue} (${entry.detail})`)
|
|
209
|
+
.join("; ");
|
|
210
|
+
return {
|
|
211
|
+
code: 1,
|
|
212
|
+
message: `deft agent hooks live probe FAILED: ${summary}. Recovery: reinstall @deftai/directive and run \`deft update\`.`,
|
|
213
|
+
cases: failures,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=agent-hooks-live-probe.js.map
|
package/dist/verify-env/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { dirname, join, relative, resolve } from "node:path";
|
|
3
|
+
import { assertWriteTargetSafe, ProjectionContainmentError } from "../fs/projection-containment.js";
|
|
3
4
|
import { checkGitClean } from "../migrate-preflight/index.js";
|
|
4
|
-
import {
|
|
5
|
+
import { applyAgentsRefresh } from "../platform/agents-md.js";
|
|
5
6
|
import { patchAgentsMdHeader, renderHeaderPatchSummary } from "./agents-header.js";
|
|
6
7
|
import { LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, OBSOLETE_FRAMEWORK_NARRATIVE_FILENAME, VBRIEF_DEPRECATION_MARKER_BODY, VBRIEF_DEPRECATION_MARKER_FILENAME, } from "./constants.js";
|
|
7
8
|
import { detectLegacyVbriefLayout, detectXbriefConvergence } from "./detect.js";
|
|
@@ -157,25 +158,33 @@ function renameOrReplace(src, dest) {
|
|
|
157
158
|
rmSync(src, { recursive: true, force: true });
|
|
158
159
|
}
|
|
159
160
|
function runAgentsRefresh(projectRoot, frameworkRoot, io) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
try {
|
|
162
|
+
assertWriteTargetSafe(projectRoot, join(projectRoot, "AGENTS.md"));
|
|
163
|
+
const { state, wrote, writable } = applyAgentsRefresh(projectRoot, {}, { frameworkRoot });
|
|
164
|
+
if (state === "current") {
|
|
165
|
+
io.writeOut("AGENTS.md managed section is current — no changes.\n");
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
if (state === "template-missing" || state === "template-malformed" || state === "unreadable") {
|
|
169
|
+
io.writeErr(`agents:refresh failed: ${state}\n`);
|
|
170
|
+
return 2;
|
|
171
|
+
}
|
|
172
|
+
if (!writable) {
|
|
173
|
+
io.writeErr("agents:refresh failed: plan produced no new_content\n");
|
|
174
|
+
return 2;
|
|
175
|
+
}
|
|
176
|
+
if (wrote) {
|
|
177
|
+
io.writeOut(`AGENTS.md updated (state=${state}).\n`);
|
|
178
|
+
}
|
|
164
179
|
return 0;
|
|
165
180
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
io.writeErr("agents:refresh failed: plan produced no new_content\n");
|
|
173
|
-
return 2;
|
|
181
|
+
catch (err) {
|
|
182
|
+
if (err instanceof ProjectionContainmentError) {
|
|
183
|
+
io.writeErr(`agents:refresh failed: ${err.message}\n`);
|
|
184
|
+
return 2;
|
|
185
|
+
}
|
|
186
|
+
throw err;
|
|
174
187
|
}
|
|
175
|
-
const path = String(plan.path ?? join(projectRoot, "AGENTS.md"));
|
|
176
|
-
writeFileSync(path, newContent, "utf8");
|
|
177
|
-
io.writeOut(`AGENTS.md updated (state=${state}).\n`);
|
|
178
|
-
return 0;
|
|
179
188
|
}
|
|
180
189
|
/** Core orchestrator for the consumer xbrief rename (#2110) + convergence (#2270). */
|
|
181
190
|
export function runXbriefMigration(args, _io) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.86.0",
|
|
4
4
|
"description": "TypeScript engine core for the Directive framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -317,8 +317,8 @@
|
|
|
317
317
|
"provenance": true
|
|
318
318
|
},
|
|
319
319
|
"dependencies": {
|
|
320
|
-
"@deftai/directive-content": "^0.
|
|
321
|
-
"@deftai/directive-types": "^0.
|
|
320
|
+
"@deftai/directive-content": "^0.86.0",
|
|
321
|
+
"@deftai/directive-types": "^0.86.0",
|
|
322
322
|
"archiver": "^8.0.0"
|
|
323
323
|
},
|
|
324
324
|
"scripts": {
|