mandrel 2.19.0 → 2.20.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/.agents/docs/agentrc-reference.json +0 -21
- package/.agents/docs/configuration.md +11 -14
- package/.agents/docs/execution-reference.md +8 -5
- package/.agents/schemas/agentrc.schema.json +0 -31
- package/.agents/scripts/check-test-temp-hygiene.js +153 -14
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +3 -4
- package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -2
- package/.agents/scripts/lib/config/explain.js +0 -8
- package/.agents/scripts/lib/config/temp-paths.js +12 -1
- package/.agents/scripts/lib/config-settings-schema.js +8 -24
- package/.agents/scripts/lib/orchestration/file-assumptions.js +4 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +13 -14
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +12 -66
- package/.agents/scripts/lib/test-env.js +15 -3
- package/.agents/scripts/lib/test-temp.js +311 -0
- package/.agents/workflows/helpers/plan-reference.md +19 -4
- package/.agents/workflows/plan.md +7 -6
- package/docs/CHANGELOG.md +8 -0
- package/lib/migrations/index.js +2 -0
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +113 -0
- package/package.json +1 -1
- package/.agents/scripts/lib/codebase-snapshot.js +0 -513
- package/.agents/scripts/lib/orchestration/planning/spec-authoring-grounding.js +0 -147
- package/.agents/scripts/lib/orchestration/spec-freshness.js +0 -129
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* spec-freshness.js — path-reference helpers for plan authoring.
|
|
3
|
-
*
|
|
4
|
-
* Stage 5 retired the epic-era `validateSpecFreshness` / structured-comment
|
|
5
|
-
* reporter (no production callers remained after the planning collapse).
|
|
6
|
-
* Survivors: path-cue extraction used by `planning/authoring-context.js`
|
|
7
|
-
* and the plan-authoring grounding tests.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Path-shape regexes. Three forms the Architect persona emits today:
|
|
12
|
-
*
|
|
13
|
-
* 1. Backticked reference → `` `src/auth.ts` ``
|
|
14
|
-
* 2. Code-block file header → `// src/auth.ts` or `# lib/foo.py`
|
|
15
|
-
* 3. Inline prose mention → bare `src/auth.ts` between word boundaries
|
|
16
|
-
*
|
|
17
|
-
* All three pull the same captured-path group. We anchor the path on a
|
|
18
|
-
* known repo root (`.agents`, `src`, `lib`, `app`, `tests`, `packages`,
|
|
19
|
-
* `scripts`, `docs`) so we don't false-positive on `library`, `testimonial`,
|
|
20
|
-
* versioned semver fragments, etc.
|
|
21
|
-
*/
|
|
22
|
-
const PATH_ROOTS = [
|
|
23
|
-
'\\.agents',
|
|
24
|
-
'src',
|
|
25
|
-
'lib',
|
|
26
|
-
'app',
|
|
27
|
-
'tests',
|
|
28
|
-
'packages',
|
|
29
|
-
'scripts',
|
|
30
|
-
'docs',
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
const PATH_BODY = '[\\w./-]+\\.[a-zA-Z0-9]{1,8}';
|
|
34
|
-
|
|
35
|
-
const BACKTICK_PATH_RE = new RegExp(
|
|
36
|
-
`\`((?:${PATH_ROOTS.join('|')})/${PATH_BODY})\``,
|
|
37
|
-
'g',
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const COMMENT_HEADER_PATH_RE = new RegExp(
|
|
41
|
-
`(?:^|\\n)\\s*(?://|#)\\s*((?:${PATH_ROOTS.join('|')})/${PATH_BODY})\\b`,
|
|
42
|
-
'g',
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const BARE_PATH_RE = new RegExp(
|
|
46
|
-
`(?:^|[\\s([<>])((?:${PATH_ROOTS.join('|')})/${PATH_BODY})(?=[\\s)\\].,;:]|$)`,
|
|
47
|
-
'g',
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Words in surrounding prose that signal a reference is intentionally
|
|
52
|
-
* net-new — the planner is *proposing* the path, not asserting it exists.
|
|
53
|
-
* When any of these appear within `AMBIGUITY_WINDOW` characters of the
|
|
54
|
-
* match, we treat the citation as intentional rather than drift.
|
|
55
|
-
*/
|
|
56
|
-
const NEW_FILE_CUES = [
|
|
57
|
-
'introduce',
|
|
58
|
-
'introduces',
|
|
59
|
-
'introducing',
|
|
60
|
-
'add',
|
|
61
|
-
'adds',
|
|
62
|
-
'adding',
|
|
63
|
-
'create',
|
|
64
|
-
'creates',
|
|
65
|
-
'creating',
|
|
66
|
-
'new file',
|
|
67
|
-
'new module',
|
|
68
|
-
'new helper',
|
|
69
|
-
'to be created',
|
|
70
|
-
'will be created',
|
|
71
|
-
'net-new',
|
|
72
|
-
'scaffold',
|
|
73
|
-
'scaffolds',
|
|
74
|
-
'scaffolding',
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
const AMBIGUITY_WINDOW = 80;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Check whether the prose surrounding `index` carries one of the
|
|
81
|
-
* net-new cue phrases. Looks both before and after the match within
|
|
82
|
-
* `AMBIGUITY_WINDOW` characters because authors phrase the cue either
|
|
83
|
-
* way: "introduce src/x.ts" *or* "src/x.ts (new helper)".
|
|
84
|
-
*
|
|
85
|
-
* Case-insensitive substring match — deliberately not regex/word-boundary
|
|
86
|
-
* so future cue variants don't silently slip the gate.
|
|
87
|
-
*
|
|
88
|
-
* @param {string} body
|
|
89
|
-
* @param {number} index
|
|
90
|
-
* @param {number} matchLength
|
|
91
|
-
* @returns {boolean}
|
|
92
|
-
*/
|
|
93
|
-
export function hasNewFileCue(body, index, matchLength) {
|
|
94
|
-
const start = Math.max(0, index - AMBIGUITY_WINDOW);
|
|
95
|
-
const end = Math.min(body.length, index + matchLength + AMBIGUITY_WINDOW);
|
|
96
|
-
const window = body.slice(start, end).toLowerCase();
|
|
97
|
-
for (const cue of NEW_FILE_CUES) {
|
|
98
|
-
if (window.includes(cue)) return true;
|
|
99
|
-
}
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Collect every `(path, index, matchLength)` triple from `body` using the
|
|
105
|
-
* three path-shape regexes. The same path can surface at multiple indices —
|
|
106
|
-
* each callsite is preserved so the ambiguity check runs against the cue at
|
|
107
|
-
* *that* index, not a different one.
|
|
108
|
-
*
|
|
109
|
-
* @param {string} body
|
|
110
|
-
* @returns {Array<{ path: string, index: number, matchLength: number }>}
|
|
111
|
-
*/
|
|
112
|
-
export function collectReferences(body) {
|
|
113
|
-
const refs = [];
|
|
114
|
-
for (const re of [BACKTICK_PATH_RE, COMMENT_HEADER_PATH_RE, BARE_PATH_RE]) {
|
|
115
|
-
re.lastIndex = 0;
|
|
116
|
-
let match = re.exec(body);
|
|
117
|
-
while (match !== null) {
|
|
118
|
-
const captured = match[1];
|
|
119
|
-
const captureIndex = match.index + match[0].indexOf(captured);
|
|
120
|
-
refs.push({
|
|
121
|
-
path: captured,
|
|
122
|
-
index: captureIndex,
|
|
123
|
-
matchLength: captured.length,
|
|
124
|
-
});
|
|
125
|
-
match = re.exec(body);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return refs;
|
|
129
|
-
}
|