mandrel 2.63.0 → 2.65.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.
Files changed (70) hide show
  1. package/.agents/agents/acceptance-critic.md +3 -2
  2. package/.agents/agents/auditor.md +3 -2
  3. package/.agents/agents/plan-critic.md +3 -2
  4. package/.agents/agents/story-worker.md +2 -2
  5. package/.agents/audit-checklists/quality.md +3 -0
  6. package/.agents/docs/agentrc-reference.json +1 -9
  7. package/.agents/docs/configuration.md +8 -7
  8. package/.agents/schemas/agentrc.schema.json +6 -13
  9. package/.agents/schemas/audit-rules.schema.json +1 -1
  10. package/.agents/schemas/story-deliver-terminal.schema.json +5 -0
  11. package/.agents/scripts/bootstrap.js +8 -2
  12. package/.agents/scripts/check-context-budget.js +1 -1
  13. package/.agents/scripts/lib/ITicketingProvider.js +1 -3
  14. package/.agents/scripts/lib/audit-suite/findings.js +1 -17
  15. package/.agents/scripts/lib/audit-suite/frontmatter.js +0 -28
  16. package/.agents/scripts/lib/audit-suite/index.js +0 -6
  17. package/.agents/scripts/lib/audit-suite/selector.js +0 -31
  18. package/.agents/scripts/lib/bootstrap/agents-md-fold.js +156 -0
  19. package/.agents/scripts/lib/bootstrap/commit-push.js +1 -1
  20. package/.agents/scripts/lib/bootstrap/manifest.js +2 -2
  21. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +13 -29
  22. package/.agents/scripts/lib/config/review-chain-default.js +13 -0
  23. package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
  24. package/.agents/scripts/lib/config-settings-schema-quality.js +11 -13
  25. package/.agents/scripts/lib/doc-tiers.js +25 -6
  26. package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
  27. package/.agents/scripts/lib/observability/metrics-ledger.js +0 -72
  28. package/.agents/scripts/lib/orchestration/ci-red-handling.js +73 -0
  29. package/.agents/scripts/lib/orchestration/code-review.js +11 -6
  30. package/.agents/scripts/lib/orchestration/deliver-recover.js +56 -11
  31. package/.agents/scripts/lib/orchestration/epic-rollup.js +29 -12
  32. package/.agents/scripts/lib/orchestration/merge-block-class.js +20 -4
  33. package/.agents/scripts/lib/orchestration/merge-poll.js +41 -22
  34. package/.agents/scripts/lib/orchestration/required-checks.js +147 -0
  35. package/.agents/scripts/lib/orchestration/review-providers/code-review.js +203 -0
  36. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +6 -4
  37. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +3 -2
  38. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +1 -0
  39. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +0 -12
  40. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +135 -20
  41. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +112 -82
  42. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +72 -5
  43. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +12 -87
  44. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +3 -0
  45. package/.agents/scripts/lib/templates/decomposer-prompts.js +5 -24
  46. package/.agents/scripts/pr-watch-with-update.js +13 -19
  47. package/.agents/scripts/providers/github/issues.js +14 -23
  48. package/.agents/scripts/sync-claude-agents.js +1 -1
  49. package/.agents/workflows/audit-quality.md +42 -7
  50. package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
  51. package/.agents/workflows/helpers/code-review.md +15 -38
  52. package/.agents/workflows/helpers/deliver-reference.md +4 -2
  53. package/.agents/workflows/helpers/deliver-story.md +3 -0
  54. package/.agents/workflows/helpers/plan-reference.md +9 -8
  55. package/.agents/workflows/mandrel-deliver.md +2 -1
  56. package/.agents/workflows/mandrel-plan.md +10 -7
  57. package/.agents/workflows/mandrel-update.md +5 -3
  58. package/docs/CHANGELOG.md +38 -0
  59. package/lib/cli/claude-code-version.js +73 -0
  60. package/lib/cli/doctor.js +2 -2
  61. package/lib/cli/registry.js +9 -0
  62. package/lib/cli/uninstall.js +37 -9
  63. package/lib/migrations/index.js +2 -0
  64. package/lib/migrations/steps/2.65.0-fold-claude-md-into-agents-md.js +38 -0
  65. package/package.json +2 -1
  66. package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +0 -99
  67. package/.agents/scripts/lib/audit-suite/runner.js +0 -205
  68. package/.agents/scripts/lib/audit-suite/substitutions.js +0 -96
  69. package/.agents/scripts/lib/audit-suite/workflow-loader.js +0 -37
  70. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +0 -234
