mandrel 1.58.0 → 1.59.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/README.md +89 -87
- package/.agents/docs/SDLC.md +11 -7
- package/.agents/docs/workflows.md +2 -1
- package/.agents/schemas/audit-rules.json +20 -0
- package/.agents/scripts/acceptance-eval.js +20 -3
- package/.agents/scripts/assert-branch.js +1 -3
- package/.agents/scripts/bootstrap.js +1 -1
- package/.agents/scripts/check-arch-cycles.js +360 -0
- package/.agents/scripts/coverage-capture.js +24 -3
- package/.agents/scripts/epic-deliver-preflight.js +5 -3
- package/.agents/scripts/epic-deliver-prepare.js +12 -4
- package/.agents/scripts/epic-execute-record-wave.js +1 -1
- package/.agents/scripts/evidence-gate.js +1 -1
- package/.agents/scripts/git-rebase-and-resolve.js +1 -1
- package/.agents/scripts/hierarchy-gate.js +34 -14
- package/.agents/scripts/lib/baselines/kinds/coverage.js +33 -149
- package/.agents/scripts/lib/baselines/kinds/duplication.js +27 -116
- package/.agents/scripts/lib/baselines/kinds/kind-factory.js +192 -0
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +34 -133
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +31 -124
- package/.agents/scripts/lib/baselines/kinds/mutation.js +25 -111
- package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +59 -0
- package/.agents/scripts/lib/baselines/maintainability-baseline-save.js +37 -0
- package/.agents/scripts/lib/baselines/writer.js +1 -1
- package/.agents/scripts/lib/close-validation/commands.js +188 -0
- package/.agents/scripts/lib/close-validation/gates.js +235 -0
- package/.agents/scripts/lib/close-validation/process.js +101 -0
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +1 -1
- package/.agents/scripts/lib/close-validation/runner.js +325 -0
- package/.agents/scripts/lib/close-validation/telemetry.js +70 -0
- package/.agents/scripts/lib/config/quality.js +6 -6
- package/.agents/scripts/lib/config-resolver.js +2 -5
- package/.agents/scripts/lib/coverage-capture.js +147 -4
- package/.agents/scripts/lib/cpu-pool.js +14 -0
- package/.agents/scripts/lib/crap-utils.js +6 -11
- package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +87 -0
- package/.agents/scripts/lib/git-utils.js +24 -22
- package/.agents/scripts/lib/maintainability-engine.js +1 -1
- package/.agents/scripts/lib/maintainability-utils.js +4 -187
- package/.agents/scripts/lib/observability/perf-report-readers.js +32 -23
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +80 -6
- package/.agents/scripts/lib/orchestration/code-review.js +90 -77
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +5 -12
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +14 -14
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +184 -49
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +26 -2
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +26 -6
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +7 -20
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -2
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -6
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +103 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +22 -64
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +38 -76
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -16
- package/.agents/scripts/lib/orchestration/file-assumptions.js +4 -3
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +144 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +7 -7
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +3 -3
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +7 -7
- package/.agents/scripts/lib/orchestration/preflight-cache.js +35 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +5 -60
- package/.agents/scripts/lib/orchestration/review-providers/native.js +7 -6
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +105 -0
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +7 -59
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +2 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -4
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +32 -35
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +1 -2
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +451 -503
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +8 -2
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +47 -2
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +2 -2
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +358 -54
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +3 -2
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +30 -3
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +5 -18
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +3 -3
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +33 -16
- package/.agents/scripts/lib/orchestration/story-reachability.js +47 -0
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -33
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +42 -64
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +9 -0
- package/.agents/scripts/lib/orchestration/ticketing/state.js +50 -436
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +471 -0
- package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +1 -1
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -7
- package/.agents/scripts/lib/project-root.js +17 -0
- package/.agents/scripts/lib/story-adjacency.js +76 -0
- package/.agents/scripts/lib/story-lifecycle.js +1 -1
- package/.agents/scripts/lib/transpile.js +93 -0
- package/.agents/scripts/lib/wave-runner/tick.js +4 -153
- package/.agents/scripts/lib/workers/crap-worker.js +1 -1
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/creation.js +20 -2
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +90 -0
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +26 -8
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +74 -0
- package/.agents/scripts/providers/github/tickets.js +110 -6
- package/.agents/scripts/run-lint.js +9 -0
- package/.agents/scripts/run-tests.js +24 -4
- package/.agents/scripts/stories-wave-tick.js +8 -5
- package/.agents/scripts/story-init.js +149 -10
- package/.agents/scripts/sync-branch-from-base.js +1 -1
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +1 -1
- package/.agents/workflows/audit-documentation.md +226 -0
- package/.agents/workflows/epic-deliver.md +16 -23
- package/.agents/workflows/epic-plan.md +1 -1
- package/.agents/workflows/helpers/epic-deliver-story.md +17 -28
- package/.agents/workflows/helpers/single-story-deliver.md +2 -1
- package/.agents/workflows/onboard.md +4 -3
- package/.agents/workflows/story-deliver.md +1 -1
- package/README.md +13 -8
- package/lib/cli/init.js +336 -0
- package/package.json +2 -1
- package/.agents/scripts/lib/auto-refresh-baselines.js +0 -308
- package/.agents/scripts/lib/close-validation.js +0 -897
- package/.agents/scripts/lib/orchestration/cascade-grouping.js +0 -275
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +0 -69
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +0 -221
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +0 -123
- package/.agents/scripts/lib/task-utils.js +0 -26
- package/.agents/scripts/story-deliver-prepare.js +0 -267
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
import { spawnSync } from 'node:child_process';
|
|
35
|
+
import { parseProviderFindings } from './parse-findings.js';
|
|
35
36
|
import { renderDepthDirective } from './review-depth.js';
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -138,65 +139,12 @@ export function mapSecurityReviewSeverity(raw) {
|
|
|
138
139
|
* @throws {Error} when stdout is not parseable JSON.
|
|
139
140
|
*/
|
|
140
141
|
export function parseSecurityReviewFindings(rawStdout) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} catch (err) {
|
|
148
|
-
throw new Error(
|
|
149
|
-
`[security-review] Failed to parse /security-review stdout as JSON: ${
|
|
150
|
-
err?.message ?? err
|
|
151
|
-
}`,
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
156
|
-
if (Array.isArray(parsed.findings)) parsed = parsed.findings;
|
|
157
|
-
else if (parsed.result !== undefined) parsed = parsed.result;
|
|
158
|
-
else if (parsed.data !== undefined) parsed = parsed.data;
|
|
159
|
-
}
|
|
160
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
161
|
-
if (Array.isArray(parsed.findings)) parsed = parsed.findings;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (!Array.isArray(parsed)) return [];
|
|
165
|
-
|
|
166
|
-
/** @type {Finding[]} */
|
|
167
|
-
const findings = [];
|
|
168
|
-
for (const entry of parsed) {
|
|
169
|
-
if (!entry || typeof entry !== 'object') continue;
|
|
170
|
-
const title =
|
|
171
|
-
typeof entry.title === 'string' && entry.title.trim().length > 0
|
|
172
|
-
? entry.title.trim()
|
|
173
|
-
: null;
|
|
174
|
-
const body =
|
|
175
|
-
typeof entry.body === 'string' && entry.body.trim().length > 0
|
|
176
|
-
? entry.body
|
|
177
|
-
: typeof entry.message === 'string' && entry.message.trim().length > 0
|
|
178
|
-
? entry.message
|
|
179
|
-
: null;
|
|
180
|
-
if (!title || !body) continue;
|
|
181
|
-
/** @type {Finding} */
|
|
182
|
-
const finding = {
|
|
183
|
-
severity: mapSecurityReviewSeverity(entry.severity),
|
|
184
|
-
title,
|
|
185
|
-
body,
|
|
186
|
-
category:
|
|
187
|
-
typeof entry.category === 'string' && entry.category.length > 0
|
|
188
|
-
? entry.category
|
|
189
|
-
: 'security',
|
|
190
|
-
};
|
|
191
|
-
if (typeof entry.file === 'string' && entry.file.length > 0) {
|
|
192
|
-
finding.file = entry.file;
|
|
193
|
-
}
|
|
194
|
-
if (Number.isInteger(entry.line) && entry.line > 0) {
|
|
195
|
-
finding.line = entry.line;
|
|
196
|
-
}
|
|
197
|
-
findings.push(finding);
|
|
198
|
-
}
|
|
199
|
-
return findings;
|
|
142
|
+
return parseProviderFindings(rawStdout, {
|
|
143
|
+
errorPrefix:
|
|
144
|
+
'[security-review] Failed to parse /security-review stdout as JSON',
|
|
145
|
+
mapSeverity: mapSecurityReviewSeverity,
|
|
146
|
+
defaultCategory: 'security',
|
|
147
|
+
});
|
|
200
148
|
}
|
|
201
149
|
|
|
202
150
|
/**
|
|
@@ -22,10 +22,8 @@
|
|
|
22
22
|
* that mock the upstream module URLs.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
runCloseValidation as defaultRunCloseValidation,
|
|
28
|
-
} from '../../../close-validation.js';
|
|
25
|
+
import { buildDefaultGates as defaultBuildDefaultGates } from '../../../close-validation/gates.js';
|
|
26
|
+
import { runCloseValidation as defaultRunCloseValidation } from '../../../close-validation/runner.js';
|
|
29
27
|
import { Logger } from '../../../Logger.js';
|
|
30
28
|
|
|
31
29
|
/**
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import path from 'node:path';
|
|
12
12
|
import { parseSprintArgs } from '../../../cli-args.js';
|
|
13
|
-
import { PROJECT_ROOT } from '../../../
|
|
13
|
+
import { PROJECT_ROOT } from '../../../project-root.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Resolve a flag value from an explicit override, a parsed CLI arg, or a
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import nodeFs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
runCloseValidation,
|
|
6
|
-
} from '../../close-validation.js';
|
|
3
|
+
import { buildDefaultGates } from '../../close-validation/gates.js';
|
|
4
|
+
import { runCloseValidation } from '../../close-validation/runner.js';
|
|
7
5
|
import { resolveConfig } from '../../config-resolver.js';
|
|
8
6
|
import { getStoryBranch, gitSync } from '../../git-utils.js';
|
|
9
7
|
import { Logger } from '../../Logger.js';
|
|
@@ -39,16 +39,20 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} from './ticket-lease.js';
|
|
42
|
+
acquireLeaseFailClosed,
|
|
43
|
+
resolveOperatorFromCandidates,
|
|
44
|
+
} from './lease-guard-shared.js';
|
|
45
|
+
import { releaseLease } from './ticket-lease.js';
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Resolve the operator handle used as the lease owner from resolved config.
|
|
49
|
-
* Routes through the shared
|
|
49
|
+
* Routes through the shared lease-guard kernel
|
|
50
|
+
* (`lease-guard-shared.resolveOperatorFromCandidates`) so a leading `@` is
|
|
50
51
|
* stripped (the assignees API expects bare logins, not `@`-prefixed mentions)
|
|
51
|
-
* and the self-held-claim comparison matches.
|
|
52
|
+
* and the self-held-claim comparison matches. The standalone surface's
|
|
53
|
+
* missing-handle policy is `'throw'` (intentional divergence from the plan
|
|
54
|
+
* path's `'null'`): init has no best-effort leg that can degrade, so an
|
|
55
|
+
* unowned lease must refuse immediately.
|
|
52
56
|
*
|
|
53
57
|
* @param {object} config Resolved `.agentrc.json` config.
|
|
54
58
|
* @returns {string} Bare operator handle.
|
|
@@ -58,17 +62,16 @@ import {
|
|
|
58
62
|
* path cannot safely serialise concurrent runs.
|
|
59
63
|
*/
|
|
60
64
|
export function resolveOperator(config) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
throw
|
|
65
|
+
return resolveOperatorFromCandidates({
|
|
66
|
+
candidates: [config?.github?.operatorHandle],
|
|
67
|
+
missingHandleBehavior: 'throw',
|
|
68
|
+
missingHandleMessage:
|
|
64
69
|
'single-story lease: no operator identity is configured. ' +
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
return handle;
|
|
70
|
+
'github.operatorHandle is unset or still the shipped `@[USERNAME]` ' +
|
|
71
|
+
'placeholder, so the standalone Story lease has no owner. Set your own ' +
|
|
72
|
+
'handle in .agentrc.local.json (e.g. { "github": { "operatorHandle": ' +
|
|
73
|
+
'"@your-login" } }) and re-run.',
|
|
74
|
+
});
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
/**
|
|
@@ -99,31 +102,25 @@ export async function acquireStoryLease({
|
|
|
99
102
|
now,
|
|
100
103
|
}) {
|
|
101
104
|
const owner = operator ?? resolveOperator(config);
|
|
102
|
-
// Fail closed: with no live-heartbeat source on the standalone path,
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
typeof now === 'number' && Number.isFinite(now) ? now : Date.now();
|
|
108
|
-
const result = await acquireLease({
|
|
105
|
+
// Fail closed: with no live-heartbeat source on the standalone path, the
|
|
106
|
+
// shared kernel anchors `heartbeatAt` to the same `now` the primitive
|
|
107
|
+
// evaluates against, so `isClaimLive` returns true for any foreign owner
|
|
108
|
+
// and `acquireLease` refuses unless `steal` is set.
|
|
109
|
+
return acquireLeaseFailClosed({
|
|
109
110
|
provider,
|
|
110
111
|
ticketId: storyId,
|
|
111
112
|
operator: owner,
|
|
112
|
-
heartbeatAt: resolvedNow,
|
|
113
113
|
steal,
|
|
114
114
|
config,
|
|
115
|
-
now
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
throw new Error(
|
|
115
|
+
now,
|
|
116
|
+
anchorHeartbeatToNow: true,
|
|
117
|
+
renderRefusal: (result) =>
|
|
119
118
|
`single-story lease: Story #${storyId} is currently held by @${result.owner}. ` +
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
return result;
|
|
119
|
+
'Another /single-story-deliver run owns this Story. Coordinate with that ' +
|
|
120
|
+
'operator, or re-run with --steal to forcibly transfer the claim once you ' +
|
|
121
|
+
'have confirmed the other run is dead. (The standalone path has no Epic ' +
|
|
122
|
+
'heartbeat ledger, so a foreign assignee always blocks unless stolen.)',
|
|
123
|
+
});
|
|
127
124
|
}
|
|
128
125
|
|
|
129
126
|
/**
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import fs from 'node:fs';
|
|
14
14
|
import path from 'node:path';
|
|
15
|
-
|
|
16
|
-
import { PROJECT_ROOT } from '../config-resolver.js';
|
|
17
15
|
import { Logger } from '../Logger.js';
|
|
16
|
+
import { PROJECT_ROOT } from '../project-root.js';
|
|
18
17
|
|
|
19
18
|
const POLICY_HEADING_RE = /^## Policy Capsule\s*$/;
|
|
20
19
|
const ANY_H2_RE = /^## /;
|