@deftai/directive-core 0.92.0 → 0.94.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/cache/fetch.d.ts +29 -0
- package/dist/cache/fetch.js +131 -4
- package/dist/cache/operations.d.ts +8 -0
- package/dist/cache/operations.js +67 -4
- package/dist/check/cached-orchestrator.js +11 -0
- package/dist/check/consumer-gate-integrity.d.ts +68 -0
- package/dist/check/consumer-gate-integrity.js +265 -0
- package/dist/check/index.d.ts +1 -0
- package/dist/check/index.js +1 -0
- package/dist/check/orchestrator.js +10 -0
- package/dist/content-contracts/skills/greptile-detector.d.ts +9 -0
- package/dist/content-contracts/skills/greptile-detector.js +9 -2
- package/dist/doctor/index.d.ts +1 -0
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/main.js +69 -0
- package/dist/doctor/openclaw-l2-adapter.d.ts +26 -0
- package/dist/doctor/openclaw-l2-adapter.js +199 -0
- package/dist/finish-loop/pr-finish-loop.js +1 -0
- package/dist/hooks/dispatcher.d.ts +24 -2
- package/dist/hooks/dispatcher.js +122 -11
- package/dist/hooks/readonly.d.ts +14 -0
- package/dist/hooks/readonly.js +126 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/hygiene.js +22 -0
- package/dist/init-deposit/index.d.ts +3 -0
- package/dist/init-deposit/index.js +3 -0
- package/dist/init-deposit/init-deposit.js +10 -0
- package/dist/init-deposit/refresh.js +11 -0
- package/dist/init-deposit/scaffold.js +3 -133
- package/dist/init-deposit/skill-discovery-deposit.d.ts +65 -0
- package/dist/init-deposit/skill-discovery-deposit.js +287 -0
- package/dist/init-deposit/skill-discovery-hosts.d.ts +94 -0
- package/dist/init-deposit/skill-discovery-hosts.js +217 -0
- package/dist/init-deposit/slash-deposit.d.ts +46 -0
- package/dist/init-deposit/slash-deposit.js +174 -0
- package/dist/intake/issue-ingest.d.ts +20 -0
- package/dist/intake/issue-ingest.js +58 -0
- package/dist/policy/host-slash-commands.d.ts +28 -0
- package/dist/policy/host-slash-commands.js +103 -0
- package/dist/policy/index.d.ts +2 -0
- package/dist/policy/index.js +61 -7
- package/dist/policy/min-greptile-confidence.d.ts +57 -0
- package/dist/policy/min-greptile-confidence.js +123 -0
- package/dist/pr-merge-readiness/compute.d.ts +11 -1
- package/dist/pr-merge-readiness/compute.js +17 -4
- package/dist/pr-merge-readiness/evaluate.d.ts +8 -1
- package/dist/pr-merge-readiness/evaluate.js +7 -4
- package/dist/pr-merge-readiness/mergeability.d.ts +7 -1
- package/dist/pr-merge-readiness/mergeability.js +14 -2
- package/dist/pr-monitor/main.d.ts +2 -0
- package/dist/pr-monitor/main.js +31 -1
- package/dist/pr-monitor/monitor.js +5 -1
- package/dist/pr-monitor/readiness.js +3 -1
- package/dist/pr-monitor/types.d.ts +8 -0
- package/dist/pr-wait-mergeable/cascade.d.ts +8 -0
- package/dist/pr-wait-mergeable/cascade.js +28 -1
- package/dist/pr-wait-mergeable/main.d.ts +2 -0
- package/dist/pr-wait-mergeable/main.js +16 -0
- package/dist/pr-wait-mergeable/types.d.ts +3 -1
- package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
- package/dist/pr-wait-mergeable/wrappers.js +3 -0
- package/dist/pr-watch/constants.d.ts +4 -1
- package/dist/pr-watch/constants.js +5 -2
- package/dist/pr-watch/main.js +1 -0
- package/dist/pr-watch/probe.d.ts +1 -1
- package/dist/pr-watch/probe.js +4 -1
- package/dist/pr-watch/types.d.ts +7 -1
- package/dist/pr-watch/watch.js +3 -2
- package/dist/review-monitor/index.d.ts +1 -0
- package/dist/review-monitor/index.js +1 -0
- package/dist/review-monitor/l4-owner.d.ts +46 -0
- package/dist/review-monitor/l4-owner.js +262 -0
- package/dist/slash/emitters.d.ts +102 -0
- package/dist/slash/emitters.js +148 -0
- package/dist/slash/generator.d.ts +98 -0
- package/dist/slash/generator.js +145 -0
- package/dist/slash/index.d.ts +16 -0
- package/dist/slash/index.js +16 -0
- package/dist/slash/openclaw-adapter.d.ts +64 -0
- package/dist/slash/openclaw-adapter.js +198 -0
- package/dist/slash/openclaw-deposit.d.ts +73 -0
- package/dist/slash/openclaw-deposit.js +279 -0
- package/dist/slash/openclaw-slugs.d.ts +52 -0
- package/dist/slash/openclaw-slugs.js +126 -0
- package/dist/slash/product-set.d.ts +50 -0
- package/dist/slash/product-set.js +142 -0
- package/dist/tool-events/classify.js +1 -0
- package/dist/triage/welcome/writers.js +16 -7
- package/dist/umbrella-current-shape/index.d.ts +45 -0
- package/dist/umbrella-current-shape/index.js +162 -8
- package/dist/vbrief-reconcile/index.d.ts +2 -2
- package/dist/vbrief-reconcile/index.js +1 -1
- package/dist/vbrief-reconcile/types.d.ts +14 -0
- package/dist/vbrief-reconcile/umbrellas.d.ts +31 -2
- package/dist/vbrief-reconcile/umbrellas.js +231 -19
- package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
- package/dist/vbrief-validate/plan-hooks.js +50 -0
- package/dist/xbrief/create.d.ts +36 -0
- package/dist/xbrief/create.js +285 -0
- package/dist/xbrief/index.d.ts +14 -0
- package/dist/xbrief/index.js +42 -0
- package/dist/xbrief/paths.d.ts +37 -0
- package/dist/xbrief/paths.js +123 -0
- package/dist/xbrief/styles.d.ts +36 -0
- package/dist/xbrief/styles.js +235 -0
- package/dist/xbrief/types.d.ts +50 -0
- package/dist/xbrief/types.js +17 -0
- package/dist/xbrief/verify.d.ts +30 -0
- package/dist/xbrief/verify.js +251 -0
- package/package.json +11 -3
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor check + --fix wire for OpenClaw L2 product-command skills (#3064 D5).
|
|
3
|
+
*
|
|
4
|
+
* Primary operator recovery path when OpenClaw is detected. Deposits thin
|
|
5
|
+
* user-invocable router + 13 product skills into workspace skills roots.
|
|
6
|
+
* Fail-closed when OC signals are absent. Policy opt-out:
|
|
7
|
+
* `plan.policy.openClawProductCommands: false`.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { generateOpenClawSkillArtifacts, isManagedOpenClawL2Skill, listOpenClawManagedSkillSlugs, } from "../slash/openclaw-adapter.js";
|
|
13
|
+
import { depositOpenClawL2ProductCommands, loadOpenClawProductCommandsPolicyFromProject, } from "../slash/openclaw-deposit.js";
|
|
14
|
+
import { detectOpenClaw, listInScopeSkillsDirs } from "./openclaw-skills.js";
|
|
15
|
+
/** Stable doctor check id for JSON findings. */
|
|
16
|
+
export const OPENCLAW_L2_ADAPTER_CHECK = "openclaw-l2-product-commands";
|
|
17
|
+
const DOC_OPENCLAW_HOST = "docs/openclaw-agent-host.md";
|
|
18
|
+
const DOC_SLASH_MULTI = "docs/slash-multi-host.md";
|
|
19
|
+
const REMEDIATION_FIX = "deft doctor --fix";
|
|
20
|
+
function defaultIsDir(path) {
|
|
21
|
+
try {
|
|
22
|
+
return statSync(path).isDirectory();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function assessGaps(skillsDirs) {
|
|
29
|
+
const artifacts = generateOpenClawSkillArtifacts();
|
|
30
|
+
const missing = [];
|
|
31
|
+
const stale = [];
|
|
32
|
+
let present = 0;
|
|
33
|
+
for (const skillsDir of skillsDirs) {
|
|
34
|
+
for (const art of artifacts) {
|
|
35
|
+
const path = join(skillsDir, art.slug, "SKILL.md");
|
|
36
|
+
if (!existsSync(path)) {
|
|
37
|
+
missing.push(`${skillsDir}/${art.slug}`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
let raw;
|
|
41
|
+
try {
|
|
42
|
+
raw = readFileSync(path, "utf8");
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
missing.push(`${skillsDir}/${art.slug}`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!isManagedOpenClawL2Skill(raw)) {
|
|
49
|
+
// Consumer customization — not a gap for doctor (preserve).
|
|
50
|
+
present += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (raw === art.skillMarkdown) {
|
|
54
|
+
present += 1;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
stale.push(`${skillsDir}/${art.slug}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { missing, stale, present };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Doctor check: OpenClaw L2 product-command skills present and current.
|
|
65
|
+
* No-ops when OpenClaw is not detected. Fix mode deposits managed skills.
|
|
66
|
+
*/
|
|
67
|
+
export function runOpenClawL2AdapterCheck(sink, addFinding, options) {
|
|
68
|
+
const seams = options.seams ?? {};
|
|
69
|
+
const env = seams.openclawEnv ?? process.env;
|
|
70
|
+
const homeDirFn = seams.openclawHomeDir ?? (() => homedir());
|
|
71
|
+
const isDir = seams.isDir ?? defaultIsDir;
|
|
72
|
+
const home = homeDirFn();
|
|
73
|
+
const detect = detectOpenClaw(env, { homeDir: home, isDir });
|
|
74
|
+
if (!detect.detected) {
|
|
75
|
+
sink.info(`${OPENCLAW_L2_ADAPTER_CHECK}: skip -- OpenClaw not detected`);
|
|
76
|
+
addFinding({
|
|
77
|
+
severity: "skip",
|
|
78
|
+
message: "OpenClaw not detected",
|
|
79
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
80
|
+
status: "skip",
|
|
81
|
+
reason: "openclaw-not-detected",
|
|
82
|
+
});
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const policy = loadOpenClawProductCommandsPolicyFromProject(options.projectRoot);
|
|
86
|
+
if (!policy) {
|
|
87
|
+
// Opt-out: under --fix, strip managed L2 skills so the adapter does not
|
|
88
|
+
// stay active after openClawProductCommands=false (#3064 Greptile P1).
|
|
89
|
+
let depositResult = null;
|
|
90
|
+
if (options.fixMode) {
|
|
91
|
+
depositResult = depositOpenClawL2ProductCommands({
|
|
92
|
+
projectRoot: options.projectRoot,
|
|
93
|
+
env,
|
|
94
|
+
homeDir: home,
|
|
95
|
+
allAgents: options.allAgents,
|
|
96
|
+
policy: false,
|
|
97
|
+
printf: (t) => {
|
|
98
|
+
if (!options.jsonMode)
|
|
99
|
+
sink.info(t.trimEnd());
|
|
100
|
+
},
|
|
101
|
+
isDir,
|
|
102
|
+
});
|
|
103
|
+
const message = `${OPENCLAW_L2_ADAPTER_CHECK}: opted out (plan.policy.openClawProductCommands=false); ` +
|
|
104
|
+
(depositResult.removedPaths.length > 0
|
|
105
|
+
? `removed ${depositResult.removedPaths.length} managed skill path(s)`
|
|
106
|
+
: "no managed L2 skills to remove");
|
|
107
|
+
sink.success(message);
|
|
108
|
+
addFinding({
|
|
109
|
+
severity: "skip",
|
|
110
|
+
message,
|
|
111
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
112
|
+
status: "opted-out-fixed",
|
|
113
|
+
reason: "policy-false",
|
|
114
|
+
removed: depositResult.removedPaths,
|
|
115
|
+
detect_reasons: detect.reasons,
|
|
116
|
+
});
|
|
117
|
+
return depositResult;
|
|
118
|
+
}
|
|
119
|
+
sink.info(`${OPENCLAW_L2_ADAPTER_CHECK}: skip -- plan.policy.openClawProductCommands=false`);
|
|
120
|
+
addFinding({
|
|
121
|
+
severity: "skip",
|
|
122
|
+
message: "OpenClaw L2 product commands opted out via policy; run `deft doctor --fix` to remove managed skills",
|
|
123
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
124
|
+
status: "opted-out",
|
|
125
|
+
reason: "policy-false",
|
|
126
|
+
});
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const skillsDirs = listInScopeSkillsDirs(detect.stateDir, options.allAgents, {
|
|
130
|
+
isDir,
|
|
131
|
+
});
|
|
132
|
+
const gaps = assessGaps(skillsDirs);
|
|
133
|
+
const expectedCount = listOpenClawManagedSkillSlugs().length * skillsDirs.length;
|
|
134
|
+
if (gaps.missing.length === 0 && gaps.stale.length === 0) {
|
|
135
|
+
const message = `${OPENCLAW_L2_ADAPTER_CHECK}: OpenClaw L2 product-command skills present ` +
|
|
136
|
+
`(router + 13) in ${options.allAgents ? "main + workspace-* seats" : "main workspace"}`;
|
|
137
|
+
sink.success(message);
|
|
138
|
+
addFinding({
|
|
139
|
+
severity: "skip",
|
|
140
|
+
message,
|
|
141
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
142
|
+
status: "present",
|
|
143
|
+
skills_dirs: skillsDirs,
|
|
144
|
+
expected: expectedCount,
|
|
145
|
+
present: gaps.present,
|
|
146
|
+
detect_reasons: detect.reasons,
|
|
147
|
+
});
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
let depositResult = null;
|
|
151
|
+
if (options.fixMode) {
|
|
152
|
+
depositResult = depositOpenClawL2ProductCommands({
|
|
153
|
+
projectRoot: options.projectRoot,
|
|
154
|
+
env,
|
|
155
|
+
homeDir: home,
|
|
156
|
+
allAgents: options.allAgents,
|
|
157
|
+
policy: true,
|
|
158
|
+
printf: (t) => {
|
|
159
|
+
if (!options.jsonMode)
|
|
160
|
+
sink.info(t.trimEnd());
|
|
161
|
+
},
|
|
162
|
+
isDir,
|
|
163
|
+
});
|
|
164
|
+
const post = assessGaps(skillsDirs);
|
|
165
|
+
if (post.missing.length === 0 && post.stale.length === 0) {
|
|
166
|
+
const message = `${OPENCLAW_L2_ADAPTER_CHECK}: deposited OpenClaw L2 product-command skills; ` +
|
|
167
|
+
"restart the OpenClaw gateway or start a new session so available_skills refreshes";
|
|
168
|
+
sink.success(message);
|
|
169
|
+
addFinding({
|
|
170
|
+
severity: "skip",
|
|
171
|
+
message,
|
|
172
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
173
|
+
status: "fixed",
|
|
174
|
+
skills_dirs: skillsDirs,
|
|
175
|
+
written: depositResult.writtenPaths,
|
|
176
|
+
detect_reasons: detect.reasons,
|
|
177
|
+
});
|
|
178
|
+
return depositResult;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const message = `${OPENCLAW_L2_ADAPTER_CHECK}: OpenClaw L2 product-command skills incomplete ` +
|
|
182
|
+
`(missing: ${gaps.missing.length}, stale: ${gaps.stale.length}) under ${skillsDirs.join(", ")}. ` +
|
|
183
|
+
`Remediation: ${REMEDIATION_FIX}. See ${DOC_OPENCLAW_HOST}, ${DOC_SLASH_MULTI}.`;
|
|
184
|
+
sink.warn(message);
|
|
185
|
+
addFinding({
|
|
186
|
+
severity: "warning",
|
|
187
|
+
message,
|
|
188
|
+
check: OPENCLAW_L2_ADAPTER_CHECK,
|
|
189
|
+
status: "missing",
|
|
190
|
+
missing: gaps.missing,
|
|
191
|
+
stale: gaps.stale,
|
|
192
|
+
skills_dirs: skillsDirs,
|
|
193
|
+
suggestion: REMEDIATION_FIX,
|
|
194
|
+
docs: [DOC_OPENCLAW_HOST, DOC_SLASH_MULTI],
|
|
195
|
+
detect_reasons: detect.reasons,
|
|
196
|
+
});
|
|
197
|
+
return depositResult;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=openclaw-l2-adapter.js.map
|
|
@@ -5,7 +5,7 @@ import { type RuntimeAuthorityPolicy } from "../policy/runtime-authority.js";
|
|
|
5
5
|
import { type VerifyResult } from "../session/verify-session-ritual.js";
|
|
6
6
|
import { type HookPayloadContext } from "./classify/index.js";
|
|
7
7
|
import { type ActiveScopeInspection } from "./scope.js";
|
|
8
|
-
export { hookReadOnlyFromPayload, isExploreSpawn, isReadOnlyHookContext } from "./readonly.js";
|
|
8
|
+
export { ASSIST_SESSION_POSTURE_ENV, hookReadOnlyFromPayload, isAssistPosture, isEphemeralSpawn, isExploreSpawn, isReadOnlyHookContext, } from "./readonly.js";
|
|
9
9
|
export { DIRECT_WRITE_HOOK_MATCHER, DIRECT_WRITE_TOOL_NAMES, isDirectWriteTool, isMcpTool, isShellTool, isSpawnTool, MCP_HOOK_MATCHER, MCP_PUSH_MERGE_BARE_NAMES, READ_ONLY_HOOK_ENV, SHELL_HOOK_MATCHER, SHELL_TOOL_NAMES, SPAWN_HOOK_MATCHER, SPAWN_TOOL_NAMES, } from "./tools.js";
|
|
10
10
|
export declare const HOOK_HOSTS: readonly ["claude", "grok", "cursor", "codex"];
|
|
11
11
|
export type HookHost = (typeof HOOK_HOSTS)[number];
|
|
@@ -21,7 +21,11 @@ export type HookDecisionCode = "session-start" | "session-start-disabled" | "ses
|
|
|
21
21
|
/** Enforcement skipped: root `.deft-directive-disable` test kill-switch (#3039). */
|
|
22
22
|
| "directive-disabled" | "session-compact-rearm" | "session-compact-rearm-degraded" | "session-compact-noop" | "not-direct-write" | "invalid-input"
|
|
23
23
|
/** Host closed stdin with zero bytes — integration failure, not a policy gate (#2864). */
|
|
24
|
-
| "stdin-empty" | "ritual-not-ready" | "scope-not-ready" | "write-propose-ready"
|
|
24
|
+
| "stdin-empty" | "ritual-not-ready" | "scope-not-ready" | "write-propose-ready"
|
|
25
|
+
/** Allowlisted assist/scratch write without active xBRIEF (#1802). */
|
|
26
|
+
| "write-assist-scratch-ready" | "write-ready" | "read-only-deny" | "spawn-explore-ready"
|
|
27
|
+
/** Non-lifecycle assist/docs spawn allowed without active xBRIEF (#3080). */
|
|
28
|
+
| "spawn-ephemeral-ready" | "spawn-ready" | "spawn-not-ready" | "runtime-policy-deny-path" | "runtime-policy-deny-scope"
|
|
25
29
|
/** Shell/MCP classifiable push/merge allowed under runtimeAuthority (#2711). */
|
|
26
30
|
| "shell-op-ready"
|
|
27
31
|
/** Shell/MCP tool seen but command/tool not classifiable as push/merge — fail open (#2711). */
|
|
@@ -102,6 +106,24 @@ export declare function isOutsideProjectRootWrite(projectRoot: string, targetPat
|
|
|
102
106
|
* planning, not implementation dispatch — exempt from the active-scope gate (#2625).
|
|
103
107
|
*/
|
|
104
108
|
export declare function isProposedLifecycleWrite(projectRoot: string, targetPath: string | null): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Canonical + gitignored assist scratch roots for low-ceremony disposable notes (#1802).
|
|
111
|
+
* Path fence only — not free-text "for Obsidian" NLP. Tracked trees (src/, packages/, …)
|
|
112
|
+
* are never listed here.
|
|
113
|
+
*/
|
|
114
|
+
export declare const ASSIST_SCRATCH_ROOT_PREFIXES: readonly [".deft-scratch/", "temp/"];
|
|
115
|
+
/**
|
|
116
|
+
* True when the write target is under an allowlisted disposable scratch root (#1802).
|
|
117
|
+
* Fail closed on null/empty/unparseable targets and on path escape (`..`).
|
|
118
|
+
* Does not authorize tracked product paths even under assist posture.
|
|
119
|
+
*/
|
|
120
|
+
export declare function isAllowlistedAssistScratchPath(projectRoot: string, targetPath: string | null): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Assist/ephemeral classification for scratch-write carve-out (#1802).
|
|
123
|
+
* Requires allowlisted path AND (assist posture markers OR ephemeral spawn markers).
|
|
124
|
+
* Path alone without posture markers fails closed to the mutation gate stack.
|
|
125
|
+
*/
|
|
126
|
+
export declare function isAssistScratchWrite(projectRoot: string, targetPath: string | null, payload: unknown, environ?: NodeJS.ProcessEnv): boolean;
|
|
105
127
|
/** Normalize hook project-root resolution on Windows (doubled drive + MSYS `/c/...`). */
|
|
106
128
|
export declare function normalizeHookProjectRoot(path: string): string;
|
|
107
129
|
export declare function projectRootFromHookPayload(payload: unknown, fallback: string): string;
|
package/dist/hooks/dispatcher.js
CHANGED
|
@@ -13,12 +13,12 @@ import { markRitualStaleAfterCompact } from "../session/ritual-sentinel.js";
|
|
|
13
13
|
import { runSessionStartHookWrite } from "../session/session-start-hook.js";
|
|
14
14
|
import { formatRitualRecoveryInstruction, inspectSessionRitual, } from "../session/verify-session-ritual.js";
|
|
15
15
|
import { hookMcpArgsText, hookShellCommand, hookToolName, hookWriteTargetPath, missingToolNameMessage, record, } from "./classify/index.js";
|
|
16
|
-
import { isExploreSpawn, isReadOnlyHookContext } from "./readonly.js";
|
|
16
|
+
import { isAssistPosture, isEphemeralSpawn, isExploreSpawn, isReadOnlyHookContext, } from "./readonly.js";
|
|
17
17
|
import { inspectActiveScope } from "./scope.js";
|
|
18
18
|
import { isDirectWriteTool, isMcpTool, isShellTool, isSpawnTool } from "./tools.js";
|
|
19
19
|
// Pure parse/classify helpers are defined in ./classify/ and re-exported from
|
|
20
20
|
// ./index.ts (#2950). Dispatcher is orchestration: classify → policy → decision.
|
|
21
|
-
export { hookReadOnlyFromPayload, isExploreSpawn, isReadOnlyHookContext } from "./readonly.js";
|
|
21
|
+
export { ASSIST_SESSION_POSTURE_ENV, hookReadOnlyFromPayload, isAssistPosture, isEphemeralSpawn, isExploreSpawn, isReadOnlyHookContext, } from "./readonly.js";
|
|
22
22
|
export { DIRECT_WRITE_HOOK_MATCHER, DIRECT_WRITE_TOOL_NAMES, isDirectWriteTool, isMcpTool, isShellTool, isSpawnTool, MCP_HOOK_MATCHER, MCP_PUSH_MERGE_BARE_NAMES, READ_ONLY_HOOK_ENV, SHELL_HOOK_MATCHER, SHELL_TOOL_NAMES, SPAWN_HOOK_MATCHER, SPAWN_TOOL_NAMES, } from "./tools.js";
|
|
23
23
|
export const HOOK_HOSTS = ["claude", "grok", "cursor", "codex"];
|
|
24
24
|
export const HOOK_EVENTS = ["session.start", "session.compact", "tool.before"];
|
|
@@ -99,6 +99,47 @@ export function isProposedLifecycleWrite(projectRoot, targetPath) {
|
|
|
99
99
|
return false;
|
|
100
100
|
return posix.startsWith("xbrief/proposed/") || posix.startsWith("vbrief/proposed/");
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Canonical + gitignored assist scratch roots for low-ceremony disposable notes (#1802).
|
|
104
|
+
* Path fence only — not free-text "for Obsidian" NLP. Tracked trees (src/, packages/, …)
|
|
105
|
+
* are never listed here.
|
|
106
|
+
*/
|
|
107
|
+
export const ASSIST_SCRATCH_ROOT_PREFIXES = [".deft-scratch/", "temp/"];
|
|
108
|
+
/**
|
|
109
|
+
* True when the write target is under an allowlisted disposable scratch root (#1802).
|
|
110
|
+
* Fail closed on null/empty/unparseable targets and on path escape (`..`).
|
|
111
|
+
* Does not authorize tracked product paths even under assist posture.
|
|
112
|
+
*/
|
|
113
|
+
export function isAllowlistedAssistScratchPath(projectRoot, targetPath) {
|
|
114
|
+
if (targetPath === null || targetPath.trim().length === 0)
|
|
115
|
+
return false;
|
|
116
|
+
const posix = toProjectRelativePosix(projectRoot, targetPath);
|
|
117
|
+
// resolve()+relative() collapses mid-path `..`; only outside-root `..` remains.
|
|
118
|
+
if (posix === ".." || posix.startsWith("../") || isAbsolute(posix))
|
|
119
|
+
return false;
|
|
120
|
+
if (isLexicalOutsideProjectRoot(posix))
|
|
121
|
+
return false;
|
|
122
|
+
for (const prefix of ASSIST_SCRATCH_ROOT_PREFIXES) {
|
|
123
|
+
if (posix === prefix.slice(0, -1) || posix.startsWith(prefix))
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Assist/ephemeral classification for scratch-write carve-out (#1802).
|
|
130
|
+
* Requires allowlisted path AND (assist posture markers OR ephemeral spawn markers).
|
|
131
|
+
* Path alone without posture markers fails closed to the mutation gate stack.
|
|
132
|
+
*/
|
|
133
|
+
export function isAssistScratchWrite(projectRoot, targetPath, payload, environ = process.env) {
|
|
134
|
+
if (!isAllowlistedAssistScratchPath(projectRoot, targetPath))
|
|
135
|
+
return false;
|
|
136
|
+
// Structural classification only — compose with #3080 ephemeral markers.
|
|
137
|
+
if (isAssistPosture(payload, environ))
|
|
138
|
+
return true;
|
|
139
|
+
if (isEphemeralSpawn(payload))
|
|
140
|
+
return true;
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
102
143
|
function isWindowsDriveOnlyRoot(value) {
|
|
103
144
|
return /^[A-Za-z]:[/\\]?$/.test(value.trim());
|
|
104
145
|
}
|
|
@@ -448,6 +489,39 @@ function decideShellOrMcpRuntimeAuthority(input, toolName, seams) {
|
|
|
448
489
|
}
|
|
449
490
|
function inspectMutationGates(input, toolName, seams, options) {
|
|
450
491
|
const projectRoot = resolve(input.projectRoot);
|
|
492
|
+
const environ = input.environ ?? process.env;
|
|
493
|
+
// Assist/scratch low-ceremony writes (#1802): allowlisted gitignored roots under
|
|
494
|
+
// assist/ephemeral classification skip ritual + active-scope (no fake scope:activate).
|
|
495
|
+
// Tracked product paths never match the path fence. Read-only still denied upstream.
|
|
496
|
+
if (!isSpawnTool(toolName)) {
|
|
497
|
+
const scratchTarget = hookWriteTargetPath(input.payload);
|
|
498
|
+
if (isAssistScratchWrite(projectRoot, scratchTarget, input.payload, environ)) {
|
|
499
|
+
const relPath = scratchTarget !== null ? toProjectRelativePosix(projectRoot, scratchTarget) : null;
|
|
500
|
+
const authzDeny = authzForMutation(input, toolName, seams, {
|
|
501
|
+
isDirectWrite: true,
|
|
502
|
+
relPath,
|
|
503
|
+
scopePath: null,
|
|
504
|
+
});
|
|
505
|
+
if (authzDeny !== null)
|
|
506
|
+
return authzDeny;
|
|
507
|
+
const runtimeDeny = runtimeAuthorityForDirectWrite(input, toolName, seams, null);
|
|
508
|
+
if (runtimeDeny !== null)
|
|
509
|
+
return runtimeDeny;
|
|
510
|
+
return {
|
|
511
|
+
verdict: "allow",
|
|
512
|
+
code: "write-assist-scratch-ready",
|
|
513
|
+
event: input.event,
|
|
514
|
+
host: input.host,
|
|
515
|
+
toolName,
|
|
516
|
+
projectRoot,
|
|
517
|
+
message: `Directive write gate allowed ${toolName} under allowlisted assist scratch ` +
|
|
518
|
+
"root (disposable notes; active scope and story-start not required). " +
|
|
519
|
+
"Tracked product paths still require mutation gates — do not smuggle source " +
|
|
520
|
+
"under .deft-scratch/ or temp/.",
|
|
521
|
+
scopePath: null,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
}
|
|
451
525
|
let ritual;
|
|
452
526
|
try {
|
|
453
527
|
ritual = (seams.inspectRitual ??
|
|
@@ -520,16 +594,38 @@ function inspectMutationGates(input, toolName, seams, options) {
|
|
|
520
594
|
// Lexical ../ + realpath re-entry guard (not bare startsWith(".."); not symlink aliases).
|
|
521
595
|
const outsideRoot = writeTarget !== null && isOutsideProjectRootWrite(projectRoot, writeTarget);
|
|
522
596
|
if (!outsideRoot || isSpawnTool(toolName)) {
|
|
523
|
-
|
|
597
|
+
let proposedPathHint;
|
|
598
|
+
if (isSpawnTool(toolName)) {
|
|
599
|
+
// Multi-path recovery for implement-class spawns (#3080 AC4).
|
|
600
|
+
proposedPathHint =
|
|
601
|
+
" Recovery: (1) Product implementation — run `deft scope:activate -- <path>` " +
|
|
602
|
+
"for the approved xBRIEF, then re-run the pre-start_agent gate stack. " +
|
|
603
|
+
"(2) Read-only research — spawn with `subagent_type`/`worker_role` explore. " +
|
|
604
|
+
"(3) Ephemeral docs/analysis — spawn with `worker_role: ephemeral` " +
|
|
605
|
+
"(aliases: docs, assist; see commands.md), or continue in the parent without " +
|
|
606
|
+
"a lifecycle story. Do not invent a fake scope only to satisfy this gate.";
|
|
607
|
+
}
|
|
608
|
+
else if (options.proposedLifecycleExempt &&
|
|
524
609
|
relTarget !== null &&
|
|
525
|
-
(relTarget.startsWith("xbrief/proposed/") || relTarget.startsWith("vbrief/proposed/"))
|
|
526
|
-
|
|
527
|
-
"
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
610
|
+
(relTarget.startsWith("xbrief/proposed/") || relTarget.startsWith("vbrief/proposed/"))) {
|
|
611
|
+
proposedPathHint =
|
|
612
|
+
" For a new proposal under xbrief/proposed/, include a lifecycle artifact " +
|
|
613
|
+
"filename (*.xbrief.json) in the Write/Edit payload so the gate can exempt " +
|
|
614
|
+
"planning writes (#2625).";
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
proposedPathHint =
|
|
618
|
+
" Recovery: run `deft scope:activate -- <path>` for the approved xBRIEF, " +
|
|
619
|
+
(options.proposedLifecycleExempt
|
|
620
|
+
? "or Write a new proposal to xbrief/proposed/*.xbrief.json (planning exemption), " +
|
|
621
|
+
"or for disposable research notes write under `.deft-scratch/` (or `temp/`) " +
|
|
622
|
+
"with assist/ephemeral posture (`DEFT_SESSION_POSTURE=assist` or " +
|
|
623
|
+
"`worker_role: assist` / ephemeral — see commands.md #1802 / #3080). " +
|
|
624
|
+
"Do not invent a fake scope only to capture Obsidian/scratch notes."
|
|
625
|
+
: "then re-run the pre-start_agent gate stack. " +
|
|
626
|
+
"For disposable research notes only: write under `.deft-scratch/` with " +
|
|
627
|
+
"assist posture (commands.md #1802) — do not fake `scope:activate` for notes.");
|
|
628
|
+
}
|
|
533
629
|
const denyCode = isSpawnTool(toolName) ? "spawn-not-ready" : "scope-not-ready";
|
|
534
630
|
return deny(input, denyCode, toolName, `Directive denied ${toolName}: ${scope.message}${proposedPathHint}`);
|
|
535
631
|
}
|
|
@@ -736,6 +832,21 @@ export function decideHook(input, seams = {}) {
|
|
|
736
832
|
scopePath: null,
|
|
737
833
|
};
|
|
738
834
|
}
|
|
835
|
+
// Ephemeral/docs/assist: write-capable non-lifecycle spawn; no active xBRIEF (#3080).
|
|
836
|
+
// Does not authorize push/merge/deploy — those remain on shell/MCP matchers.
|
|
837
|
+
if (isEphemeralSpawn(input.payload)) {
|
|
838
|
+
return {
|
|
839
|
+
verdict: "allow",
|
|
840
|
+
code: "spawn-ephemeral-ready",
|
|
841
|
+
event: input.event,
|
|
842
|
+
host: input.host,
|
|
843
|
+
toolName,
|
|
844
|
+
projectRoot,
|
|
845
|
+
message: `Directive allowed ephemeral ${toolName} spawn without active-xBRIEF ` +
|
|
846
|
+
"implementation gates (non-lifecycle assist/docs posture).",
|
|
847
|
+
scopePath: null,
|
|
848
|
+
};
|
|
849
|
+
}
|
|
739
850
|
return inspectMutationGates(input, toolName, seams, { proposedLifecycleExempt: false });
|
|
740
851
|
}
|
|
741
852
|
// Shell/Bash and classifiable MCP: enforce scopes.push / scopes.merge (#2711).
|
package/dist/hooks/readonly.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
/** Session posture env for assist/research low-ceremony writes (#1802). */
|
|
2
|
+
export declare const ASSIST_SESSION_POSTURE_ENV = "DEFT_SESSION_POSTURE";
|
|
1
3
|
/** Best-effort read-only explore signal from host payload (#1185). */
|
|
2
4
|
export declare function hookReadOnlyFromPayload(payload: unknown): boolean;
|
|
3
5
|
/** Read-only hook context: env override or host payload marker (#1185). */
|
|
4
6
|
export declare function isReadOnlyHookContext(payload: unknown, environ?: NodeJS.ProcessEnv): boolean;
|
|
5
7
|
/** Explore sub-agent spawns are exempt from the implementation gate stack (#1185). */
|
|
6
8
|
export declare function isExploreSpawn(payload: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Assist / research / ephemeral session posture for low-ceremony scratch writes (#1802).
|
|
11
|
+
* Structural markers only (env, payload posture fields, worker_role/subagent_type).
|
|
12
|
+
* Absent marker → false (fail closed). Compose with allowlisted scratch path fence.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isAssistPosture(payload: unknown, environ?: NodeJS.ProcessEnv): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Ephemeral / assist / docs spawns skip active-xBRIEF implementation gates (#3080).
|
|
17
|
+
* True only with an explicit allowlisted marker. Absent marker → false (fail closed).
|
|
18
|
+
* When an ephemeral marker conflicts with implement envelope signals, implement wins.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isEphemeralSpawn(payload: unknown): boolean;
|
|
7
21
|
//# sourceMappingURL=readonly.d.ts.map
|
package/dist/hooks/readonly.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { READ_ONLY_HOOK_ENV } from "./tools.js";
|
|
2
2
|
const TRUTHY = new Set(["1", "true", "yes", "on"]);
|
|
3
|
+
/** Session posture env for assist/research low-ceremony writes (#1802). */
|
|
4
|
+
export const ASSIST_SESSION_POSTURE_ENV = "DEFT_SESSION_POSTURE";
|
|
5
|
+
/** Explicit non-lifecycle assist markers (#3080 / #1802). Primary: ephemeral; aliases: docs, assist. */
|
|
6
|
+
const EPHEMERAL_ROLE_MARKERS = new Set(["ephemeral", "docs", "assist"]);
|
|
7
|
+
/** Assist/research session posture tokens (structural; not free-text NLP) (#1802). */
|
|
8
|
+
const ASSIST_POSTURE_MARKERS = new Set([
|
|
9
|
+
"assist",
|
|
10
|
+
"ephemeral",
|
|
11
|
+
"docs",
|
|
12
|
+
"research",
|
|
13
|
+
"research-notes",
|
|
14
|
+
"research_notes",
|
|
15
|
+
"scratch",
|
|
16
|
+
]);
|
|
3
17
|
function record(value) {
|
|
4
18
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
5
19
|
? value
|
|
@@ -28,6 +42,9 @@ function isReadOnlyCapability(value) {
|
|
|
28
42
|
const normalized = value.toLowerCase().replace(/[_\s-]/g, "");
|
|
29
43
|
return normalized === "readonly";
|
|
30
44
|
}
|
|
45
|
+
function normalizePostureToken(value) {
|
|
46
|
+
return value.toLowerCase().replace(/[_\s]/g, "-");
|
|
47
|
+
}
|
|
31
48
|
/** Best-effort read-only explore signal from host payload (#1185). */
|
|
32
49
|
export function hookReadOnlyFromPayload(payload) {
|
|
33
50
|
const input = record(payload);
|
|
@@ -80,4 +97,113 @@ export function isExploreSpawn(payload) {
|
|
|
80
97
|
fieldString(input, "workerRole");
|
|
81
98
|
return workerRole?.toLowerCase() === "explore";
|
|
82
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Assist / research / ephemeral session posture for low-ceremony scratch writes (#1802).
|
|
102
|
+
* Structural markers only (env, payload posture fields, worker_role/subagent_type).
|
|
103
|
+
* Absent marker → false (fail closed). Compose with allowlisted scratch path fence.
|
|
104
|
+
*/
|
|
105
|
+
export function isAssistPosture(payload, environ = process.env) {
|
|
106
|
+
const envPosture = (environ[ASSIST_SESSION_POSTURE_ENV] ?? "").trim();
|
|
107
|
+
if (envPosture.length > 0 && ASSIST_POSTURE_MARKERS.has(normalizePostureToken(envPosture))) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
// Explicit assist env override (truthy), separate from posture token names.
|
|
111
|
+
if (envTruthy(environ, "DEFT_HOOK_ASSIST"))
|
|
112
|
+
return true;
|
|
113
|
+
const input = record(payload);
|
|
114
|
+
if (input === null)
|
|
115
|
+
return false;
|
|
116
|
+
const toolInput = toolInputRecord(input) ?? input;
|
|
117
|
+
const posture = fieldString(toolInput, "posture") ??
|
|
118
|
+
fieldString(toolInput, "session_posture") ??
|
|
119
|
+
fieldString(toolInput, "sessionPosture") ??
|
|
120
|
+
fieldString(input, "posture") ??
|
|
121
|
+
fieldString(input, "session_posture") ??
|
|
122
|
+
fieldString(input, "sessionPosture");
|
|
123
|
+
if (posture !== null && ASSIST_POSTURE_MARKERS.has(normalizePostureToken(posture))) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
// Shared taxonomy with #3080 ephemeral spawn markers.
|
|
127
|
+
if (isEphemeralSpawn(payload))
|
|
128
|
+
return true;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Structural implement signals that win over an ephemeral marker (fail closed, #3080).
|
|
133
|
+
* Detected from envelope fields only — never free-text prompt heuristics.
|
|
134
|
+
*/
|
|
135
|
+
function hasImplementConflictSignal(toolInput, input) {
|
|
136
|
+
const driveTo = fieldString(toolInput, "drive_to") ??
|
|
137
|
+
fieldString(toolInput, "driveTo") ??
|
|
138
|
+
fieldString(toolInput, "drive-to") ??
|
|
139
|
+
fieldString(input, "drive_to") ??
|
|
140
|
+
fieldString(input, "driveTo") ??
|
|
141
|
+
fieldString(input, "drive-to");
|
|
142
|
+
if (driveTo !== null) {
|
|
143
|
+
const normalized = driveTo.toLowerCase().replace(/[_\s]/g, "-");
|
|
144
|
+
if (normalized === "merge-ready" ||
|
|
145
|
+
normalized === "merge" ||
|
|
146
|
+
normalized.startsWith("merge-") ||
|
|
147
|
+
normalized.includes("implement")) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Non-ephemeral worker roles that imply product implementation / swarm leaf.
|
|
152
|
+
// Skip when this field is itself the ephemeral marker (conflict is via other fields).
|
|
153
|
+
const workerRole = fieldString(toolInput, "worker_role") ??
|
|
154
|
+
fieldString(toolInput, "workerRole") ??
|
|
155
|
+
fieldString(input, "worker_role") ??
|
|
156
|
+
fieldString(input, "workerRole");
|
|
157
|
+
if (workerRole !== null && !EPHEMERAL_ROLE_MARKERS.has(workerRole.toLowerCase())) {
|
|
158
|
+
const role = workerRole.toLowerCase().replace(/[_\s]/g, "-");
|
|
159
|
+
if (role === "leaf-implementation" ||
|
|
160
|
+
role === "implementation" ||
|
|
161
|
+
role === "implement" ||
|
|
162
|
+
role.includes("implement")) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const dispatchKind = fieldString(toolInput, "dispatch_kind") ??
|
|
167
|
+
fieldString(toolInput, "dispatchKind") ??
|
|
168
|
+
fieldString(input, "dispatch_kind") ??
|
|
169
|
+
fieldString(input, "dispatchKind");
|
|
170
|
+
if (dispatchKind !== null) {
|
|
171
|
+
const kind = dispatchKind.toLowerCase().replace(/[_\s]/g, "-");
|
|
172
|
+
if (kind === "swarm-cohort" || kind === "swarm-leaf" || kind.includes("implement")) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Ephemeral / assist / docs spawns skip active-xBRIEF implementation gates (#3080).
|
|
180
|
+
* True only with an explicit allowlisted marker. Absent marker → false (fail closed).
|
|
181
|
+
* When an ephemeral marker conflicts with implement envelope signals, implement wins.
|
|
182
|
+
*/
|
|
183
|
+
export function isEphemeralSpawn(payload) {
|
|
184
|
+
const input = record(payload);
|
|
185
|
+
if (input === null)
|
|
186
|
+
return false;
|
|
187
|
+
const toolInput = toolInputRecord(input) ?? input;
|
|
188
|
+
const subagentType = fieldString(toolInput, "subagent_type") ??
|
|
189
|
+
fieldString(toolInput, "subagentType") ??
|
|
190
|
+
fieldString(input, "subagent_type") ??
|
|
191
|
+
fieldString(input, "subagentType");
|
|
192
|
+
const workerRole = fieldString(toolInput, "worker_role") ??
|
|
193
|
+
fieldString(toolInput, "workerRole") ??
|
|
194
|
+
fieldString(input, "worker_role") ??
|
|
195
|
+
fieldString(input, "workerRole");
|
|
196
|
+
const marker = (workerRole !== null && EPHEMERAL_ROLE_MARKERS.has(workerRole.toLowerCase())
|
|
197
|
+
? workerRole.toLowerCase()
|
|
198
|
+
: null) ??
|
|
199
|
+
(subagentType !== null && EPHEMERAL_ROLE_MARKERS.has(subagentType.toLowerCase())
|
|
200
|
+
? subagentType.toLowerCase()
|
|
201
|
+
: null);
|
|
202
|
+
if (marker === null)
|
|
203
|
+
return false;
|
|
204
|
+
// Implement signals win over ephemeral markers (fail closed).
|
|
205
|
+
if (hasImplementConflictSignal(toolInput, input))
|
|
206
|
+
return false;
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
83
209
|
//# sourceMappingURL=readonly.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export * as resolution from "./resolution/index.js";
|
|
|
50
50
|
export * as scm from "./scm/index.js";
|
|
51
51
|
export * as scope from "./scope/index.js";
|
|
52
52
|
export * as session from "./session/index.js";
|
|
53
|
+
export * as slash from "./slash/index.js";
|
|
53
54
|
export * as slice from "./slice/index.js";
|
|
54
55
|
export * as storyReady from "./story-ready/index.js";
|
|
55
56
|
export * as swarm from "./swarm/index.js";
|
|
@@ -65,6 +66,7 @@ export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
|
65
66
|
export * as verifyEnv from "./verify-env/index.js";
|
|
66
67
|
export * as verifySource from "./verify-source/index.js";
|
|
67
68
|
export * as wipCap from "./wip-cap/index.js";
|
|
69
|
+
export * as xbrief from "./xbrief/index.js";
|
|
68
70
|
export * as xbriefMigrate from "./xbrief-migrate/index.js";
|
|
69
71
|
export declare const CORE_PACKAGE: "@deftai/directive-core";
|
|
70
72
|
/** Returns identifying metadata for the core engine package. */
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ export * as resolution from "./resolution/index.js";
|
|
|
51
51
|
export * as scm from "./scm/index.js";
|
|
52
52
|
export * as scope from "./scope/index.js";
|
|
53
53
|
export * as session from "./session/index.js";
|
|
54
|
+
export * as slash from "./slash/index.js";
|
|
54
55
|
export * as slice from "./slice/index.js";
|
|
55
56
|
export * as storyReady from "./story-ready/index.js";
|
|
56
57
|
export * as swarm from "./swarm/index.js";
|
|
@@ -66,6 +67,7 @@ export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
|
66
67
|
export * as verifyEnv from "./verify-env/index.js";
|
|
67
68
|
export * as verifySource from "./verify-source/index.js";
|
|
68
69
|
export * as wipCap from "./wip-cap/index.js";
|
|
70
|
+
export * as xbrief from "./xbrief/index.js";
|
|
69
71
|
export * as xbriefMigrate from "./xbrief-migrate/index.js";
|
|
70
72
|
export const CORE_PACKAGE = "@deftai/directive-core";
|
|
71
73
|
/** Returns identifying metadata for the core engine package. */
|