@@ -1,234 +0,0 @@
1
- /**
2
- * phases/local-lens-review.js — the Story-scope local-lens pass: selects the
3
- * local lenses matching the Story diff and materializes their prompts. The
4
- * review spine (`runStoryReviewCore`) owns diff enumeration and code review.
5
- */
6
-
7
- import {
8
- evaluateLensDiffFloor,
9
- runAuditSuite,
10
- selectLocalLenses,
11
- } from '../../../audit-suite/index.js';
12
- import { gitSpawn } from '../../../git-utils.js';
13
- import {
14
- emitRuntimeFriction,
15
- RUNTIME_FRICTION_CATEGORIES,
16
- } from '../../../observability/runtime-friction.js';
17
- import { computeChangeSet } from '../../change-set.js';
18
-
19
- /** Fixed for this tier; not risk-scaled. */
20
- const STORY_SCOPE_LENS_DEPTH = 'light';
21
-
22
- /**
23
- * Roster of materialized lens-prompt artifacts the host MUST walk — the
24
- * default review provider never reads them, so without this they are inert.
25
- *
26
- * @param {object|null} materialized the `runAuditSuite` result envelope.
27
- * @returns {string|null} the roster block, or `null` when there is nothing to walk.
28
- */
29
- function renderLensArtifactRoster(materialized) {
30
- const paths = (materialized?.workflows ?? [])
31
- .map((w) => w?.artifactPath)
32
- .filter((p) => typeof p === 'string' && p.length > 0);
33
- if (paths.length === 0) return null;
34
- return [
35
- `Lens prompts materialized (host MUST read/walk each against the Story diff):`,
36
- ...paths.map((p) => ` - ${p}`),
37
- ].join('\n');
38
- }
39
-
40
- /**
41
- * Built-in substitution keys, so no per-lens declaration is needed.
42
- *
43
- * @param {{ changedFiles: string[], storyId?: number|string|null }} args
44
- * @returns {Record<string, string>}
45
- */
46
- function buildLensSubstitutions({ changedFiles, storyId }) {
47
- const substitutions = { changedFiles: changedFiles.join('\n') };
48
- if (storyId != null && `${storyId}`.length > 0) {
49
- substitutions.ticketId = String(storyId);
50
- }
51
- return substitutions;
52
- }
53
-
54
- /**
55
- * Never throws: an unknown diff returns `[]`, which matches no lens, same as
56
- * an empty one.
57
- *
58
- * @param {{
59
- * baseRef: string,
60
- * headRef: string,
61
- * gitSpawnFn?: import('../../change-set.js').GitSpawnFn,
62
- * }} args
63
- * @returns {string[]} Changed file paths, or `[]` on any failure.
64
- */
65
- function enumerateChangedFiles({ baseRef, headRef, gitSpawnFn = gitSpawn }) {
66
- return computeChangeSet({ baseRef, headRef, gitSpawnFn }).files ?? [];
67
- }
68
-
69
- /**
70
- * Three-state injection: an array is used verbatim; `null` means the spine
71
- * already failed to enumerate, so don't re-spawn git; `undefined` means
72
- * nobody enumerated, so self-enumerate.
73
- *
74
- * @param {{
75
- * changedFiles: string[]|null|undefined,
76
- * baseRef: string,
77
- * headRef: string,
78
- * gitSpawnFn?: import('../../change-set.js').GitSpawnFn,
79
- * }} args
80
- * @returns {string[]}
81
- */
82
- function resolveLensChangeSet({
83
- changedFiles,
84
- baseRef,
85
- headRef,
86
- gitSpawnFn = gitSpawn,
87
- }) {
88
- if (changedFiles === undefined) {
89
- return enumerateChangedFiles({ baseRef, headRef, gitSpawnFn });
90
- }
91
- return changedFiles ?? [];
92
- }
93
-
94
- /**
95
- * Run the maker-blind Story-scope lens pass (called only from
96
- * `runStoryReviewCore`). No matching lens → no lens work. A diff below the
97
- * lens diff-floor with no sensitive-path hits records the roster but skips
98
- * materialization; an unknown line count fails open. Advisory: any failure
99
- * degrades to a skipped envelope plus a friction signal.
100
- *
101
- * @param {{
102
- * baseRef: string,
103
- * headRef: string,
104
- * changedFiles?: string[]|null,
105
- * changedLineCount?: number|null,
106
- * lensDiffFloor?: number,
107
- * storyId?: number|string|null,
108
- * artifactPrefix?: string,
109
- * progress: (tag: string, msg: string) => void,
110
- * progressTag?: string,
111
- * gitSpawnFn?: import('../../change-set.js').GitSpawnFn,
112
- * selectLocalLensesFn?: typeof selectLocalLenses,
113
- * runAuditSuiteFn?: typeof runAuditSuite,
114
- * evaluateLensDiffFloorFn?: typeof evaluateLensDiffFloor,
115
- * emitToolDegradationFn?: typeof emitRuntimeFriction,
116
- * }} args
117
- * @returns {Promise<{
118
- * depth: 'light',
119
- * lenses: string[],
120
- * skipped: boolean,
121
- * floorSkip: object|null,
122
- * materialized: object|null,
123
- * artifactPaths: string[],
124
- * }>}
125
- */
126
- export async function runLocalLensReview({
127
- baseRef,
128
- headRef,
129
- changedFiles: injectedChangedFiles,
130
- changedLineCount = null,
131
- lensDiffFloor,
132
- storyId,
133
- artifactPrefix,
134
- progress,
135
- progressTag = 'CODE-REVIEW',
136
- gitSpawnFn = gitSpawn,
137
- selectLocalLensesFn = selectLocalLenses,
138
- runAuditSuiteFn = runAuditSuite,
139
- evaluateLensDiffFloorFn = evaluateLensDiffFloor,
140
- emitToolDegradationFn = emitRuntimeFriction,
141
- }) {
142
- const empty = {
143
- depth: STORY_SCOPE_LENS_DEPTH,
144
- lenses: [],
145
- skipped: true,
146
- floorSkip: null,
147
- materialized: null,
148
- artifactPaths: [],
149
- };
150
- try {
151
- const changedFiles = resolveLensChangeSet({
152
- changedFiles: injectedChangedFiles,
153
- baseRef,
154
- headRef,
155
- gitSpawnFn,
156
- });
157
- const lenses = selectLocalLensesFn({ changedFiles });
158
- if (lenses.length === 0) {
159
- progress(
160
- progressTag,
161
- 'No local lens matched the Story diff — skipping the lens pass.',
162
- );
163
- return empty;
164
- }
165
-
166
- // After selection so a floor-skip still records which lenses it skipped.
167
- const floorVerdict = evaluateLensDiffFloorFn({
168
- changedFiles,
169
- changedLineCount,
170
- floor: lensDiffFloor,
171
- });
172
- if (floorVerdict.skip) {
173
- progress(
174
- progressTag,
175
- `Lens diff-floor: ${floorVerdict.changedLineCount} changed line(s) < ` +
176
- `floor ${floorVerdict.floor} with zero sensitive-path hits — ` +
177
- `skipping materialization of ${lenses.join(', ')}.`,
178
- );
179
- return {
180
- depth: STORY_SCOPE_LENS_DEPTH,
181
- lenses,
182
- skipped: true,
183
- floorSkip: floorVerdict,
184
- materialized: null,
185
- artifactPaths: [],
186
- };
187
- }
188
- // Story-scoped names so concurrent closes can't clobber each other.
189
- const effectivePrefix =
190
- artifactPrefix ?? (storyId != null ? `story-${storyId}` : 'story-scope');
191
- const materialized = await runAuditSuiteFn({
192
- auditWorkflows: lenses,
193
- substitutions: buildLensSubstitutions({ changedFiles, storyId }),
194
- artifactPrefix: effectivePrefix,
195
- });
196
- progress(
197
- progressTag,
198
- `Ran ${lenses.length} local lens(es) at ${STORY_SCOPE_LENS_DEPTH} depth: ${lenses.join(', ')}.`,
199
- );
200
- const roster = renderLensArtifactRoster(materialized);
201
- if (roster) progress(progressTag, roster);
202
- const artifactPaths = (materialized?.workflows ?? [])
203
- .map((w) => w?.artifactPath)
204
- .filter((p) => typeof p === 'string' && p.length > 0);
205
- return {
206
- depth: STORY_SCOPE_LENS_DEPTH,
207
- lenses,
208
- skipped: false,
209
- floorSkip: floorVerdict,
210
- materialized,
211
- artifactPaths,
212
- };
213
- } catch (err) {
214
- // Degradations are operational signals (friction), not findings.
215
- progress(
216
- progressTag,
217
- `⚠️ local lens pass failed (continuing without it): ${err?.message ?? err}`,
218
- );
219
- try {
220
- await emitToolDegradationFn({
221
- storyId,
222
- category: RUNTIME_FRICTION_CATEGORIES.TOOL_DEGRADED,
223
- tool: 'local-lens-review',
224
- details: {
225
- surface: 'lens-materialization',
226
- reason: String(err?.message ?? err).slice(0, 500),
227
- },
228
- });
229
- } catch {
230
- // Observability must never fail the close.
231
- }
232
- return empty;
233
- }
234
- }