ai-foreman 1.5.0 → 1.6.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 (51) hide show
  1. package/dist/agentRun.d.ts +3 -2
  2. package/dist/agentRun.js +27 -8
  3. package/dist/branch/git.d.ts +3 -0
  4. package/dist/branch/git.js +31 -5
  5. package/dist/branch/github.d.ts +2 -2
  6. package/dist/branch/github.js +2 -2
  7. package/dist/branch/gitlab.d.ts +3 -2
  8. package/dist/branch/gitlab.js +10 -4
  9. package/dist/branch/planner.d.ts +3 -1
  10. package/dist/branch/planner.js +24 -2
  11. package/dist/branch/runner.d.ts +10 -1
  12. package/dist/branch/runner.js +41 -13
  13. package/dist/branch/types.d.ts +4 -0
  14. package/dist/buildRuns.d.ts +35 -0
  15. package/dist/buildRuns.js +149 -0
  16. package/dist/cli/runtimeAuthPrompt.d.ts +1 -1
  17. package/dist/cli/runtimeAuthPrompt.js +2 -2
  18. package/dist/cli/start.js +153 -16
  19. package/dist/cli/status.d.ts +2 -0
  20. package/dist/cli/status.js +71 -55
  21. package/dist/cli/tickets.js +57 -10
  22. package/dist/foreman.d.ts +3 -1
  23. package/dist/foreman.js +46 -4
  24. package/dist/index.js +0 -0
  25. package/dist/interviews.d.ts +26 -4
  26. package/dist/interviews.js +71 -4
  27. package/dist/log.d.ts +1 -1
  28. package/dist/roles.d.ts +11 -0
  29. package/dist/roles.js +8 -0
  30. package/dist/runtimeAuth.d.ts +1 -1
  31. package/dist/runtimeAuth.js +6 -25
  32. package/dist/runtimeReadiness.d.ts +14 -0
  33. package/dist/runtimeReadiness.js +122 -0
  34. package/dist/ticketPlanning.d.ts +83 -0
  35. package/dist/ticketPlanning.js +287 -0
  36. package/dist/tickets/commands.js +16 -0
  37. package/dist/tickets/delivery.d.ts +38 -0
  38. package/dist/tickets/delivery.js +152 -0
  39. package/dist/tickets/importer.js +4 -0
  40. package/dist/tickets/renderMarkdown.js +9 -0
  41. package/dist/tickets/setupConfig.d.ts +8 -0
  42. package/dist/tickets/setupConfig.js +47 -2
  43. package/dist/tickets/sourceFetch.d.ts +24 -0
  44. package/dist/tickets/sourceFetch.js +246 -0
  45. package/dist/tickets/stateDb.d.ts +10 -0
  46. package/dist/tickets/stateDb.js +24 -0
  47. package/dist/tickets/ticketLoader.js +18 -0
  48. package/dist/tickets/ticketSchema.d.ts +93 -0
  49. package/dist/tickets/ticketSchema.js +17 -0
  50. package/dist/tickets/validate.js +12 -0
  51. package/package.json +29 -2
@@ -47,6 +47,24 @@ export function validateTicketDefs(tickets) {
47
47
  errors.push({ path: `tickets[${t.id}].depends_on`, message: `references unknown ticket: ${dep}` });
48
48
  }
49
49
  }
50
+ for (const replacement of t.superseded_by ?? []) {
51
+ if (!ids.has(replacement))
52
+ errors.push({ path: `tickets[${t.id}].superseded_by`, message: `references unknown ticket: ${replacement}` });
53
+ if (replacement === t.id)
54
+ errors.push({ path: `tickets[${t.id}].superseded_by`, message: "ticket cannot supersede itself" });
55
+ const reciprocal = tickets.find((candidate) => candidate.id === replacement)?.supersedes ?? [];
56
+ if (ids.has(replacement) && !reciprocal.includes(t.id))
57
+ errors.push({ path: `tickets[${t.id}].superseded_by`, message: `${replacement} is missing reciprocal supersedes link to ${t.id}` });
58
+ }
59
+ for (const replaced of t.supersedes ?? []) {
60
+ if (!ids.has(replaced))
61
+ errors.push({ path: `tickets[${t.id}].supersedes`, message: `references unknown ticket: ${replaced}` });
62
+ if (replaced === t.id)
63
+ errors.push({ path: `tickets[${t.id}].supersedes`, message: "ticket cannot supersede itself" });
64
+ const reciprocal = tickets.find((candidate) => candidate.id === replaced)?.superseded_by ?? [];
65
+ if (!reciprocal.includes(t.id))
66
+ errors.push({ path: `tickets[${t.id}].supersedes`, message: `${replaced} is missing reciprocal superseded_by link to ${t.id}` });
67
+ }
50
68
  }
