mandrel 2.65.0 → 2.66.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 (56) hide show
  1. package/.agents/agents/acceptance-critic.md +5 -5
  2. package/.agents/agents/auditor.md +17 -18
  3. package/.agents/agents/plan-critic.md +5 -5
  4. package/.agents/agents/story-worker.md +5 -5
  5. package/.agents/docs/execution-reference.md +27 -5
  6. package/.agents/instructions.md +10 -12
  7. package/.agents/rules/ci-remediation.md +3 -3
  8. package/.agents/rules/gherkin-standards.md +3 -2
  9. package/.agents/rules/git-conventions-reference.md +12 -3
  10. package/.agents/rules/git-conventions.md +9 -7
  11. package/.agents/rules/testing-standards.md +8 -7
  12. package/.agents/runtime-deps.json +1 -1
  13. package/.agents/scripts/bootstrap.js +94 -89
  14. package/.agents/scripts/lib/baselines/duplication-scanner.js +17 -7
  15. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +78 -78
  16. package/.agents/scripts/lib/cli/standard-args.js +60 -76
  17. package/.agents/scripts/lib/cli-args.js +26 -0
  18. package/.agents/scripts/lib/config/gates/shared.js +3 -3
  19. package/.agents/scripts/lib/feedback-loop/graduate-steps.js +205 -0
  20. package/.agents/scripts/lib/feedback-loop/graduator-core.js +47 -782
  21. package/.agents/scripts/lib/feedback-loop/graduator-gh.js +449 -0
  22. package/.agents/scripts/lib/observability/close-telemetry.js +330 -0
  23. package/.agents/scripts/lib/observability/runtime-friction.js +2 -0
  24. package/.agents/scripts/lib/observability/signal-validator.js +17 -5
  25. package/.agents/scripts/lib/orchestration/code-review.js +22 -0
  26. package/.agents/scripts/lib/orchestration/plan-metrics.js +76 -63
  27. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +23 -0
  28. package/.agents/scripts/lib/orchestration/run-epilogue.js +6 -0
  29. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +2 -0
  30. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +349 -263
  31. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +21 -7
  32. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +4 -0
  33. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +327 -314
  34. package/.agents/scripts/lib/orchestration/ticket-validator.js +19 -36
  35. package/.agents/scripts/lib/signals/detectors/common.js +63 -51
  36. package/.agents/scripts/lib/transpile.js +28 -3
  37. package/.agents/scripts/single-story-close.js +10 -2
  38. package/.agents/scripts/single-story-confirm-merge.js +267 -238
  39. package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
  40. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -2
  41. package/.agents/workflows/audit-architecture.md +5 -4
  42. package/.agents/workflows/audit-documentation.md +5 -5
  43. package/.agents/workflows/audit-performance.md +10 -10
  44. package/.agents/workflows/helpers/acceptance-self-eval.md +8 -8
  45. package/.agents/workflows/helpers/audit-lens-core.md +30 -57
  46. package/.agents/workflows/helpers/deliver-digest.md +2 -2
  47. package/.agents/workflows/helpers/deliver-reference.md +3 -1
  48. package/.agents/workflows/helpers/deliver-story.md +6 -1
  49. package/.agents/workflows/helpers/parallel-tooling.md +16 -18
  50. package/.agents/workflows/mandrel-deliver.md +1 -1
  51. package/.agents/workflows/mandrel-plan.md +6 -5
  52. package/docs/CHANGELOG.md +26 -0
  53. package/lib/cli/guarded-sync.js +87 -0
  54. package/lib/cli/sync-agents.js +9 -92
  55. package/lib/cli/sync-commands.js +9 -101
  56. package/package.json +2 -2
@@ -25,6 +25,17 @@ function resolveFlag(paramValue, parsedValue) {
25
25
  return paramValue ?? parsedValue;
26
26
  }
27
27
 
28
+ /**
29
+ * A boolean flag: param beats parsed arg, absent reads as `false`.
30
+ *
31
+ * @param {unknown} paramValue
32
+ * @param {unknown} parsedValue
33
+ * @returns {boolean}
34
+ */
35
+ function booleanFlag(paramValue, parsedValue) {
36
+ return !!resolveFlag(paramValue, parsedValue);
37
+ }
38
+
28
39
  /**
29
40
  * Junk reads as absent (so the config default applies), never coerced.
30
41
  *
@@ -88,7 +99,7 @@ const RETIRED_FLAGS = Object.freeze({
88
99
  * @param {string[]} argv
89
100
  * @throws {Error}
90
101
  */
