@aperant/framework 0.13.0 → 0.15.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 (241) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +1 -1
  3. package/agents/apt-pr-review-i18n.md +190 -0
  4. package/agents/apt-pr-review-xplatform.md +189 -0
  5. package/dist/cli/commands/audit-branch-current.d.mts +27 -5
  6. package/dist/cli/commands/audit-branch-current.d.mts.map +1 -1
  7. package/dist/cli/commands/audit-branch-current.mjs +3 -3
  8. package/dist/cli/commands/audit-branch-current.mjs.map +1 -1
  9. package/dist/cli/commands/event.d.mts.map +1 -1
  10. package/dist/cli/commands/event.mjs +6 -4
  11. package/dist/cli/commands/event.mjs.map +1 -1
  12. package/dist/cli/commands/fan-out.d.mts.map +1 -1
  13. package/dist/cli/commands/fan-out.mjs +3 -1
  14. package/dist/cli/commands/fan-out.mjs.map +1 -1
  15. package/dist/cli/commands/features-audit.d.mts.map +1 -1
  16. package/dist/cli/commands/features-audit.mjs +6 -1
  17. package/dist/cli/commands/features-audit.mjs.map +1 -1
  18. package/dist/cli/commands/followups.d.mts +5 -0
  19. package/dist/cli/commands/followups.d.mts.map +1 -0
  20. package/dist/cli/commands/followups.mjs +266 -0
  21. package/dist/cli/commands/followups.mjs.map +1 -0
  22. package/dist/cli/commands/health-check.d.mts.map +1 -1
  23. package/dist/cli/commands/health-check.mjs +3 -1
  24. package/dist/cli/commands/health-check.mjs.map +1 -1
  25. package/dist/cli/commands/merge-detect.d.mts +29 -0
  26. package/dist/cli/commands/merge-detect.d.mts.map +1 -0
  27. package/dist/cli/commands/merge-detect.mjs +196 -0
  28. package/dist/cli/commands/merge-detect.mjs.map +1 -0
  29. package/dist/cli/commands/merge-integrate.d.mts +28 -0
  30. package/dist/cli/commands/merge-integrate.d.mts.map +1 -0
  31. package/dist/cli/commands/merge-integrate.mjs +383 -0
  32. package/dist/cli/commands/merge-integrate.mjs.map +1 -0
  33. package/dist/cli/commands/pr-review/detect-specialists.d.mts +58 -0
  34. package/dist/cli/commands/pr-review/detect-specialists.d.mts.map +1 -0
  35. package/dist/cli/commands/pr-review/detect-specialists.mjs +980 -0
  36. package/dist/cli/commands/pr-review/detect-specialists.mjs.map +1 -0
  37. package/dist/cli/commands/pr-review.d.mts.map +1 -1
  38. package/dist/cli/commands/pr-review.mjs +11 -2
  39. package/dist/cli/commands/pr-review.mjs.map +1 -1
  40. package/dist/cli/commands/precompact-hook.d.mts.map +1 -1
  41. package/dist/cli/commands/precompact-hook.mjs +10 -6
  42. package/dist/cli/commands/precompact-hook.mjs.map +1 -1
  43. package/dist/cli/commands/roadmap.d.mts.map +1 -1
  44. package/dist/cli/commands/roadmap.mjs +24 -11
  45. package/dist/cli/commands/roadmap.mjs.map +1 -1
  46. package/dist/cli/commands/seed.d.mts.map +1 -1
  47. package/dist/cli/commands/seed.mjs +3 -1
  48. package/dist/cli/commands/seed.mjs.map +1 -1
  49. package/dist/cli/commands/state.d.mts.map +1 -1
  50. package/dist/cli/commands/state.mjs +9 -3
  51. package/dist/cli/commands/state.mjs.map +1 -1
  52. package/dist/cli/commands/statusline.d.mts.map +1 -1
  53. package/dist/cli/commands/statusline.mjs +5 -1
  54. package/dist/cli/commands/statusline.mjs.map +1 -1
  55. package/dist/cli/commands/task.d.mts.map +1 -1
  56. package/dist/cli/commands/task.mjs +126 -23
  57. package/dist/cli/commands/task.mjs.map +1 -1
  58. package/dist/cli/commands/worktree.d.mts +1 -1
  59. package/dist/cli/commands/worktree.d.mts.map +1 -1
  60. package/dist/cli/commands/worktree.mjs +282 -83
  61. package/dist/cli/commands/worktree.mjs.map +1 -1
  62. package/dist/cli/config/post-merge-sweep.d.mts.map +1 -1
  63. package/dist/cli/config/post-merge-sweep.mjs +3 -2
  64. package/dist/cli/config/post-merge-sweep.mjs.map +1 -1
  65. package/dist/cli/config/share-policy.d.mts +3 -1
  66. package/dist/cli/config/share-policy.d.mts.map +1 -1
  67. package/dist/cli/config/share-policy.mjs +16 -3
  68. package/dist/cli/config/share-policy.mjs.map +1 -1
  69. package/dist/cli/config/upgrade-gitignore.d.mts.map +1 -1
  70. package/dist/cli/config/upgrade-gitignore.mjs +27 -5
  71. package/dist/cli/config/upgrade-gitignore.mjs.map +1 -1
  72. package/dist/cli/consistency/parse-qa.mjs +12 -1
  73. package/dist/cli/consistency/parse-qa.mjs.map +1 -1
  74. package/dist/cli/consistency/parse-review.d.mts +23 -0
  75. package/dist/cli/consistency/parse-review.d.mts.map +1 -1
  76. package/dist/cli/consistency/parse-review.mjs +36 -0
  77. package/dist/cli/consistency/parse-review.mjs.map +1 -1
  78. package/dist/cli/consistency/parse-spec.d.mts +16 -0
  79. package/dist/cli/consistency/parse-spec.d.mts.map +1 -1
  80. package/dist/cli/consistency/parse-spec.mjs +44 -0
  81. package/dist/cli/consistency/parse-spec.mjs.map +1 -1
  82. package/dist/cli/coordination/agent-identity.d.mts +5 -2
  83. package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
  84. package/dist/cli/coordination/agent-identity.mjs +6 -4
  85. package/dist/cli/coordination/agent-identity.mjs.map +1 -1
  86. package/dist/cli/coordination/store.d.mts +1 -1
  87. package/dist/cli/dispatch.d.mts.map +1 -1
  88. package/dist/cli/dispatch.mjs +4 -0
  89. package/dist/cli/dispatch.mjs.map +1 -1
  90. package/dist/cli/followups/derive.d.mts +63 -0
  91. package/dist/cli/followups/derive.d.mts.map +1 -0
  92. package/dist/cli/followups/derive.mjs +115 -0
  93. package/dist/cli/followups/derive.mjs.map +1 -0
  94. package/dist/cli/followups/schema.d.mts +165 -0
  95. package/dist/cli/followups/schema.d.mts.map +1 -0
  96. package/dist/cli/followups/schema.mjs +251 -0
  97. package/dist/cli/followups/schema.mjs.map +1 -0
  98. package/dist/cli/gate/context.d.mts +1 -1
  99. package/dist/cli/gate/gates/followups-adjudicated.d.mts +69 -0
  100. package/dist/cli/gate/gates/followups-adjudicated.d.mts.map +1 -0
  101. package/dist/cli/gate/gates/followups-adjudicated.mjs +141 -0
  102. package/dist/cli/gate/gates/followups-adjudicated.mjs.map +1 -0
  103. package/dist/cli/gate/gates/index.mjs +1 -0
  104. package/dist/cli/gate/gates/index.mjs.map +1 -1
  105. package/dist/cli/git/materialize-env.d.mts +39 -0
  106. package/dist/cli/git/materialize-env.d.mts.map +1 -0
  107. package/dist/cli/git/materialize-env.mjs +217 -0
  108. package/dist/cli/git/materialize-env.mjs.map +1 -0
  109. package/dist/cli/help.d.mts.map +1 -1
  110. package/dist/cli/help.mjs +9 -1
  111. package/dist/cli/help.mjs.map +1 -1
  112. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  113. package/dist/cli/install/legacy-paths.mjs +4 -0
  114. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  115. package/dist/cli/roadmap/lifecycle.d.mts.map +1 -1
  116. package/dist/cli/roadmap/lifecycle.mjs +4 -1
  117. package/dist/cli/roadmap/lifecycle.mjs.map +1 -1
  118. package/dist/cli/task/ids.d.mts +9 -0
  119. package/dist/cli/task/ids.d.mts.map +1 -1
  120. package/dist/cli/task/ids.mjs +9 -0
  121. package/dist/cli/task/ids.mjs.map +1 -1
  122. package/dist/cli/task/index-md.d.mts +5 -0
  123. package/dist/cli/task/index-md.d.mts.map +1 -1
  124. package/dist/cli/task/index-md.mjs +12 -4
  125. package/dist/cli/task/index-md.mjs.map +1 -1
  126. package/dist/cli/util/io.d.mts +6 -0
  127. package/dist/cli/util/io.d.mts.map +1 -1
  128. package/dist/cli/util/io.mjs +16 -1
  129. package/dist/cli/util/io.mjs.map +1 -1
  130. package/dist/cli/util/project.d.mts +7 -2
  131. package/dist/cli/util/project.d.mts.map +1 -1
  132. package/dist/cli/util/project.mjs +11 -14
  133. package/dist/cli/util/project.mjs.map +1 -1
  134. package/dist/cli/util/state-paths.d.mts +19 -0
  135. package/dist/cli/util/state-paths.d.mts.map +1 -0
  136. package/dist/cli/util/state-paths.mjs +45 -0
  137. package/dist/cli/util/state-paths.mjs.map +1 -0
  138. package/dist/plugin/.claude-plugin/plugin.json +4 -1
  139. package/dist/plugin/agents/apt-pr-review-i18n.md +190 -0
  140. package/dist/plugin/agents/apt-pr-review-xplatform.md +189 -0
  141. package/dist/plugin/skills/apt/SKILL.md +9 -3
  142. package/dist/plugin/skills/apt-close-task/SKILL.md +48 -0
  143. package/dist/plugin/skills/apt-debug/SKILL.md +19 -9
  144. package/dist/plugin/skills/apt-execute/SKILL.md +3 -1
  145. package/dist/plugin/skills/apt-fan-out/SKILL.md +65 -1
  146. package/dist/plugin/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
  147. package/dist/plugin/skills/apt-pr-review/SCHEMA.md +4 -2
  148. package/dist/plugin/skills/apt-pr-review/SKILL.md +117 -29
  149. package/dist/plugin/skills/apt-quick/SKILL.md +24 -1
  150. package/dist/plugin/skills/apt-review/SKILL.md +6 -0
  151. package/dist/plugin/skills/apt-run/SKILL.md +1 -1
  152. package/dist/plugin/skills/apt-setup/SKILL.md +21 -3
  153. package/dist/plugin/skills/apt-ship/SKILL.md +32 -11
  154. package/dist/plugin/skills/apt-terminal/SKILL.md +8 -0
  155. package/dist/plugin/skills/apt-triage/SKILL.md +4 -0
  156. package/dist/plugin/skills/apt-verify/SKILL.md +24 -0
  157. package/dist/plugin/skills/apt-watch-ci/SKILL.md +3 -1
  158. package/dist/types/config.d.ts +33 -0
  159. package/dist/types/config.d.ts.map +1 -1
  160. package/package.json +1 -1
  161. package/prompts/conductor-framework-context.md +1 -1
  162. package/prompts/github/pr_i18n_agent.md +279 -0
  163. package/prompts/github/pr_xplatform_agent.md +283 -0
  164. package/prompts/inbox-clarification.md +18 -11
  165. package/skills/apt/SKILL.md +9 -3
  166. package/skills/apt-close-task/SKILL.md +48 -0
  167. package/skills/apt-debug/SKILL.md +19 -9
  168. package/skills/apt-execute/SKILL.md +3 -1
  169. package/skills/apt-fan-out/SKILL.md +65 -1
  170. package/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
  171. package/skills/apt-pr-review/SCHEMA.md +4 -2
  172. package/skills/apt-pr-review/SKILL.md +117 -29
  173. package/skills/apt-quick/SKILL.md +24 -1
  174. package/skills/apt-review/SKILL.md +6 -0
  175. package/skills/apt-run/SKILL.md +1 -1
  176. package/skills/apt-setup/SKILL.md +21 -3
  177. package/skills/apt-ship/SKILL.md +32 -11
  178. package/skills/apt-terminal/SKILL.md +8 -0
  179. package/skills/apt-triage/SKILL.md +4 -0
  180. package/skills/apt-verify/SKILL.md +24 -0
  181. package/skills/apt-watch-ci/SKILL.md +3 -1
  182. package/src/cli/commands/audit-branch-current.mjs +3 -3
  183. package/src/cli/commands/event.mjs +6 -4
  184. package/src/cli/commands/fan-out.mjs +3 -1
  185. package/src/cli/commands/features-audit.mjs +6 -1
  186. package/src/cli/commands/followups.mjs +303 -0
  187. package/src/cli/commands/health-check.mjs +3 -1
  188. package/src/cli/commands/merge-detect.mjs +203 -0
  189. package/src/cli/commands/merge-integrate.mjs +392 -0
  190. package/src/cli/commands/pr-review/__fixtures__/android-strings/app/src/main/res/values-fr/strings.xml +3 -0
  191. package/src/cli/commands/pr-review/__fixtures__/babel-js/package.json +4 -0
  192. package/src/cli/commands/pr-review/__fixtures__/c-ifdef/src/main.c +4 -0
  193. package/src/cli/commands/pr-review/__fixtures__/ci-matrix/.github/workflows/ci.yml +10 -0
  194. package/src/cli/commands/pr-review/__fixtures__/cmake-win/CMakeLists.txt +5 -0
  195. package/src/cli/commands/pr-review/__fixtures__/diffs/add-arb.patch +9 -0
  196. package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-dep.patch +13 -0
  197. package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-list-item-dep.patch +17 -0
  198. package/src/cli/commands/pr-review/__fixtures__/diffs/lone-weak-t.patch +8 -0
  199. package/src/cli/commands/pr-review/__fixtures__/diffs/monorepo-b.patch +7 -0
  200. package/src/cli/commands/pr-review/__fixtures__/diffs/two-weak-xpl.patch +12 -0
  201. package/src/cli/commands/pr-review/__fixtures__/dropped-underscore/src/app.js +2 -0
  202. package/src/cli/commands/pr-review/__fixtures__/electron-app/package.json +4 -0
  203. package/src/cli/commands/pr-review/__fixtures__/i18n-locale-file/src/locales/fr.json +1 -0
  204. package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/a/locales/fr.json +1 -0
  205. package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/b/src/index.ts +1 -0
  206. package/src/cli/commands/pr-review/__fixtures__/py-babel/pyproject.toml +3 -0
  207. package/src/cli/commands/pr-review/__fixtures__/qt-i18n-dir/i18n/app_fr.ts +11 -0
  208. package/src/cli/commands/pr-review/__fixtures__/rust-cli/Cargo.toml +7 -0
  209. package/src/cli/commands/pr-review/__fixtures__/rust-cli/src/main.rs +1 -0
  210. package/src/cli/commands/pr-review/__fixtures__/ts-dir/ts/foo.ts +3 -0
  211. package/src/cli/commands/pr-review/detect-specialists.mjs +1023 -0
  212. package/src/cli/commands/pr-review.mjs +12 -2
  213. package/src/cli/commands/precompact-hook.mjs +10 -6
  214. package/src/cli/commands/roadmap.mjs +24 -11
  215. package/src/cli/commands/seed.mjs +3 -1
  216. package/src/cli/commands/state.mjs +9 -3
  217. package/src/cli/commands/statusline.mjs +5 -1
  218. package/src/cli/commands/task.mjs +135 -23
  219. package/src/cli/commands/worktree.mjs +298 -81
  220. package/src/cli/config/post-merge-sweep.mjs +3 -2
  221. package/src/cli/config/share-policy.mjs +16 -3
  222. package/src/cli/config/upgrade-gitignore.mjs +27 -5
  223. package/src/cli/consistency/parse-qa.mjs +11 -1
  224. package/src/cli/consistency/parse-review.mjs +36 -0
  225. package/src/cli/consistency/parse-spec.mjs +43 -0
  226. package/src/cli/coordination/agent-identity.mjs +6 -4
  227. package/src/cli/dispatch.mjs +4 -0
  228. package/src/cli/followups/derive.mjs +123 -0
  229. package/src/cli/followups/schema.mjs +264 -0
  230. package/src/cli/gate/gates/followups-adjudicated.mjs +158 -0
  231. package/src/cli/gate/gates/index.mjs +1 -0
  232. package/src/cli/git/materialize-env.mjs +212 -0
  233. package/src/cli/help.mjs +9 -1
  234. package/src/cli/install/legacy-paths.mjs +4 -0
  235. package/src/cli/roadmap/lifecycle.mjs +4 -1
  236. package/src/cli/task/ids.mjs +9 -0
  237. package/src/cli/task/index-md.mjs +12 -4
  238. package/src/cli/util/io.mjs +15 -1
  239. package/src/cli/util/project.mjs +11 -14
  240. package/src/cli/util/state-paths.mjs +45 -0
  241. package/prompts/followup_planner.md +0 -399
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @internal
3
+ * followups/schema.mjs — validate the per-task followups.json ledger (G45).
4
+ *
5
+ * Pure: takes a parsed JSON document, returns a normalized shape with
6
+ * structured `schema_errors[]`. Never throws, never touches the filesystem
7
+ * (mirrors the consistency-parser style).
8
+ *
9
+ * Row shape:
10
+ * {
11
+ * id: string, // free id (e.g. oos-1, rev-rf-3, qa-2, or a voluntary id)
12
+ * title: string,
13
+ * class_proposed: 'in-pr' | 'new-task' | 'polish', // a PROPOSAL — adjudication is authority (ID-03)
14
+ * origin: 'plan' | 'discuss' | 'execute' | 'verify' | 'review' | 'ci',
15
+ * files: string[],
16
+ * outcome_refs: string[], // 'O<n>' ids validated elsewhere (derive.validateOutcomeRefs)
17
+ * status: 'open' | 'fixed' | 'dispositioned',
18
+ * adjudication?: {
19
+ * verdict: 'load-bearing' | 'deferrable',
20
+ * by: 'verify' | 'verify-proof',
21
+ * outcome_ref?: string | null // nullable — refactor-only specs have no outcomes (ID-01)
22
+ * },
23
+ * disposition?: {
24
+ * kind: 'filed_task' | 'executed_commit' | 'parked_note' | 'dropped_by_user',
25
+ * ref: string,
26
+ * reason?: string // required for dropped_by_user (enforced at the CLI seam)
27
+ * }
28
+ * }
29
+ *
30
+ * Output:
31
+ * { rows: ValidRow[], schema_errors: [{row_index, id?, field, message}] }
32
+ *
33
+ * A row that fails validation is reported in schema_errors and EXCLUDED from
34
+ * rows[] (so downstream gate logic never reasons over a malformed row).
35
+ */
36
+ export const CLASS_PROPOSED = new Set(['in-pr', 'new-task', 'polish']);
37
+ export const ORIGINS = new Set(['plan', 'discuss', 'execute', 'verify', 'review', 'ci']);
38
+ export const STATUSES = new Set(['open', 'fixed', 'dispositioned']);
39
+ export const VERDICTS = new Set(['load-bearing', 'deferrable']);
40
+ export const ADJUDICATORS = new Set(['verify', 'verify-proof']);
41
+ export const DISPOSITION_KINDS = new Set([
42
+ 'filed_task',
43
+ 'executed_commit',
44
+ 'parked_note',
45
+ 'dropped_by_user',
46
+ ]);
47
+ /**
48
+ * @typedef {Object} FollowupAdjudication
49
+ * @property {'load-bearing'|'deferrable'} verdict
50
+ * @property {'verify'|'verify-proof'} by
51
+ * @property {string|null} [outcome_ref]
52
+ *
53
+ * @typedef {Object} FollowupDisposition
54
+ * @property {'filed_task'|'executed_commit'|'parked_note'|'dropped_by_user'} kind
55
+ * @property {string} ref
56
+ * @property {string} [reason]
57
+ *
58
+ * @typedef {Object} FollowupRow
59
+ * @property {string} id
60
+ * @property {string} title
61
+ * @property {'in-pr'|'new-task'|'polish'} class_proposed
62
+ * @property {'plan'|'discuss'|'execute'|'verify'|'review'|'ci'} origin
63
+ * @property {string[]} files
64
+ * @property {string[]} outcome_refs
65
+ * @property {'open'|'fixed'|'dispositioned'} status
66
+ * @property {FollowupAdjudication} [adjudication]
67
+ * @property {FollowupDisposition} [disposition]
68
+ *
69
+ * @typedef {Object} ParsedFollowups
70
+ * @property {FollowupRow[]} rows
71
+ * @property {Array<{row_index: number, id?: string, field: string, message: string}>} schema_errors
72
+ *
73
+ * The selector helpers below read only `status` / `adjudication` /
74
+ * `disposition`, so they accept a structural row shape (any caller-built row
75
+ * with those fields fits) and return the same element type they were given.
76
+ * @typedef {{status?: string, adjudication?: {verdict?: string}, disposition?: {kind?: string, ref?: string}}} SelectorRow
77
+ */
78
+ /**
79
+ * @param {unknown} doc — a parsed followups.json document. Accepts either
80
+ * `{ rows: [...] }` or a bare `[...]` array of rows.
81
+ * @returns {ParsedFollowups}
82
+ */
83
+ export function parseFollowups(doc) {
84
+ /** @type {Array<{row_index: number, id?: string, field: string, message: string}>} */
85
+ const schema_errors = [];
86
+ /** @type {Array<object>} */
87
+ const rows = [];
88
+ const rawRows = extractRows(doc);
89
+ if (rawRows === null) {
90
+ schema_errors.push({
91
+ row_index: -1,
92
+ field: 'rows',
93
+ message: 'followups.json must be an array of rows or an object with a `rows` array',
94
+ });
95
+ return { rows, schema_errors };
96
+ }
97
+ for (let i = 0; i < rawRows.length; i++) {
98
+ const r = rawRows[i];
99
+ const errsBefore = schema_errors.length;
100
+ if (!r || typeof r !== 'object' || Array.isArray(r)) {
101
+ schema_errors.push({ row_index: i, field: 'row', message: 'row must be an object' });
102
+ continue;
103
+ }
104
+ const id = typeof r.id === 'string' && r.id.trim().length > 0 ? r.id : undefined;
105
+ const push = (field, message) => schema_errors.push({ row_index: i, id, field, message });
106
+ if (!id)
107
+ push('id', 'missing or empty `id`');
108
+ if (typeof r.title !== 'string' || r.title.trim().length === 0)
109
+ push('title', 'missing or empty `title`');
110
+ if (!CLASS_PROPOSED.has(r.class_proposed))
111
+ push('class_proposed', `must be one of: ${[...CLASS_PROPOSED].join(', ')}`);
112
+ if (!ORIGINS.has(r.origin))
113
+ push('origin', `must be one of: ${[...ORIGINS].join(', ')}`);
114
+ if (!STATUSES.has(r.status))
115
+ push('status', `must be one of: ${[...STATUSES].join(', ')}`);
116
+ if (r.files !== undefined && !isStringArray(r.files))
117
+ push('files', 'must be a string array');
118
+ if (r.outcome_refs !== undefined && !isStringArray(r.outcome_refs))
119
+ push('outcome_refs', 'must be a string array of O<n> ids');
120
+ if (r.adjudication !== undefined) {
121
+ const a = r.adjudication;
122
+ if (!a || typeof a !== 'object' || Array.isArray(a)) {
123
+ push('adjudication', 'must be an object when present');
124
+ }
125
+ else {
126
+ if (!VERDICTS.has(a.verdict))
127
+ push('adjudication.verdict', `must be one of: ${[...VERDICTS].join(', ')}`);
128
+ if (!ADJUDICATORS.has(a.by))
129
+ push('adjudication.by', `must be one of: ${[...ADJUDICATORS].join(', ')}`);
130
+ if (a.outcome_ref !== undefined &&
131
+ a.outcome_ref !== null &&
132
+ typeof a.outcome_ref !== 'string')
133
+ push('adjudication.outcome_ref', 'must be a string, null, or omitted');
134
+ }
135
+ }
136
+ if (r.disposition !== undefined) {
137
+ const d = r.disposition;
138
+ if (!d || typeof d !== 'object' || Array.isArray(d)) {
139
+ push('disposition', 'must be an object when present');
140
+ }
141
+ else {
142
+ if (!DISPOSITION_KINDS.has(d.kind))
143
+ push('disposition.kind', `must be one of: ${[...DISPOSITION_KINDS].join(', ')}`);
144
+ if (typeof d.ref !== 'string' || d.ref.trim().length === 0)
145
+ push('disposition.ref', 'missing or empty `ref`');
146
+ }
147
+ }
148
+ if (schema_errors.length === errsBefore) {
149
+ rows.push({
150
+ id,
151
+ title: r.title,
152
+ class_proposed: r.class_proposed,
153
+ origin: r.origin,
154
+ files: Array.isArray(r.files) ? r.files : [],
155
+ outcome_refs: Array.isArray(r.outcome_refs) ? r.outcome_refs : [],
156
+ status: r.status,
157
+ ...(r.adjudication !== undefined
158
+ ? { adjudication: normalizeAdjudication(r.adjudication) }
159
+ : {}),
160
+ ...(r.disposition !== undefined
161
+ ? { disposition: normalizeDisposition(r.disposition) }
162
+ : {}),
163
+ });
164
+ }
165
+ }
166
+ return { rows, schema_errors };
167
+ }
168
+ /**
169
+ * Rows that block `task close`: any `open` row, or any `dispositioned` row
170
+ * without a valid `disposition.kind` + `ref`. (A `fixed` row is settled.)
171
+ *
172
+ * @template {SelectorRow} T
173
+ * @param {{rows: T[]}} parsed
174
+ * @returns {T[]}
175
+ */
176
+ export function listBlockingRowsForClose(parsed) {
177
+ const rows = parsed && Array.isArray(parsed.rows) ? parsed.rows : [];
178
+ return rows.filter((r) => {
179
+ if (r.status === 'open')
180
+ return true;
181
+ if (r.status === 'dispositioned') {
182
+ const d = r.disposition;
183
+ return (!d ||
184
+ !DISPOSITION_KINDS.has(d.kind) ||
185
+ typeof d.ref !== 'string' ||
186
+ d.ref.trim().length === 0);
187
+ }
188
+ return false;
189
+ });
190
+ }
191
+ /**
192
+ * Open rows that have no `adjudication` (ship-gate input).
193
+ *
194
+ * @template {SelectorRow} T
195
+ * @param {{rows: T[]}} parsed
196
+ * @returns {T[]}
197
+ */
198
+ export function listUnadjudicatedOpen(parsed) {
199
+ const rows = parsed && Array.isArray(parsed.rows) ? parsed.rows : [];
200
+ return rows.filter((r) => r.status === 'open' && !r.adjudication);
201
+ }
202
+ /**
203
+ * Load-bearing rows that are not yet fixed (ship-gate input).
204
+ *
205
+ * @template {SelectorRow} T
206
+ * @param {{rows: T[]}} parsed
207
+ * @returns {T[]}
208
+ */
209
+ export function listLoadBearingUnfixed(parsed) {
210
+ const rows = parsed && Array.isArray(parsed.rows) ? parsed.rows : [];
211
+ return rows.filter((r) => r.adjudication && r.adjudication.verdict === 'load-bearing' && r.status !== 'fixed');
212
+ }
213
+ /**
214
+ * Rows whose `status === 'dispositioned'` lack a valid disposition record.
215
+ *
216
+ * @template {SelectorRow} T
217
+ * @param {{rows: T[]}} parsed
218
+ * @returns {T[]}
219
+ */
220
+ export function listUndispositioned(parsed) {
221
+ const rows = parsed && Array.isArray(parsed.rows) ? parsed.rows : [];
222
+ return rows.filter((r) => {
223
+ if (r.status !== 'dispositioned')
224
+ return false;
225
+ const d = r.disposition;
226
+ return (!d || !DISPOSITION_KINDS.has(d.kind) || typeof d.ref !== 'string' || d.ref.trim().length === 0);
227
+ });
228
+ }
229
+ function extractRows(doc) {
230
+ if (Array.isArray(doc))
231
+ return doc;
232
+ if (doc && typeof doc === 'object' && Array.isArray(doc.rows))
233
+ return doc.rows;
234
+ return null;
235
+ }
236
+ function isStringArray(v) {
237
+ return Array.isArray(v) && v.every((x) => typeof x === 'string');
238
+ }
239
+ function normalizeAdjudication(a) {
240
+ const out = { verdict: a.verdict, by: a.by };
241
+ if (a.outcome_ref !== undefined)
242
+ out.outcome_ref = a.outcome_ref;
243
+ return out;
244
+ }
245
+ function normalizeDisposition(d) {
246
+ const out = { kind: d.kind, ref: d.ref };
247
+ if (typeof d.reason === 'string')
248
+ out.reason = d.reason;
249
+ return out;
250
+ }
251
+ //# sourceMappingURL=schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.mjs","sourceRoot":"","sources":["../../../src/cli/followups/schema.mjs"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export function buildGateContext(projectRoot: any, taskId: any): {
9
9
  projectRoot: string;