51
69
  for (const t of tickets) {
52
70
  if ((t.risk === "Medium" || t.risk === "High") && !t.rollback) {
@@ -7,6 +7,14 @@ export interface TicketExternalRef {
7
7
  key?: string | null;
8
8
  url?: string | null;
9
9
  }
10
+ /** General provenance reference. `external_refs` remains accepted for compatibility. */
11
+ export interface TicketSourceRef {
12
+ source: string;
13
+ item: string;
14
+ url?: string | null;
15
+ fingerprint?: string | null;
16
+ note?: string | null;
17
+ }
10
18
  export interface TicketDef {
11
19
  id: string;
12
20
  order: number;
@@ -23,6 +31,9 @@ export interface TicketDef {
23
31
  rollback?: string | null;
24
32
  notes?: string | null;
25
33
  external_refs?: TicketExternalRef[];
34
+ source_refs?: TicketSourceRef[];
35
+ superseded_by?: string[];
36
+ supersedes?: string[];
26
37
  }
27
38
  export declare const TICKET_JSON_SCHEMA: {
28
39
  readonly type: "object";
@@ -117,6 +128,47 @@ export declare const TICKET_JSON_SCHEMA: {
117
128
  };
118
129
  };
119
130
  };
131
+ readonly source_refs: {
132
+ readonly type: "array";
133
+ readonly items: {
134
+ readonly type: "object";
135
+ readonly required: readonly ["source", "item"];
136
+ readonly additionalProperties: true;
137
+ readonly properties: {
138
+ readonly source: {
139
+ readonly type: "string";
140
+ readonly minLength: 1;
141
+ };
142
+ readonly item: {
143
+ readonly type: "string";
144
+ readonly minLength: 1;
145
+ };
146
+ readonly url: {
147
+ readonly type: readonly ["string", "null"];
148
+ };
149
+ readonly fingerprint: {
150
+ readonly type: readonly ["string", "null"];
151
+ };
152
+ readonly note: {
153
+ readonly type: readonly ["string", "null"];
154
+ };
155
+ };
156
+ };
157
+ };
158
+ readonly superseded_by: {
159
+ readonly type: "array";
160
+ readonly items: {
161
+ readonly type: "string";
162
+ };
163
+ readonly uniqueItems: true;
164
+ };
165
+ readonly supersedes: {
166
+ readonly type: "array";
167
+ readonly items: {
168
+ readonly type: "string";
169
+ };
170
+ readonly uniqueItems: true;
171
+ };
120
172
  };
121
173
  };
122
174
  export declare const TICKETS_FILE_SCHEMA: {
@@ -218,6 +270,47 @@ export declare const TICKETS_FILE_SCHEMA: {
218
270
  };
219
271
  };
220
272
  };
273
+ readonly source_refs: {
274
+ readonly type: "array";
275
+ readonly items: {
276
+ readonly type: "object";
277
+ readonly required: readonly ["source", "item"];
278
+ readonly additionalProperties: true;
279
+ readonly properties: {
280
+ readonly source: {
281
+ readonly type: "string";
282
+ readonly minLength: 1;
283
+ };
284
+ readonly item: {
285
+ readonly type: "string";
286
+ readonly minLength: 1;
287
+ };
288
+ readonly url: {
289
+ readonly type: readonly ["string", "null"];
290
+ };
291
+ readonly fingerprint: {
292
+ readonly type: readonly ["string", "null"];
293
+ };
294
+ readonly note: {
295
+ readonly type: readonly ["string", "null"];
296
+ };
297
+ };
298
+ };
299
+ };
300
+ readonly superseded_by: {
301
+ readonly type: "array";
302
+ readonly items: {
303
+ readonly type: "string";
304
+ };
305
+ readonly uniqueItems: true;
306
+ };
307
+ readonly supersedes: {
308
+ readonly type: "array";
309
+ readonly items: {
310
+ readonly type: "string";
311
+ };
312
+ readonly uniqueItems: true;
313
+ };
221
314
  };
222
315
  };
223
316
  };
@@ -34,6 +34,23 @@ export const TICKET_JSON_SCHEMA = {
34
34
  },
35
35
  },
36
36
  },