91
- function assertNoRetiredFlags(argv) {
102
+ export function assertNoRetiredFlags(argv) {
92
103
  for (const [flag, why] of Object.entries(RETIRED_FLAGS)) {
93
104
  const present = argv.some((a) => a === flag || a.startsWith(`${flag}=`));
94
105
  if (!present) continue;
@@ -102,8 +113,8 @@ function assertNoRetiredFlags(argv) {
102
113
  /**
103
114
  * Returns raw wait-for-merge intent; the runner resolves it after the arm.
104
115
  *
105
- * @param {{ storyIdParam, cwdParam, skipValidationParam, skipSyncParam, noAutoMergeParam, waitForMergeParam, noWaitForMergeParam, maxWaitSecondsParam, mergeWatchModeParam, rerunAdvisoryParam, overrideReviewBlockParam }} raw
106
- * @returns {{ storyId, cwd, skipValidation, skipSync, noAutoMerge, waitForMergeExplicit, noWaitForMerge, maxWaitSeconds, mergeWatchMode, rerunAdvisory, overrideReviewBlock }}
116
+ * @param {{ storyIdParam, cwdParam, skipValidationParam, skipSyncParam, noAutoMergeParam, waitForMergeParam, noWaitForMergeParam, maxWaitSecondsParam, mergeWatchModeParam, rerunAdvisoryParam, overrideReviewBlockParam, workerTokensParam }} raw
117
+ * @returns {{ storyId, cwd, skipValidation, skipSync, noAutoMerge, waitForMergeExplicit, noWaitForMerge, maxWaitSeconds, mergeWatchMode, rerunAdvisory, overrideReviewBlock, workerTokens }}
107
118
  */
108
119
  export function parseCloseOptions({
109
120
  storyIdParam,
@@ -117,6 +128,7 @@ export function parseCloseOptions({
117
128
  mergeWatchModeParam,
118
129
  rerunAdvisoryParam,
119
130
  overrideReviewBlockParam,
131
+ workerTokensParam,
120
132
  }) {
121
133
  // An injecting caller never reads argv (the host's flags are not its
122
134
  // business), so `parsed` stays empty and the retired-flag guard is skipped.
@@ -145,17 +157,19 @@ export function parseCloseOptions({
145
157
  resolveFlag(mergeWatchModeParam, parsed.mergeWatchMode),
146
158
  ),
147
159
  rerunAdvisory: intAtLeast(rerunAdvisory, 0),
148
- skipValidation: !!resolveFlag(skipValidationParam, parsed.skipValidation),
149
- skipSync: !!resolveFlag(skipSyncParam, parsed.skipSync),
150
- noAutoMerge: !!resolveFlag(noAutoMergeParam, parsed.noAutoMerge),
160
+ skipValidation: booleanFlag(skipValidationParam, parsed.skipValidation),
161
+ skipSync: booleanFlag(skipSyncParam, parsed.skipSync),
162
+ noAutoMerge: booleanFlag(noAutoMergeParam, parsed.noAutoMerge),
151
163
  waitForMergeExplicit:
152
164
  typeof waitForMergeExplicit === 'boolean'
153
165
  ? waitForMergeExplicit
154
166
  : undefined,
155
- noWaitForMerge: !!resolveFlag(noWaitForMergeParam, parsed.noWaitForMerge),
167
+ noWaitForMerge: booleanFlag(noWaitForMergeParam, parsed.noWaitForMerge),
156
168
  // Both doors validate, so neither can arm a reasonless override.
157
169
  overrideReviewBlock: parseOverrideReviewBlock(
158
170
  resolveFlag(overrideReviewBlockParam, parsed.overrideReviewBlock),
159
171
  ),
172
+ // Raw: validated best-effort by the runner, never thrown on.
173
+ workerTokens: resolveFlag(workerTokensParam, parsed.workerTokens),
160
174
  };
161
175
  }
@@ -65,6 +65,7 @@ async function postAuditRecord({ post, surface }) {
65
65
  * prUrl: string,
66
66
  * prNumber: number|null,
67
67
  * criticalCount: number,
68
+ * criticalByProvider?: Record<string, number>,
68
69
  * reason: string,
69
70
  * config?: object,
70
71
  * emitFrictionFn?: typeof emitRuntimeFriction,
@@ -77,6 +78,7 @@ export async function handleOverriddenReviewBlock({
77
78
  prUrl,
78
79
  prNumber,
79
80
  criticalCount,
81
+ criticalByProvider = {},
80
82
  reason,
81
83
  config,
82
84
  emitFrictionFn = emitRuntimeFriction,
@@ -104,6 +106,8 @@ export async function handleOverriddenReviewBlock({
104
106
  details: {
105
107
  prUrl,
106
108
  criticalCount,
109
+ // The false-positive proxy: attributed like the halt it rejected.
110
+ criticalByProvider,
107
111
  reason: reason.slice(0, REASON_SIGNAL_LIMIT),
108
112
  },
109
113
  config,