forge-workflow 0.1.0-beta.5 → 0.1.0-beta.6

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 (128) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +36 -0
  3. package/CLAUDE.md +0 -12
  4. package/CODING_STANDARDS.md +72 -0
  5. package/bin/forge.js +12 -1
  6. package/docs/guides/MIGRATION.md +3 -3
  7. package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +4 -0
  8. package/docs/reference/INSTALL.md +4 -0
  9. package/docs/reference/LEGACY_CLAIM_REPAIR.md +112 -0
  10. package/docs/reference/RELEASE.md +4 -4
  11. package/docs/reference/github-accounts.md +134 -0
  12. package/docs/reference/shepherd.md +63 -13
  13. package/lib/adapters/pr-state-adapter.js +15 -2
  14. package/lib/base-remote.js +138 -0
  15. package/lib/beta5-compatibility-evidence.js +1093 -0
  16. package/lib/bun-lockfile-proof.js +413 -0
  17. package/lib/bun-workflow-pins.js +461 -0
  18. package/lib/capabilities/index.js +9 -0
  19. package/lib/capabilities/model.js +141 -0
  20. package/lib/capabilities/probes.js +347 -0
  21. package/lib/codex-skills.js +2 -2
  22. package/lib/commands/_manifest.js +1 -0
  23. package/lib/commands/_registry.js +48 -18
  24. package/lib/commands/clean.js +57 -1
  25. package/lib/commands/doctor.js +37 -6
  26. package/lib/commands/gate.js +197 -27
  27. package/lib/commands/github.js +215 -0
  28. package/lib/commands/hooks.js +54 -6
  29. package/lib/commands/memory.js +66 -2
  30. package/lib/commands/merge.js +720 -73
  31. package/lib/commands/plan.js +33 -2
  32. package/lib/commands/pr.js +2 -0
  33. package/lib/commands/preflight.js +10 -2
  34. package/lib/commands/push.js +108 -6
  35. package/lib/commands/recall.js +95 -61
  36. package/lib/commands/release.js +23 -2
  37. package/lib/commands/remember.js +28 -4
  38. package/lib/commands/serve.js +26 -9
  39. package/lib/commands/setup.js +132 -4
  40. package/lib/commands/shepherd.js +578 -72
  41. package/lib/commands/ship.js +15 -69
  42. package/lib/commands/skill.js +8 -0
  43. package/lib/commands/team.js +47 -8
  44. package/lib/commands/test.js +163 -4
  45. package/lib/commands/validate.js +65 -21
  46. package/lib/commands/worktree.js +155 -19
  47. package/lib/fixtures/beta5-corpus/v1/README.md +9 -0
  48. package/lib/fixtures/beta5-corpus/v1/contract/command-contract.json +26 -0
  49. package/lib/fixtures/beta5-corpus/v1/contract/package-contract.json +13 -0
  50. package/lib/fixtures/beta5-corpus/v1/contract/workflow-stage-matrix.json +8 -0
  51. package/lib/fixtures/beta5-corpus/v1/manifest.json +25 -0
  52. package/lib/fixtures/beta5-corpus/v1/state/comments.jsonl +1 -0
  53. package/lib/fixtures/beta5-corpus/v1/state/config.yaml +6 -0
  54. package/lib/fixtures/beta5-corpus/v1/state/dependencies.jsonl +1 -0
  55. package/lib/fixtures/beta5-corpus/v1/state/issues.jsonl +2 -0
  56. package/lib/fixtures/beta5-corpus/v1/state/kernel.sql +20 -0
  57. package/lib/forge-issues.js +78 -0
  58. package/lib/gate-events.js +98 -10
  59. package/lib/github-context.js +308 -0
  60. package/lib/global-flags.js +1 -0
  61. package/lib/hook-renderer.js +29 -1
  62. package/lib/issue-render.js +19 -0
  63. package/lib/kernel/broker.js +723 -31
  64. package/lib/kernel/claim-reconciler.js +238 -0
  65. package/lib/kernel/lease-enforcer.js +9 -4
  66. package/lib/kernel/legacy-claim-repair.js +442 -0
  67. package/lib/kernel/live-claim-projection.js +26 -0
  68. package/lib/kernel/migrations.js +118 -3
  69. package/lib/kernel/readiness-model.js +184 -12
  70. package/lib/kernel/schema.js +49 -1
  71. package/lib/kernel/sqlite-driver.js +3322 -183
  72. package/lib/kernel/taxonomy-validator.js +4 -1
  73. package/lib/kernel/windows-private-acl.js +239 -0
  74. package/lib/memory/hygiene.js +191 -0
  75. package/lib/memory/router.js +94 -27
  76. package/lib/memory/usage-evidence.js +4 -0
  77. package/lib/memory-digest.js +59 -0
  78. package/lib/merge-rules.js +135 -17
  79. package/lib/npm-publish-workflow.js +233 -40
  80. package/lib/package-root.js +2 -0
  81. package/lib/pr-monitor/auto-actions.js +169 -28
  82. package/lib/pr-monitor/differ.js +110 -4
  83. package/lib/pr-monitor/events.js +0 -0
  84. package/lib/pr-monitor/flow-monitor.js +1424 -0
  85. package/lib/pr-monitor/gather.js +251 -44
  86. package/lib/pr-monitor/journal.js +0 -37
  87. package/lib/pr-monitor/monitor.js +117 -10
  88. package/lib/pr-monitor/process-identity.js +117 -0
  89. package/lib/pr-monitor/reconcile-executor.js +1101 -625
  90. package/lib/pr-monitor/reconcile.js +0 -0
  91. package/lib/pr-monitor/render-summary.js +121 -24
  92. package/lib/pr-monitor/review-preflight.js +269 -0
  93. package/lib/pr-monitor/shepherd-lease.js +28 -19
  94. package/lib/pr-monitor/verdict.js +438 -0
  95. package/lib/pr-monitor/watch-lifecycle.js +144 -38
  96. package/lib/pr-monitor/watch-owner.js +1414 -0
  97. package/lib/pr-monitor/watch.js +129 -58
  98. package/lib/pr-shepherd.js +17 -3
  99. package/lib/project-memory.js +145 -3
  100. package/lib/protected-state-authority.js +799 -4
  101. package/lib/protected-state-surfaces.js +181 -3
  102. package/lib/release-readiness.js +2 -3
  103. package/lib/review-adapter.js +65 -0
  104. package/lib/skills-sync.js +65 -32
  105. package/lib/validation/risk-manifest.js +339 -0
  106. package/lib/workflow/enforce-stage.js +44 -0
  107. package/lib/workflow/plan-authority.js +225 -0
  108. package/package.json +8 -4
  109. package/scripts/commitlint.js +13 -15
  110. package/scripts/generate-risk-manifest.js +91 -0
  111. package/scripts/github-context-bridge.sh +10 -0
  112. package/scripts/legacy-claim-repair.js +145 -0
  113. package/scripts/lib/behavioral-eval-runtime.js +3 -2
  114. package/scripts/process-tree.js +14 -2
  115. package/scripts/protected-state-check.js +440 -17
  116. package/scripts/sync-agent-skills.js +333 -34
  117. package/scripts/test-full-suite.js +704 -18
  118. package/scripts/test-profile.js +13 -3
  119. package/scripts/test.js +95 -14
  120. package/skills/coverage.json +1 -0
  121. package/skills/review/SKILL.md +2 -0
  122. package/skills/review/evals/scorecard.json +2 -2
  123. package/skills/setup/SKILL.md +18 -0
  124. package/skills/setup/evals/scorecard.json +3 -3
  125. package/skills/shepherd/SKILL.md +19 -2
  126. package/skills/shepherd/evals/scorecard.json +3 -3
  127. package/skills/validate/SKILL.md +3 -0
  128. package/skills/validate/evals/scorecard.json +1 -1
