@deftai/directive-core 0.81.0 → 0.82.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/content-contracts/skills/helpers.d.ts +6 -0
- package/dist/content-contracts/skills/helpers.js +47 -3
- package/dist/content-contracts/skills/skill-external-fetch-gate.d.ts +18 -0
- package/dist/content-contracts/skills/skill-external-fetch-gate.js +81 -0
- package/dist/eval/crud-telemetry.d.ts +2 -0
- package/dist/eval/crud-telemetry.js +30 -0
- package/dist/intake/github-body-cli.js +2 -0
- package/dist/intake/github-body.d.ts +11 -0
- package/dist/intake/github-body.js +95 -24
- package/dist/integration-e2e/helpers.js +1 -1
- package/dist/issue-sync/sync-from-xbrief.js +3 -0
- package/dist/orphan-active/evaluate.d.ts +25 -0
- package/dist/orphan-active/evaluate.js +275 -0
- package/dist/orphan-active/index.d.ts +3 -0
- package/dist/orphan-active/index.js +3 -0
- package/dist/orphan-active/refs.d.ts +16 -0
- package/dist/orphan-active/refs.js +105 -0
- package/dist/pr-wait-mergeable/cascade.d.ts +8 -0
- package/dist/pr-wait-mergeable/cascade.js +18 -0
- package/dist/pr-wait-mergeable/main.d.ts +4 -0
- package/dist/pr-wait-mergeable/main.js +44 -73
- package/dist/pr-wait-mergeable/result.d.ts +2 -1
- package/dist/pr-wait-mergeable/result.js +4 -0
- package/dist/pr-wait-mergeable/semantic-green.d.ts +27 -0
- package/dist/pr-wait-mergeable/semantic-green.js +202 -0
- package/dist/pr-wait-mergeable/types.d.ts +1 -0
- package/dist/pr-watch/constants.d.ts +4 -4
- package/dist/pr-watch/constants.js +4 -4
- package/dist/pr-watch/watch.js +5 -3
- package/dist/release/native-steps.js +11 -4
- package/dist/render/framework-commands.js +6 -0
- package/dist/scope/brief-io.d.ts +26 -0
- package/dist/scope/brief-io.js +77 -0
- package/dist/scope/decompose.js +2 -2
- package/dist/scope/decomposed-refs.js +3 -3
- package/dist/scope/demote.js +2 -2
- package/dist/scope/project-definition-sync.d.ts +2 -2
- package/dist/scope/project-definition-sync.js +15 -3
- package/dist/scope/registry-artifact-sync.d.ts +6 -1
- package/dist/scope/registry-artifact-sync.js +31 -13
- package/dist/scope/transition.js +23 -15
- package/dist/scope/undo.js +2 -2
- package/dist/scope/vbrief-json.d.ts +1 -2
- package/dist/scope/vbrief-json.js +1 -4
- package/dist/staleness-tickler/state.js +19 -2
- package/dist/triage/queue/cache.js +5 -0
- package/dist/verify-source/index.d.ts +1 -0
- package/dist/verify-source/index.js +1 -0
- package/dist/verify-source/skill-external-fetch-gate.d.ts +21 -0
- package/dist/verify-source/skill-external-fetch-gate.js +71 -0
- package/package.json +7 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
3
|
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
4
|
-
import {
|
|
4
|
+
import { atomicWriteText } from "../cache/io.js";
|
|
5
|
+
import { formatBriefJson } from "./brief-io.js";
|
|
5
6
|
import { relativeToVbrief, resolveVbriefRef, scopeIdsForFilename } from "./vbrief-ref.js";
|
|
6
7
|
function rewriteRegistryPlanReference(ref, oldResolved, newRel, vbriefRoot) {
|
|
7
8
|
if (typeof ref !== "object" || ref === null || Array.isArray(ref)) {
|
|
@@ -88,20 +89,30 @@ function registryItemMatchesScope(item, scopeData, oldPath, newPath, vbriefRoot)
|
|
|
88
89
|
return (typeof scopeTitle === "string" && typeof itemTitle === "string" && itemTitle === scopeTitle);
|
|
89
90
|
}
|
|
90
91
|
/** Best-effort sync of a registry artifact (PROJECT-DEFINITION, specification, etc.) after a lifecycle move. */
|
|
91
|
-
export function syncRegistryArtifactAfterScopeMove(registryPath, scopeData, oldPath, newPath, vbriefRoot, targetStatus) {
|
|
92
|
+
export function syncRegistryArtifactAfterScopeMove(registryPath, scopeData, oldPath, newPath, vbriefRoot, targetStatus, hooks = {}) {
|
|
92
93
|
const newRel = relativeToVbrief(newPath, vbriefRoot);
|
|
93
94
|
if (newRel === null) {
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
|
-
if (!existsSync(registryPath)) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
97
|
try {
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
98
|
+
let registry;
|
|
99
|
+
if (hooks.loadForMutation !== undefined) {
|
|
100
|
+
if (!existsSync(registryPath)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const [loaded] = hooks.loadForMutation();
|
|
104
|
+
registry = loaded;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
if (!existsSync(registryPath)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const parsed = JSON.parse(readFileSync(registryPath, "utf8"));
|
|
111
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
registry = parsed;
|
|
103
115
|
}
|
|
104
|
-
const registry = parsed;
|
|
105
116
|
const plan = registry.plan;
|
|
106
117
|
if (typeof plan !== "object" || plan === null || Array.isArray(plan)) {
|
|
107
118
|
return;
|
|
@@ -149,11 +160,18 @@ export function syncRegistryArtifactAfterScopeMove(registryPath, scopeData, oldP
|
|
|
149
160
|
}
|
|
150
161
|
}
|
|
151
162
|
if (changed) {
|
|
152
|
-
|
|
163
|
+
if (hooks.persist !== undefined) {
|
|
164
|
+
hooks.persist(registryPath, registry);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
atomicWriteText(registryPath, formatBriefJson(registry));
|
|
168
|
+
}
|
|
153
169
|
}
|
|
154
170
|
}
|
|
155
|
-
catch {
|
|
156
|
-
|
|
171
|
+
catch (err) {
|
|
172
|
+
if (hooks.loadForMutation !== undefined || hooks.persist !== undefined) {
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
157
175
|
}
|
|
158
176
|
}
|
|
159
177
|
//# sourceMappingURL=registry-artifact-sync.js.map
|
package/dist/scope/transition.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
3
|
import { InstrumentedVbriefCrud, persistCrudMetrics } from "../eval/crud-telemetry.js";
|
|
4
4
|
import { assertProjectionContained, ProjectionContainmentError, } from "../fs/projection-containment.js";
|
|
5
5
|
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
6
6
|
import { append, canonicalLogPath, newDecisionId } from "./audit-log.js";
|
|
7
|
+
import { atomicWriteBrief, formatBriefJson, readBriefForMutation } from "./brief-io.js";
|
|
7
8
|
import { stampCompletionMetadata } from "./capacity-stamp.js";
|
|
8
9
|
import { LIFECYCLE_FOLDERS, MOVE_LABELS, STATUS_PRECONDITIONS, STAY_LABELS, TRANSITIONS, } from "./constants.js";
|
|
9
10
|
import { detectLifecycleFolder, updateDecomposedChildBackReferences, updateDecomposedParentBackReferences, } from "./decomposed-refs.js";
|
|
10
11
|
import { syncProjectDefinitionAfterScopeMove } from "./project-definition-sync.js";
|
|
11
12
|
import { syncSpecificationAfterScopeMove } from "./specification-sync.js";
|
|
12
|
-
import {
|
|
13
|
+
import { utcNowIso } from "./vbrief-json.js";
|
|
13
14
|
export function runTransition(action, filePath, now = new Date()) {
|
|
14
15
|
if (!(action in TRANSITIONS)) {
|
|
15
16
|
const valid = Object.keys(TRANSITIONS).sort().join(", ");
|
|
@@ -43,13 +44,11 @@ export function runTransition(action, filePath, now = new Date()) {
|
|
|
43
44
|
`File is in ${currentFolder}/.`,
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
return { ok: false, message: `Invalid JSON in ${resolvedPath}: ${String(err)}` };
|
|
47
|
+
const readResult = readBriefForMutation(resolvedPath);
|
|
48
|
+
if (!readResult.ok) {
|
|
49
|
+
return { ok: false, message: readResult.message };
|
|
52
50
|
}
|
|
51
|
+
const data = readResult.data;
|
|
53
52
|
const plan = data.plan;
|
|
54
53
|
if (typeof plan !== "object" || plan === null || Array.isArray(plan)) {
|
|
55
54
|
return { ok: false, message: `Missing or invalid 'plan' object in ${resolvedPath}` };
|
|
@@ -100,7 +99,7 @@ export function runTransition(action, filePath, now = new Date()) {
|
|
|
100
99
|
if (act === "complete") {
|
|
101
100
|
stampCompletionMetadata(planObj, projectRoot, nowIso);
|
|
102
101
|
}
|
|
103
|
-
const formatted =
|
|
102
|
+
const formatted = formatBriefJson(data);
|
|
104
103
|
const crud = new InstrumentedVbriefCrud({ now: () => now });
|
|
105
104
|
if (targetFolder !== null) {
|
|
106
105
|
const destDir = join(vbriefRoot, targetFolder);
|
|
@@ -111,10 +110,11 @@ export function runTransition(action, filePath, now = new Date()) {
|
|
|
111
110
|
}
|
|
112
111
|
// #2578: stamp terminal status at the destination path in the same write as
|
|
113
112
|
// folder placement — never leave a non-terminal status under completed/.
|
|
114
|
-
const writeResult =
|
|
113
|
+
const writeResult = atomicWriteBrief(destPath, data, vbriefRoot);
|
|
115
114
|
if (!writeResult.ok) {
|
|
116
|
-
return { ok: false, message: writeResult.
|
|
115
|
+
return { ok: false, message: writeResult.message };
|
|
117
116
|
}
|
|
117
|
+
crud.recordTrustedUpdate(destPath, formatted);
|
|
118
118
|
try {
|
|
119
119
|
unlinkSync(resolvedPath);
|
|
120
120
|
}
|
|
@@ -135,18 +135,26 @@ export function runTransition(action, filePath, now = new Date()) {
|
|
|
135
135
|
}
|
|
136
136
|
updateDecomposedParentBackReferences(data, resolvedPath, destPath, vbriefRoot);
|
|
137
137
|
updateDecomposedChildBackReferences(data, resolvedPath, destPath, vbriefRoot);
|
|
138
|
-
syncProjectDefinitionAfterScopeMove(data, resolvedPath, destPath, vbriefRoot, targetStatus);
|
|
139
|
-
syncSpecificationAfterScopeMove(data, resolvedPath, destPath, vbriefRoot, targetStatus);
|
|
140
138
|
const actionLabel = MOVE_LABELS[act] ?? act.charAt(0).toUpperCase() + act.slice(1);
|
|
139
|
+
const pdSyncError = syncProjectDefinitionAfterScopeMove(data, resolvedPath, destPath, vbriefRoot, targetStatus);
|
|
140
|
+
if (pdSyncError !== null) {
|
|
141
|
+
return {
|
|
142
|
+
ok: false,
|
|
143
|
+
message: `${actionLabel} ${basename}: brief moved to ${targetFolder}/ but ` +
|
|
144
|
+
`PROJECT-DEFINITION sync failed: ${pdSyncError}`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
syncSpecificationAfterScopeMove(data, resolvedPath, destPath, vbriefRoot, targetStatus);
|
|
141
148
|
return {
|
|
142
149
|
ok: true,
|
|
143
150
|
message: `${actionLabel} ${basename}: ${currentFolder}/ -> ${targetFolder}/ (status: ${targetStatus})`,
|
|
144
151
|
};
|
|
145
152
|
}
|
|
146
|
-
const writeResult =
|
|
153
|
+
const writeResult = atomicWriteBrief(resolvedPath, data, vbriefRoot);
|
|
147
154
|
if (!writeResult.ok) {
|
|
148
|
-
return { ok: false, message: writeResult.
|
|
155
|
+
return { ok: false, message: writeResult.message };
|
|
149
156
|
}
|
|
157
|
+
crud.recordTrustedUpdate(resolvedPath, formatted);
|
|
150
158
|
try {
|
|
151
159
|
persistCrudMetrics(projectRoot, crud.getMetrics());
|
|
152
160
|
}
|
package/dist/scope/undo.js
CHANGED
|
@@ -4,7 +4,7 @@ import { assertWriteTargetSafe, ProjectionContainmentError } from "../fs/project
|
|
|
4
4
|
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
5
5
|
import { append, canonicalLogPath, newDecisionId, readAll } from "./audit-log.js";
|
|
6
6
|
import { REVERSIBLE_ACTIONS, TERMINAL_ACTIONS } from "./constants.js";
|
|
7
|
-
import {
|
|
7
|
+
import { formatBriefJson, utcNowIso } from "./vbrief-json.js";
|
|
8
8
|
function vbriefRoot(projectRoot) {
|
|
9
9
|
return resolveLifecycleRoot(projectRoot);
|
|
10
10
|
}
|
|
@@ -185,7 +185,7 @@ function moveAndFlip(srcFile, destFolder, newStatus, timestamp, projectRoot) {
|
|
|
185
185
|
const planObj = plan;
|
|
186
186
|
planObj.status = newStatus;
|
|
187
187
|
planObj.updated = timestamp;
|
|
188
|
-
writeFileSync(srcFile,
|
|
188
|
+
writeFileSync(srcFile, formatBriefJson(data), "utf8");
|
|
189
189
|
mkdirSync(destFolder, { recursive: true });
|
|
190
190
|
const destPath = join(destFolder, basename(srcFile));
|
|
191
191
|
renameSync(srcFile, destPath);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function formatVbriefJson(data: unknown): string;
|
|
1
|
+
export { formatBriefJson } from "./brief-io.js";
|
|
3
2
|
export declare function utcNowIso(now?: Date): string;
|
|
4
3
|
//# sourceMappingURL=vbrief-json.d.ts.map
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export function formatVbriefJson(data) {
|
|
3
|
-
return `${JSON.stringify(data, null, 2)}\n`;
|
|
4
|
-
}
|
|
1
|
+
export { formatBriefJson } from "./brief-io.js";
|
|
5
2
|
export function utcNowIso(now = new Date()) {
|
|
6
3
|
return now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
7
4
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { resolveTriageCachePath } from "../triage/cache-path.js";
|
|
3
4
|
export const STATE_RELATIVE_PATH = join("xbrief", ".triage-cache", "staleness-tickler-state.json");
|
|
5
|
+
const STATE_FILE_NAME = "staleness-tickler-state.json";
|
|
6
|
+
function resolveStalenessTicklerStatePath(projectRoot) {
|
|
7
|
+
return resolveTriageCachePath(projectRoot, STATE_FILE_NAME);
|
|
8
|
+
}
|
|
4
9
|
function defaultReadText(path) {
|
|
5
10
|
try {
|
|
6
11
|
return readFileSync(path, "utf8");
|
|
@@ -31,11 +36,23 @@ export function parseStalenessTicklerState(text) {
|
|
|
31
36
|
return {};
|
|
32
37
|
}
|
|
33
38
|
export function loadStalenessTicklerState(projectRoot, io = {}) {
|
|
34
|
-
|
|
39
|
+
let path;
|
|
40
|
+
try {
|
|
41
|
+
path = resolveStalenessTicklerStatePath(projectRoot);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
35
46
|
return parseStalenessTicklerState((io.readText ?? defaultReadText)(path));
|
|
36
47
|
}
|
|
37
48
|
export function saveStalenessTicklerState(projectRoot, state, io = {}) {
|
|
38
|
-
|
|
49
|
+
let path;
|
|
50
|
+
try {
|
|
51
|
+
path = resolveStalenessTicklerStatePath(projectRoot);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
39
56
|
try {
|
|
40
57
|
(io.writeText ?? defaultWriteText)(path, `${JSON.stringify(state, null, 2)}\n`);
|
|
41
58
|
}
|
|
@@ -213,6 +213,11 @@ export function loadCachedIssues(repo, options) {
|
|
|
213
213
|
if (scanPassed === false) {
|
|
214
214
|
continue;
|
|
215
215
|
}
|
|
216
|
+
// cachePut writes content.md only when scan_result.passed is true; missing
|
|
217
|
+
// approved content means the entry was quarantined or tampered — fail closed.
|
|
218
|
+
if (scanPassed === true && !existsSync(join(entryDir, "content.md"))) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
216
221
|
const rawTitle = typeof payload.title === "string" ? payload.title : "";
|
|
217
222
|
const safeTitle = sanitizeQueueTitle(rawTitle);
|
|
218
223
|
if (safeTitle === null) {
|
|
@@ -6,5 +6,6 @@ export * from "./cursor-tier1.js";
|
|
|
6
6
|
export * from "./python-call-scan.js";
|
|
7
7
|
export * from "./rule-ownership-lint.js";
|
|
8
8
|
export * from "./scm-boundary.js";
|
|
9
|
+
export * from "./skill-external-fetch-gate.js";
|
|
9
10
|
export * from "./verify-stubs.js";
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,5 +6,6 @@ export * from "./cursor-tier1.js";
|
|
|
6
6
|
export * from "./python-call-scan.js";
|
|
7
7
|
export * from "./rule-ownership-lint.js";
|
|
8
8
|
export * from "./scm-boundary.js";
|
|
9
|
+
export * from "./skill-external-fetch-gate.js";
|
|
9
10
|
export * from "./verify-stubs.js";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* skill-external-fetch-gate.ts -- deterministic gate for fetch-then-execute skill prose (#1936 / #1532).
|
|
3
|
+
*
|
|
4
|
+
* Production entry for collectExternalFetchViolations: wired into
|
|
5
|
+
* `task verify:skill-external-fetch-gate` and `check:framework-source`.
|
|
6
|
+
*
|
|
7
|
+
* Exit codes (three-state):
|
|
8
|
+
* 0 -- clean: every shipped skill with external-fetch language has Security context mitigation.
|
|
9
|
+
* 1 -- drift: one or more skills pair fetch/follow-through with execute/install without mitigation.
|
|
10
|
+
* 2 -- config error: skills directory missing or unreadable.
|
|
11
|
+
*/
|
|
12
|
+
export interface SkillExternalFetchGateResult {
|
|
13
|
+
readonly code: 0 | 1 | 2;
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly stream: "stdout" | "stderr";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Evaluate the skill external-fetch gate for a framework-source or consumer tree.
|
|
19
|
+
*/
|
|
20
|
+
export declare function evaluateSkillExternalFetchGate(projectRoot: string): SkillExternalFetchGateResult;
|
|
21
|
+
//# sourceMappingURL=skill-external-fetch-gate.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* skill-external-fetch-gate.ts -- deterministic gate for fetch-then-execute skill prose (#1936 / #1532).
|
|
3
|
+
*
|
|
4
|
+
* Production entry for collectExternalFetchViolations: wired into
|
|
5
|
+
* `task verify:skill-external-fetch-gate` and `check:framework-source`.
|
|
6
|
+
*
|
|
7
|
+
* Exit codes (three-state):
|
|
8
|
+
* 0 -- clean: every shipped skill with external-fetch language has Security context mitigation.
|
|
9
|
+
* 1 -- drift: one or more skills pair fetch/follow-through with execute/install without mitigation.
|
|
10
|
+
* 2 -- config error: skills directory missing or unreadable.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { resolve } from "node:path";
|
|
14
|
+
import { listSkillMdEntriesFromRoot, listSkillMdFilesFromRoot, resolveContentPathFromRoot, } from "../content-contracts/skills/helpers.js";
|
|
15
|
+
import { collectExternalFetchViolations } from "../content-contracts/skills/skill-external-fetch-gate.js";
|
|
16
|
+
const EXIT_OK = 0;
|
|
17
|
+
const EXIT_DRIFT = 1;
|
|
18
|
+
const EXIT_CONFIG_ERROR = 2;
|
|
19
|
+
function resolveSkillsRoot(projectRoot) {
|
|
20
|
+
const resolved = resolveContentPathFromRoot(resolve(projectRoot), "skills");
|
|
21
|
+
return existsSync(resolved) ? resolved : null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Evaluate the skill external-fetch gate for a framework-source or consumer tree.
|
|
25
|
+
*/
|
|
26
|
+
export function evaluateSkillExternalFetchGate(projectRoot) {
|
|
27
|
+
const root = resolve(projectRoot);
|
|
28
|
+
const skillsRoot = resolveSkillsRoot(root);
|
|
29
|
+
if (skillsRoot === null) {
|
|
30
|
+
return {
|
|
31
|
+
code: EXIT_CONFIG_ERROR,
|
|
32
|
+
message: `skill external-fetch gate: skills directory not found under ${root}`,
|
|
33
|
+
stream: "stderr",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
const skillPaths = listSkillMdFilesFromRoot(root);
|
|
39
|
+
if (skillPaths.length === 0) {
|
|
40
|
+
return {
|
|
41
|
+
code: EXIT_DRIFT,
|
|
42
|
+
message: `FAIL: skill external-fetch gate found no SKILL.md files under ${skillsRoot}`,
|
|
43
|
+
stream: "stderr",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
entries = listSkillMdEntriesFromRoot(root);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
return {
|
|
51
|
+
code: EXIT_CONFIG_ERROR,
|
|
52
|
+
message: `skill external-fetch gate: failed to read skills under ${skillsRoot}: ${msg}`,
|
|
53
|
+
stream: "stderr",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const violations = collectExternalFetchViolations(entries);
|
|
57
|
+
if (violations.length > 0) {
|
|
58
|
+
const sanitize = (value) => value.replace(/\r?\n/g, " ");
|
|
59
|
+
const lines = [
|
|
60
|
+
`FAIL: skill external-fetch gate detected ${violations.length} violation(s):`,
|
|
61
|
+
...violations.map((v) => ` - ${sanitize(v.skillPath)}: ${sanitize(v.detail)}`),
|
|
62
|
+
];
|
|
63
|
+
return { code: EXIT_DRIFT, message: lines.join("\n"), stream: "stderr" };
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
code: EXIT_OK,
|
|
67
|
+
message: `OK: skill external-fetch gate clean -- ${entries.length} skill(s) scanned (root=${root.replace(/\r?\n/g, " ")}).`,
|
|
68
|
+
stream: "stdout",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=skill-external-fetch-gate.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.0",
|
|
4
4
|
"description": "TypeScript engine core for the Directive framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"types": "./dist/wip-cap/index.d.ts",
|
|
31
31
|
"default": "./dist/wip-cap/index.js"
|
|
32
32
|
},
|
|
33
|
+
"./orphan-active": {
|
|
34
|
+
"types": "./dist/orphan-active/index.d.ts",
|
|
35
|
+
"default": "./dist/orphan-active/index.js"
|
|
36
|
+
},
|
|
33
37
|
"./agents-md-budget": {
|
|
34
38
|
"types": "./dist/agents-md-budget/index.d.ts",
|
|
35
39
|
"default": "./dist/agents-md-budget/index.js"
|
|
@@ -309,8 +313,8 @@
|
|
|
309
313
|
"provenance": true
|
|
310
314
|
},
|
|
311
315
|
"dependencies": {
|
|
312
|
-
"@deftai/directive-content": "^0.
|
|
313
|
-
"@deftai/directive-types": "^0.
|
|
316
|
+
"@deftai/directive-content": "^0.82.0",
|
|
317
|
+
"@deftai/directive-types": "^0.82.0",
|
|
314
318
|
"archiver": "^8.0.0"
|
|
315
319
|
},
|
|
316
320
|
"scripts": {
|