@deftai/directive-core 0.81.0 → 0.83.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/hooks/cursor-hooks.d.ts +23 -0
- package/dist/hooks/cursor-hooks.js +95 -0
- package/dist/hooks/dispatcher.d.ts +8 -1
- package/dist/hooks/dispatcher.js +23 -5
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/init-deposit/agent-hooks.d.ts +4 -2
- package/dist/init-deposit/agent-hooks.js +137 -14
- package/dist/init-deposit/hygiene.js +1 -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/lifecycle/events.d.ts +1 -0
- package/dist/lifecycle/events.js +59 -9
- 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/policy/host-hooks.d.ts +21 -0
- package/dist/policy/host-hooks.js +96 -0
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.js +15 -1
- 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/product-signal/consent.d.ts +20 -3
- package/dist/product-signal/consent.js +63 -6
- package/dist/product-signal/gates.d.ts +1 -1
- package/dist/product-signal/submit.d.ts +5 -1
- package/dist/product-signal/submit.js +42 -18
- 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/vbrief-validate/plan-hooks.d.ts +2 -0
- package/dist/vbrief-validate/plan-hooks.js +25 -0
- package/dist/verify-env/agent-hooks.d.ts +2 -1
- package/dist/verify-env/agent-hooks.js +3 -2
- 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,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,6 +6,8 @@ export declare function validateSessionRitualStalenessHoursOnPlan(plan: unknown,
|
|
|
6
6
|
export declare function validateTriageRankingLabelsOnPlan(plan: unknown, filepath: string): string[];
|
|
7
7
|
/** vbrief_validate hook: validate ``plan.policy.runtimeAuthority`` (#1394). */
|
|
8
8
|
export declare function validateRuntimeAuthorityOnPlan(plan: unknown, filepath: string): string[];
|
|
9
|
+
/** vbrief_validate hook: validate ``plan.policy.hostHooks`` (#2752). */
|
|
10
|
+
export declare function validateHostHooksOnPlan(plan: unknown, filepath: string): string[];
|
|
9
11
|
/** vbrief_validate hook: validate ``plan.policy.stalenessTickler`` (#2489). */
|
|
10
12
|
export declare function validateStalenessTicklerOnPlan(plan: unknown, filepath: string): string[];
|
|
11
13
|
/** Run all PROJECT-DEFINITION policy hooks (mirrors lazy-import block in Python). */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateHostHooks } from "../policy/host-hooks.js";
|
|
1
2
|
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
2
3
|
import { validateRuntimeAuthority } from "../policy/runtime-authority.js";
|
|
3
4
|
import { validateStalenessTickler } from "../policy/staleness-tickler.js";
|
|
@@ -121,6 +122,24 @@ export function validateRuntimeAuthorityOnPlan(plan, filepath) {
|
|
|
121
122
|
}
|
|
122
123
|
return out;
|
|
123
124
|
}
|
|
125
|
+
/** vbrief_validate hook: validate ``plan.policy.hostHooks`` (#2752). */
|
|
126
|
+
export function validateHostHooksOnPlan(plan, filepath) {
|
|
127
|
+
if (typeof plan !== "object" || plan === null || Array.isArray(plan)) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
const policy = readPlanPolicy(plan);
|
|
131
|
+
if (typeof policy !== "object" || policy === null || Array.isArray(policy)) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
if (!("hostHooks" in policy)) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const err of validateHostHooks(policy.hostHooks)) {
|
|
139
|
+
out.push(`${filepath}: ${err} (#2752)`);
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
124
143
|
/** vbrief_validate hook: validate ``plan.policy.stalenessTickler`` (#2489). */
|
|
125
144
|
export function validateStalenessTicklerOnPlan(plan, filepath) {
|
|
126
145
|
if (typeof plan !== "object" || plan === null || Array.isArray(plan)) {
|
|
@@ -191,6 +210,12 @@ export function runProjectDefinitionHooks(plan, filepath) {
|
|
|
191
210
|
catch {
|
|
192
211
|
/* hook must not break validation */
|
|
193
212
|
}
|
|
213
|
+
try {
|
|
214
|
+
errors.push(...validateHostHooksOnPlan(plan, filepath));
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
/* hook must not break validation */
|
|
218
|
+
}
|
|
194
219
|
return errors;
|
|
195
220
|
}
|
|
196
221
|
//# sourceMappingURL=plan-hooks.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AgentHookInspection } from "../init-deposit/agent-hooks.js";
|
|
2
|
+
import type { HostHooksPolicy } from "../policy/host-hooks.js";
|
|
2
3
|
import type { OutputStream } from "./verify-hooks-installed.js";
|
|
3
4
|
export interface AgentHookHealthResult {
|
|
4
5
|
readonly code: 0 | 1 | 2;
|
|
@@ -7,5 +8,5 @@ export interface AgentHookHealthResult {
|
|
|
7
8
|
readonly registrations: readonly AgentHookInspection[];
|
|
8
9
|
}
|
|
9
10
|
/** Read-only P0 agent-host registration health, independent of git hooks. */
|
|
10
|
-
export declare function evaluateAgentHooks(projectRoot: string): AgentHookHealthResult;
|
|
11
|
+
export declare function evaluateAgentHooks(projectRoot: string, hostHooksPolicy?: HostHooksPolicy): AgentHookHealthResult;
|
|
11
12
|
//# sourceMappingURL=agent-hooks.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { inspectAgentHookDeposit } from "../init-deposit/agent-hooks.js";
|
|
4
|
+
import { loadHostHooksPolicyFromProject } from "../policy/host-hooks.js";
|
|
4
5
|
function isDirectory(path) {
|
|
5
6
|
try {
|
|
6
7
|
return statSync(path).isDirectory();
|
|
@@ -10,7 +11,7 @@ function isDirectory(path) {
|
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
/** Read-only P0 agent-host registration health, independent of git hooks. */
|
|
13
|
-
export function evaluateAgentHooks(projectRoot) {
|
|
14
|
+
export function evaluateAgentHooks(projectRoot, hostHooksPolicy = loadHostHooksPolicyFromProject(projectRoot)) {
|
|
14
15
|
const root = resolve(projectRoot);
|
|
15
16
|
if (!isDirectory(root)) {
|
|
16
17
|
return {
|
|
@@ -20,7 +21,7 @@ export function evaluateAgentHooks(projectRoot) {
|
|
|
20
21
|
registrations: [],
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
|
-
const registrations = inspectAgentHookDeposit(root);
|
|
24
|
+
const registrations = inspectAgentHookDeposit(root, hostHooksPolicy);
|
|
24
25
|
const unhealthy = registrations.filter((entry) => entry.status !== "healthy");
|
|
25
26
|
if (unhealthy.length > 0) {
|
|
26
27
|
return {
|
|
@@ -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.83.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.83.0",
|
|
317
|
+
"@deftai/directive-types": "^0.83.0",
|
|
314
318
|
"archiver": "^8.0.0"
|
|
315
319
|
},
|
|
316
320
|
"scripts": {
|