@@ -14,6 +14,107 @@
14
14
  */
15
15
 
16
16
  const { EVENT_TYPES: T, makeEvent } = require('./events');
17
+ const {
18
+ VERDICT_STATES,
19
+ normalizePrNumber,
20
+ normalizeRepository,
21
+ normalizeSha,
22
+ object,
23
+ readArrayItems,
24
+ readDataProperty,
25
+ } = require('./verdict');
26
+
27
+ const CURRENT_VERDICT_STATES = new Set(Object.values(VERDICT_STATES));
28
+
29
+ function compareText(left, right) {
30
+ if (left < right) return -1;
31
+ if (left > right) return 1;
32
+ return 0;
33
+ }
34
+
35
+ function normalizedReasonCodes(verdict) {
36
+ const reasons = readArrayItems(readDataProperty(verdict, 'reasons').value);
37
+ if (!reasons) return null;
38
+ const codes = [];
39
+ for (const entry of reasons) {
40
+ const code = readDataProperty(entry, 'code').value;
41
+ if (!object(entry) || typeof code !== 'string' || !code.trim()) return null;
42
+ codes.push(code.trim());
43
+ }
44
+ return [...new Set(codes)].sort(compareText);
45
+ }
46
+
47
+ function normalizeCurrentVerdict(verdict, { absent = false } = {}) {
48
+ if (absent && verdict == null) {
49
+ return {
50
+ state: null, repository: null, prNumber: null, headSha: null, baseSha: null, reasons: [],
51
+ };
52
+ }
53
+ const record = object(verdict);
54
+ const state = readDataProperty(record, 'state').value;
55
+ const repository = normalizeRepository(readDataProperty(record, 'repository').value);
56
+ const prNumber = normalizePrNumber(readDataProperty(record, 'prNumber').value);
57
+ const headSha = normalizeSha(readDataProperty(record, 'headSha').value);
58
+ const baseSha = normalizeSha(readDataProperty(record, 'baseSha').value);
59
+ const valid = record && CURRENT_VERDICT_STATES.has(state)
60
+ && repository && prNumber && headSha && baseSha;
61
+ const reasons = valid ? normalizedReasonCodes(verdict) : null;
62
+ if (!valid || reasons === null
63
+ || (state === VERDICT_STATES.MERGE_READY && reasons.length > 0)
64
+ || (state !== VERDICT_STATES.MERGE_READY && reasons.length === 0)) {
65
+ return {
66
+ state: VERDICT_STATES.INCOMPLETE,
67
+ repository: null,
68
+ prNumber: null,
69
+ headSha: null,
70
+ baseSha: null,
71
+ reasons: ['malformed_verdict'],
72
+ };
73
+ }
74
+ return {
75
+ state,
76
+ repository,
77
+ prNumber,
78
+ headSha,
79
+ baseSha,
80
+ reasons,
81
+ };
82
+ }
83
+
84
+ function difference(left, right) {
85
+ const rightSet = new Set(right);
86
+ return left.filter((value) => !rightSet.has(value));
87
+ }
88
+
89
+ /** Deterministically describe a transition between exact-current-head verdicts. */
90
+ function diffVerdictEvidence(previous, next) {
91
+ const before = normalizeCurrentVerdict(previous, { absent: true });
92
+ const after = normalizeCurrentVerdict(next);
93
+ const addedReasons = difference(after.reasons, before.reasons);
94
+ const removedReasons = difference(before.reasons, after.reasons);
95
+ const headChanged = before.headSha !== after.headSha;
96
+ const baseChanged = before.baseSha !== after.baseSha;
97
+ const repositoryChanged = before.repository !== after.repository;
98
+ const prChanged = before.prNumber !== after.prNumber;
99
+ const stateChanged = before.state !== after.state;
100
+ return {
101
+ changed: headChanged || baseChanged || repositoryChanged || prChanged || stateChanged
102
+ || addedReasons.length > 0 || removedReasons.length > 0,
103
+ headChanged,
104
+ stateChanged,
105
+ baseChanged,
106
+ repositoryChanged,
107
+ prChanged,
108
+ from: before.state,
109
+ to: after.state,
110
+ repository: after.repository,
111
+ prNumber: after.prNumber,
112
+ headSha: after.headSha,
113
+ baseSha: after.baseSha,
114
+ addedReasons,
115
+ removedReasons,
116
+ };
117
+ }
17
118
 