37
+ source_refs: {
38
+ type: "array",
39
+ items: {
40
+ type: "object",
41
+ required: ["source", "item"],
42
+ additionalProperties: true,
43
+ properties: {
44
+ source: { type: "string", minLength: 1 },
45
+ item: { type: "string", minLength: 1 },
46
+ url: { type: ["string", "null"] },
47
+ fingerprint: { type: ["string", "null"] },
48
+ note: { type: ["string", "null"] },
49
+ },
50
+ },
51
+ },
52
+ superseded_by: { type: "array", items: { type: "string" }, uniqueItems: true },
53
+ supersedes: { type: "array", items: { type: "string" }, uniqueItems: true },
37
54
  },
38
55
  };
39
56
  export const TICKETS_FILE_SCHEMA = {
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { validateTicketDefs, detectCycles } from "./ticketLoader.js";
4
4
  import { buildNextQueue } from "./queue.js";
5
+ import { loadDeliveryConfig, validateDeliveryConfig } from "./delivery.js";
5
6
  export function runAllValidation(config, projectDir, ticketDefs, states, db) {
6
7
  const issues = [];
7
8
  // Pass 1: schema and source
@@ -11,6 +12,17 @@ export function runAllValidation(config, projectDir, ticketDefs, states, db) {
11
12
  for (const cycle of detectCycles(ticketDefs)) {
12
13
  issues.push({ pass: 1, severity: "error", message: `[cycle] dependency cycle: ${cycle}` });
13
14
  }
15
+ try {
16
+ const delivery = loadDeliveryConfig(projectDir);
17
+ if (delivery) {
18
+ for (const issue of validateDeliveryConfig(delivery, ticketDefs)) {
19
+ issues.push({ pass: 1, severity: "error", message: `[delivery] ${issue.path}: ${issue.message}` });
20
+ }
21
+ }
22
+ }
23
+ catch (err) {
24
+ issues.push({ pass: 1, severity: "error", message: `[delivery] ${err instanceof Error ? err.message : String(err)}` });
25
+ }
14
26
  // Pass 2: state validation
15
27
  const ticketIds = new Set(ticketDefs.map((t) => t.id));
16
28
  for (const [id, state] of states) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-foreman",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "An orchestrator that keeps Codex CLI / Claude Code builders moving through their step list unattended. Part of Rafi.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -25,6 +25,30 @@
25
25
  "types": "./dist/interviews.d.ts",
26
26
  "default": "./dist/interviews.js"
27
27
  },
28
+ "./runtime-readiness.js": {
29
+ "types": "./dist/runtimeReadiness.d.ts",
30
+ "default": "./dist/runtimeReadiness.js"
31
+ },
32
+ "./roles.js": {
33
+ "types": "./dist/roles.d.ts",
34
+ "default": "./dist/roles.js"
35
+ },
36
+ "./build-runs.js": {
37
+ "types": "./dist/buildRuns.d.ts",
38
+ "default": "./dist/buildRuns.js"
39
+ },
40
+ "./ticket-planning.js": {
41
+ "types": "./dist/ticketPlanning.d.ts",
42
+ "default": "./dist/ticketPlanning.js"
43
+ },
44
+ "./tickets/source-fetch.js": {
45
+ "types": "./dist/tickets/sourceFetch.d.ts",
46
+ "default": "./dist/tickets/sourceFetch.js"
47
+ },
48
+ "./tickets/setup-config.js": {
49
+ "types": "./dist/tickets/setupConfig.d.ts",
50
+ "default": "./dist/tickets/setupConfig.js"
51
+ },
28
52
  "./cli/tickets.js": {
29
53
  "types": "./dist/cli/tickets.d.ts",
30
54
  "default": "./dist/cli/tickets.js"
@@ -73,13 +97,16 @@
73
97
  "@anthropic-ai/claude-agent-sdk": "^0.3.148"
74
98
  },
75
99
  "dependencies": {
76
- "special-agents": "0.6.0",
100
+ "special-agents": "0.7.0",
101
+ "rafi-spec": "0.7.0",
77
102
  "@clack/prompts": "^1.4.0",
78
103
  "ajv": "^8.20.0",
79
104
  "ajv-formats": "^3.0.1",
80
105
  "better-sqlite3": "^12.10.0",
81
106
  "commander": "^12.1.0",
82
107
  "luxon": "^3.7.2",
108
+ "parse5": "7.2.1",
109
+ "pdfjs-dist": "4.10.38",
83
110
  "yaml": "^2.5.1"
84
111
  },
85
112
  "devDependencies": {