10
- sharedRoot: any;
10
+ sharedRoot: string;
11
11
  taskId: string;
12
12
  taskDir: string;
13
13
  taskRecord: any;
@@ -0,0 +1,69 @@
1
+ export default gate;
2
+ declare namespace gate {
3
+ let id: string;
4
+ let description: string;
5
+ let severity: string;
6
+ let skills: string[];
7
+ function applies_to_profile(ctx: any): boolean;
8
+ function check(ctx: any): Promise<{
9
+ status: string;
10
+ reason: string;
11
+ inputs: string[];
12
+ evidence?: undefined;
13
+ } | {
14
+ status: string;
15
+ reason: string;
16
+ evidence: {
17
+ out_of_scope_bullets: string[];
18
+ missing_expected?: undefined;
19
+ unadjudicated_open?: undefined;
20
+ load_bearing_unfixed?: undefined;
21
+ };
22
+ inputs: string[];
23
+ } | {
24
+ status: string;
25
+ reason: string;
26
+ evidence: {
27
+ missing_expected: {
28
+ id: string;
29
+ title: string;
30
+ origin: string;
31
+ }[];
32
+ out_of_scope_bullets?: undefined;
33
+ unadjudicated_open?: undefined;
34
+ load_bearing_unfixed?: undefined;
35
+ };
36
+ inputs: string[];
37
+ } | {
38
+ status: string;
39
+ reason: string;
40
+ evidence: {
41
+ unadjudicated_open: {
42
+ id: any;
43
+ title: any;
44
+ status: any;
45
+ verdict: any;
46
+ }[];
47
+ out_of_scope_bullets?: undefined;
48
+ missing_expected?: undefined;
49
+ load_bearing_unfixed?: undefined;
50
+ };
51
+ inputs: string[];
52
+ } | {
53
+ status: string;
54
+ reason: string;
55
+ evidence: {
56
+ load_bearing_unfixed: {
57
+ id: any;
58
+ title: any;
59
+ status: any;
60
+ verdict: any;
61
+ }[];
62
+ out_of_scope_bullets?: undefined;
63
+ missing_expected?: undefined;
64
+ unadjudicated_open?: undefined;
65
+ };
66
+ inputs: string[];
67
+ }>;
68
+ }
69
+ //# sourceMappingURL=followups-adjudicated.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"followups-adjudicated.d.mts","sourceRoot":"","sources":["../../../../src/cli/gate/gates/followups-adjudicated.mjs"],"names":[],"mappings":";;;;;;IAuDqB,+CAAwC;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiGC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @internal
3
+ * G45 followups-adjudicated — blocking gate for `apt:ship` (full-pipeline only).
4
+ *
5
+ * The deterministic part the deferring agent can't talk past: shipping is
6
+ * blocked until every open follow-up row carries an adjudication and every
7
+ * load-bearing row is fixed. The ledger derivation also forces adoption —
8
+ * a spec.md with `## Out of Scope` bullets but no followups.json fails.
9
+ *
10
+ * Fails when:
11
+ * (a) spec.md has Out of Scope bullets but followups.json is absent
12
+ * (adoption forcing function),
13
+ * (b) the derived expected universe has rows missing from the ledger,
14
+ * (c) any `status: 'open'` row lacks `adjudication`,
15
+ * (d) any `verdict: 'load-bearing'` row has `status !== 'fixed'`.
16
+ *
17
+ * Skips when:
18
+ * - spec.md is absent, OR
19
+ * - there are no expected candidates AND no ledger.
20
+ *
21
+ * Fast Path Guarantee (ID-12): `applies_to_profile` gates this to
22
+ * full-pipeline (QUICK/DEBUG → lite → skip). The exemption is regression-
23
+ * locked by followups-quick-exempt.test.ts (ST7).
24
+ *
25
+ * Bypass: only the existing audited `--force --reason` (G42 Phase 1 pattern).
26
+ */
27
+ import { existsSync, readFileSync } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ import { parseOutOfScope } from '../../consistency/parse-spec.mjs';
30
+ import { computeMissingExpected, deriveExpectedCandidates } from '../../followups/derive.mjs';
31
+ import { listLoadBearingUnfixed, listUnadjudicatedOpen, parseFollowups, } from '../../followups/schema.mjs';
32
+ import { readJsonIfExists } from '../../util/io.mjs';
33
+ import { registerGate } from '../registry.mjs';
34
+ function rowSummary(r) {
35
+ return {
36
+ id: r.id,
37
+ title: r.title ?? null,
38
+ status: r.status ?? null,
39
+ verdict: r.adjudication?.verdict ?? null,
40
+ };
41
+ }
42
+ const gate = {
43
+ id: 'followups-adjudicated',
44
+ description: 'followups.json covers every derived candidate, every open row is adjudicated, and every load-bearing row is fixed (skipped if spec.md absent or no candidates + no ledger)',
45
+ severity: 'blocking',
46
+ skills: ['ship'],
47
+ applies_to_profile: (ctx) => ctx.profile === 'full-pipeline',
48
+ async check(ctx) {
49
+ const specPath = join(ctx.taskDir, 'spec.md');
50
+ const followupsPath = join(ctx.taskDir, 'followups.json');
51
+ const reviewPath = join(ctx.taskDir, 'review.json');
52
+ const qaPath = join(ctx.taskDir, 'qa_signoff.json');
53
+ const inputs = [specPath, followupsPath, reviewPath, qaPath];
54
+ if (!existsSync(specPath)) {
55
+ return {
56
+ status: 'skip',
57
+ reason: 'spec.md not present — skipping followups-adjudicated',
58
+ inputs,
59
+ };
60
+ }
61
+ let specContent;
62
+ try {
63
+ specContent = readFileSync(specPath, 'utf-8');
64
+ }
65
+ catch (err) {
66
+ // existsSync passed but the read failed (TOCTOU race, permission
67
+ // error). Return a structured fail like the sibling gates
68
+ // (review-clean, verify-approved) rather than throwing out of the
69
+ // gate runner — important in the concurrent-worktree environment.
70
+ return {
71
+ status: 'fail',
72
+ reason: `spec.md could not be read: ${err.message}`,
73
+ inputs,
74
+ };
75
+ }
76
+ const oosBullets = parseOutOfScope(specContent);
77
+ const review = readJsonIfExists(reviewPath);
78
+ const qa = readJsonIfExists(qaPath);
79
+ const candidates = deriveExpectedCandidates({ specContent, review, qa });
80
+ const ledgerDoc = readJsonIfExists(followupsPath);
81
+ const ledgerPresent = ledgerDoc !== null;
82
+ // Skip when there is nothing to track and no ledger to validate.
83
+ if (candidates.length === 0 && !ledgerPresent) {
84
+ return {
85
+ status: 'skip',
86
+ reason: 'no expected follow-up candidates and no ledger — nothing to adjudicate',
87
+ inputs,
88
+ };
89
+ }
90
+ // (a) Out of Scope bullets exist but no ledger — adoption forcing function.
91
+ if (oosBullets.length > 0 && !ledgerPresent) {
92
+ return {
93
+ status: 'fail',
94
+ reason: `spec.md has ${oosBullets.length} Out of Scope bullet(s) but followups.json is absent — run \`apt-tools followups check\` and seed the ledger`,
95
+ evidence: { out_of_scope_bullets: oosBullets.map((b) => b.text) },
96
+ inputs,
97
+ };
98
+ }
99
+ const parsed = parseFollowups(ledgerDoc ?? { rows: [] });
100
+ // (b) Missing expected rows.
101
+ const missing = computeMissingExpected(candidates, parsed.rows);
102
+ if (missing.length > 0) {
103
+ return {
104
+ status: 'fail',
105
+ reason: `${missing.length} expected follow-up row(s) missing from followups.json`,
106
+ evidence: {
107
+ missing_expected: missing.map((m) => ({ id: m.id, title: m.title, origin: m.origin })),
108
+ },
109
+ inputs,
110
+ };
111
+ }
112
+ // (c) Open rows lacking adjudication.
113
+ const unadjudicated = listUnadjudicatedOpen(parsed);
114
+ if (unadjudicated.length > 0) {
115
+ return {
116
+ status: 'fail',
117
+ reason: `${unadjudicated.length} open follow-up row(s) lack adjudication`,
118
+ evidence: { unadjudicated_open: unadjudicated.map(rowSummary) },
119
+ inputs,
120
+ };
121
+ }
122
+ // (d) Load-bearing rows not fixed.
123
+ const loadBearing = listLoadBearingUnfixed(parsed);
124
+ if (loadBearing.length > 0) {
125
+ return {
126
+ status: 'fail',
127
+ reason: `${loadBearing.length} load-bearing follow-up row(s) not fixed`,
128
+ evidence: { load_bearing_unfixed: loadBearing.map(rowSummary) },
129
+ inputs,
130
+ };
131
+ }
132
+ return {
133
+ status: 'pass',
134
+ reason: `followups.json adjudicated (${parsed.rows.length} row(s), ${candidates.length} expected candidate(s))`,
135
+ inputs,
136
+ };
137
+ },
138
+ };
139
+ registerGate(gate);
140
+ export default gate;
141
+ //# sourceMappingURL=followups-adjudicated.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"followups-adjudicated.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/followups-adjudicated.mjs"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ import './plan-exists.mjs';
15
15
  import './all-subtasks-complete.mjs';