18
119
  /** Index an array of objects by a key field into a Map. */
19
120
  function indexBy(list, field) {
@@ -44,9 +145,9 @@ function diffChecks(prev, next, out) {
44
145
  const before = prevByName.get(String(c.name));
45
146
  const wasFailed = before?.class === 'failed';
46
147
  if (c.class === 'failed' && !wasFailed) {
47
- out.push(makeEvent(T.CHECK_FAILED, `${c.name}:${next.headSha}`, { name: c.name }));
148
+ out.push(makeEvent(T.CHECK_FAILED, `${c.name}:${next.headSha}`, { name: c.displayName || c.name }));
48
149
  } else if (c.class === 'green' && wasFailed) {
49
- out.push(makeEvent(T.CHECK_RECOVERED, `${c.name}:${next.headSha}`, { name: c.name }));
150
+ out.push(makeEvent(T.CHECK_RECOVERED, `${c.name}:${next.headSha}`, { name: c.displayName || c.name }));
50
151
  }
51
152
  }
52
153
  if (allGreen(next.checks) && !allGreen(prev.checks)) {
@@ -92,7 +193,9 @@ function diffReviews(prev, next, out) {
92
193
  || before.commitOid !== r.commitOid;
93
194
  if (changed) {
94
195
  out.push(makeEvent(T.REVIEW_SUBMITTED, `${r.author}:${r.commitOid || r.submittedAt}`, {
95
- author: r.author, verdict: r.state, commitOid: r.commitOid || null,
196
+ author: r.displayAuthor || r.author,
197
+ verdict: r.state,
198
+ commitOid: r.displayCommitOid || r.commitOid || null,
96
199
  }));
97
200
  }
98
201
  }
@@ -139,7 +242,9 @@ function diffDegraded(prev, next, out) {
139
242
  const prevSurfaces = new Set((prev.degraded || []).map((d) => d.surface));
140
243
  for (const d of (next.degraded || [])) {
141
244
  if (!prevSurfaces.has(d.surface)) {
142
- out.push(makeEvent(T.MONITOR_DEGRADED, d.surface, { surface: d.surface, error: d.error || '' }));
245
+ out.push(makeEvent(T.MONITOR_DEGRADED, d.surface, {
246
+ surface: d.displaySurface || d.surface, error: d.error || '',
247
+ }));
143
248
  }
144
249
  }
145
250
  }
@@ -190,6 +295,7 @@ function diffSnapshots(prev, next) {
190
295
 
191
296
  module.exports = {
192
297
  diffSnapshots,
298
+ diffVerdictEvidence,
193
299
  allGreen,
194
300
  indexBy,
195
301
  };
Binary file