@deftai/directive-core 0.63.0 → 0.64.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.
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic gate: assert that Cursor is enumerated as a Tier-1 descriptor in
|
|
3
|
+
* both the swarm Phase 3 capability matrix and the review-cycle monitoring
|
|
4
|
+
* tier-selection table (#1877). Without this gate the "Cursor -> Tier 1" mapping
|
|
5
|
+
* is prose-trusted; a doc edit that drops the Cursor descriptor would silently
|
|
6
|
+
* re-open the misclassification (Cursor falling through to a blocking poll).
|
|
7
|
+
*/
|
|
8
|
+
export interface CursorTier1Target {
|
|
9
|
+
/** Project-root-relative path to the skill file. */
|
|
10
|
+
readonly path: string;
|
|
11
|
+
/** Human label for the surface, used in failure output. */
|
|
12
|
+
readonly label: string;
|
|
13
|
+
/** Whitespace-normalized substrings that MUST all be present. */
|
|
14
|
+
readonly markers: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
export declare const CURSOR_TIER1_TARGETS: readonly CursorTier1Target[];
|
|
17
|
+
/** Collapse all runs of whitespace to a single space (substring-containment normalization). */
|
|
18
|
+
export declare function normalizeWhitespace(text: string): string;
|
|
19
|
+
export interface CursorTier1Finding {
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly missingMarkers: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export interface CursorTier1Result {
|
|
25
|
+
readonly code: 0 | 1 | 2;
|
|
26
|
+
readonly findings: readonly CursorTier1Finding[];
|
|
27
|
+
readonly message: string;
|
|
28
|
+
readonly stream: "stdout" | "stderr";
|
|
29
|
+
}
|
|
30
|
+
export interface CursorTier1Options {
|
|
31
|
+
readonly targets?: readonly CursorTier1Target[];
|
|
32
|
+
readonly quiet?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function evaluateCursorTier1(projectRoot: string, options?: CursorTier1Options): CursorTier1Result;
|
|
35
|
+
//# sourceMappingURL=cursor-tier1.d.ts.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
export const CURSOR_TIER1_TARGETS = [
|
|
4
|
+
{
|
|
5
|
+
path: "content/skills/deft-directive-swarm/SKILL.md",
|
|
6
|
+
label: "swarm Phase 3 capability matrix",
|
|
7
|
+
markers: [
|
|
8
|
+
"Probe for the Cursor `Task` tool",
|
|
9
|
+
"cursor-composer",
|
|
10
|
+
"cursor-cloud-agent",
|
|
11
|
+
"Step 2e: Cursor Launch",
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
path: "content/skills/deft-directive-review-cycle/SKILL.md",
|
|
16
|
+
label: "review-cycle monitoring tier selection",
|
|
17
|
+
markers: [
|
|
18
|
+
"cursor-composer",
|
|
19
|
+
"cursor-cloud-agent",
|
|
20
|
+
"Tier 1 with the backgrounded Cursor `Task` poller path",
|
|
21
|
+
"Heartbeat contract for Cursor pollers",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
/** Collapse all runs of whitespace to a single space (substring-containment normalization). */
|
|
26
|
+
export function normalizeWhitespace(text) {
|
|
27
|
+
return text.replace(/\s+/g, " ");
|
|
28
|
+
}
|
|
29
|
+
export function evaluateCursorTier1(projectRoot, options = {}) {
|
|
30
|
+
const root = resolve(projectRoot);
|
|
31
|
+
let isDir = false;
|
|
32
|
+
try {
|
|
33
|
+
isDir = statSync(root).isDirectory();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
isDir = false;
|
|
37
|
+
}
|
|
38
|
+
if (!isDir) {
|
|
39
|
+
return {
|
|
40
|
+
code: 2,
|
|
41
|
+
findings: [],
|
|
42
|
+
message: `verify_cursor_tier1: --project-root is not a directory: ${root}\n` +
|
|
43
|
+
" Recovery: pass an existing directory path.",
|
|
44
|
+
stream: "stderr",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const targets = options.targets ?? CURSOR_TIER1_TARGETS;
|
|
48
|
+
const findings = [];
|
|
49
|
+
for (const target of targets) {
|
|
50
|
+
const full = join(root, target.path);
|
|
51
|
+
if (!existsSync(full)) {
|
|
52
|
+
return {
|
|
53
|
+
code: 2,
|
|
54
|
+
findings: [...findings],
|
|
55
|
+
message: `verify_cursor_tier1: required skill file not found: ${target.path}\n` +
|
|
56
|
+
" Recovery: run from the framework source root, or update CURSOR_TIER1_TARGETS if the skill moved.",
|
|
57
|
+
stream: "stderr",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
let normalized;
|
|
61
|
+
try {
|
|
62
|
+
normalized = normalizeWhitespace(readFileSync(full, { encoding: "utf8" }));
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
66
|
+
return {
|
|
67
|
+
code: 2,
|
|
68
|
+
findings: [...findings],
|
|
69
|
+
message: `verify_cursor_tier1: could not read ${target.path}: ${msg}`,
|
|
70
|
+
stream: "stderr",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const missing = target.markers.filter((marker) => !normalized.includes(normalizeWhitespace(marker)));
|
|
74
|
+
if (missing.length > 0) {
|
|
75
|
+
findings.push({ path: target.path, label: target.label, missingMarkers: missing });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (findings.length > 0) {
|
|
79
|
+
const header = "verify_cursor_tier1: Cursor is not fully enumerated as a Tier-1 descriptor (#1877).\n" +
|
|
80
|
+
" Root cause: a Cursor agent has a first-class backgroundable sub-agent primitive (the Task tool) and\n" +
|
|
81
|
+
" is therefore Tier 1 / Approach 1. If the matrices below drop the Cursor descriptor, a Cursor session\n" +
|
|
82
|
+
" silently degrades to the Approach-3 blocking poll. Re-add the missing marker(s):";
|
|
83
|
+
const body = findings
|
|
84
|
+
.map((f) => ` ${f.path} (${f.label}) missing: ${f.missingMarkers.map((m) => `"${m}"`).join(", ")}`)
|
|
85
|
+
.join("\n");
|
|
86
|
+
return { code: 1, findings, message: `${header}\n${body}`, stream: "stderr" };
|
|
87
|
+
}
|
|
88
|
+
const msg = `verify_cursor_tier1: Cursor enumerated as a Tier-1 descriptor in ${targets.length} matrix surface(s) (#1877).`;
|
|
89
|
+
if (options.quiet) {
|
|
90
|
+
return { code: 0, findings: [], message: "", stream: "stdout" };
|
|
91
|
+
}
|
|
92
|
+
return { code: 0, findings: [], message: msg, stream: "stdout" };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=cursor-tier1.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"description": "TypeScript engine core for the Directive framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -229,8 +229,8 @@
|
|
|
229
229
|
"provenance": true
|
|
230
230
|
},
|
|
231
231
|
"dependencies": {
|
|
232
|
-
"@deftai/directive-content": "^0.
|
|
233
|
-
"@deftai/directive-types": "^0.
|
|
232
|
+
"@deftai/directive-content": "^0.64.0",
|
|
233
|
+
"@deftai/directive-types": "^0.64.0",
|
|
234
234
|
"archiver": "^8.0.0"
|
|
235
235
|
},
|
|
236
236
|
"scripts": {
|