16
16
  import './verify-approved.mjs';
17
17
  import './review-clean.mjs';
18
+ import './followups-adjudicated.mjs';
18
19
  import './gitignore-in-sync.mjs';
19
20
  import './consistency-check.mjs';
20
21
  import './tdd-iron-law.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,yBAAyB,CAAA;AAChC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,6BAA6B,CAAA;AACpC,OAAO,yBAAyB,CAAA;AAChC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Reject a rel_path that is absolute or escapes the worktree root BEFORE any
3
+ * write (the traversal guard, mirroring the core `assertPathContained` choke
4
+ * point). Returns the resolved absolute target, or null when unsafe.
5
+ *
6
+ * Exported so the security-sensitive guard can be unit-tested directly: the
7
+ * libSQL-backed `materializeProjectEnvCli` can only no-op in environments where
8
+ * `@libsql/client` is unresolvable (the framework test runner), so the pure
9
+ * guard is the testable load-bearing surface.
10
+ */
11
+ export function resolveContainedTarget(worktreePath: any, relPath: any): string | null;
12
+ /**
13
+ * Resolve the libSQL `projects.id` for a given project root path. The desktop /
14
+ * self-hosted app keys `project_env` rows by the project's stored id, NOT its
15
+ * path; the framework CLI only knows the path, so we match it against the
16
+ * `projects.path` column. Returns null when the project is unknown to libSQL
17
+ * (e.g. a fresh repo never opened in the app) — the caller treats that as
18
+ * "no env to materialize", never an error.
19
+ */
20
+ export function resolveProjectIdFromPath(client: any, projectPath: any): Promise<string | null>;
21
+ /**
22
+ * Materialize the project's stored env blobs verbatim into a worktree.
23
+ *
24
+ * @param worktreePath absolute path of the target worktree
25
+ * @param projectPath absolute path of the main project root (used to resolve
26
+ * the libSQL project id via `projects.path`)
27
+ * @param explicitProjectId optional override when the caller already knows the id
28
+ * @returns { materialized, rejected, errored } counts — never throws.
29
+ */
30
+ export function materializeProjectEnvCli(worktreePath: any, projectPath: any, explicitProjectId: any): materialized;
31
+ /**
32
+ * Detect drift for an already-materialized worktree (ID-07): compare each
33
+ * stored blob's fingerprint against the on-disk file. Returns per-file verdicts;
34
+ * `sync-env` simply re-runs `materializeProjectEnvCli` to overwrite.
35
+ *
36
+ * @returns { hasDrift, files: [{ relPath, status }] } — never throws.
37
+ */
38
+ export function detectEnvDriftCli(worktreePath: any, projectPath: any, explicitProjectId: any): hasDrift;
39
+ //# sourceMappingURL=materialize-env.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize-env.d.mts","sourceRoot":"","sources":["../../../src/cli/git/materialize-env.mjs"],"names":[],"mappings":"AAsCA;;;;;;;;;GASG;AACH,uFAMC;AAyBD;;;;;;;GAOG;AACH,gGAcC;AAoCD;;;;;;;;GAQG;AACH,uGAFc,YAAY,CA8BzB;AAED;;;;;;GAMG;AACH,gGAFc,QAAQ,CA8BrB"}