ai-foreman 1.0.0 → 1.0.2

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.
@@ -0,0 +1,90 @@
1
+ export type TicketStatus = "planned" | "next" | "in_progress" | "blocked" | "done" | "canceled";
2
+ export type ValidationResult = "passed" | "failed" | "not_run" | "not_applicable";
3
+ export interface TicketState {
4
+ ticket_id: string;
5
+ status: TicketStatus;
6
+ owner: string | null;
7
+ current_step: string | null;
8
+ next_action: string | null;
9
+ blocked_by_json: string;
10
+ blocker_type: string | null;
11
+ blocker_notes: string | null;
12
+ first_blocked_at: string | null;
13
+ last_checked_at: string | null;
14
+ last_worked_at: string | null;
15
+ completed_at: string | null;
16
+ attempt_count: number;
17
+ last_error: string | null;
18
+ evidence: string | null;
19
+ validation_result: ValidationResult | null;
20
+ validation_commands: string | null;
21
+ validation_notes: string | null;
22
+ updated_at: string;
23
+ updated_by: string | null;
24
+ }
25
+ export interface TicketEvent {
26
+ id?: number;
27
+ timestamp: string;
28
+ actor: string | null;
29
+ ticket_id: string | null;
30
+ event_type: string;
31
+ old_status: string | null;
32
+ new_status: string | null;
33
+ summary: string;
34
+ validation: string | null;
35
+ evidence: string | null;
36
+ payload_json: string;
37
+ }
38
+ export interface ValidationSnapshot {
39
+ id?: number;
40
+ timestamp: string;
41
+ scope: string;
42
+ result: ValidationResult;
43
+ commands: string | null;
44
+ evidence: string | null;
45
+ notes: string | null;
46
+ }
47
+ export interface FutureWorkItem {
48
+ id?: number;
49
+ discovered_at: string;
50
+ source_ticket: string | null;
51
+ proposed_ticket: string | null;
52
+ priority_guess: string | null;
53
+ area: string | null;
54
+ summary: string;
55
+ rationale: string | null;
56
+ needs_decision_from: string | null;
57
+ disposition: "triage" | "accepted" | "rejected" | "merged" | "queued";
58
+ }
59
+ export interface RecentCompletedContext {
60
+ ticket_id: string;
61
+ why_it_remains_here: string;
62
+ pinned_until: string | null;
63
+ updated_at: string;
64
+ }
65
+ export interface ArchiveIndexEntry {
66
+ archive_file: string;
67
+ scope: string;
68
+ last_updated: string | null;
69
+ notes: string | null;
70
+ }
71
+ export declare class StateDb {
72
+ private db;
73
+ constructor(dbPath: string);
74
+ close(): void;
75
+ getState(ticketId: string): TicketState | undefined;
76
+ getAllStates(): Map<string, TicketState>;
77
+ upsertState(ticketId: string, patch: Partial<Omit<TicketState, "ticket_id">>, now: string): void;
78
+ insertEvent(event: Omit<TicketEvent, "id">): void;
79
+ getRecentEvents(limit: number): TicketEvent[];
80
+ insertValidationSnapshot(snap: Omit<ValidationSnapshot, "id">): void;
81
+ getRecentValidationSnapshot(): ValidationSnapshot | undefined;
82
+ insertFutureWork(item: Omit<FutureWorkItem, "id">): number;
83
+ getFutureWork(): FutureWorkItem[];
84
+ getFutureWorkById(id: number): FutureWorkItem | undefined;
85
+ updateFutureWorkDisposition(id: number, disposition: string): void;
86
+ getRecentCompleted(): RecentCompletedContext[];
87
+ upsertRecentCompleted(row: RecentCompletedContext): void;
88
+ getArchiveIndex(): ArchiveIndexEntry[];
89
+ transaction<T>(fn: () => T): T;
90
+ }
@@ -0,0 +1,9 @@
1
+ import { type TicketDef } from "./ticketSchema.js";
2
+ export declare function loadTickets(ticketsPath: string): TicketDef[];
3
+ export declare function saveTickets(ticketsPath: string, tickets: TicketDef[]): void;
4
+ export interface ValidationError {
5
+ path: string;
6
+ message: string;
7
+ }
8
+ export declare function validateTicketDefs(tickets: TicketDef[]): ValidationError[];
9
+ export declare function detectCycles(tickets: TicketDef[]): string[];
@@ -0,0 +1,170 @@
1
+ export type TicketPriority = "P0" | "P1" | "P2" | "P3";
2
+ export type TicketSize = "XS" | "S" | "M" | "L" | "XL";
3
+ export type TicketRisk = "Low" | "Medium" | "High";
4
+ export interface TicketDef {
5
+ id: string;
6
+ order: number;
7
+ title: string;
8
+ area: string;
9
+ priority: TicketPriority;
10
+ size: TicketSize;
11
+ risk: TicketRisk;
12
+ depends_on: string[];
13
+ summary: string;
14
+ acceptance: string[];
15
+ required_tests: string[];
16
+ likely_files: string[];
17
+ rollback?: string | null;
18
+ notes?: string | null;
19
+ }
20
+ export declare const TICKET_JSON_SCHEMA: {
21
+ readonly type: "object";
22
+ readonly required: readonly ["id", "order", "title", "area", "priority", "size", "risk", "depends_on", "summary", "acceptance", "required_tests", "likely_files"];
23
+ readonly additionalProperties: true;
24
+ readonly properties: {
25
+ readonly id: {
26
+ readonly type: "string";
27
+ readonly pattern: "^[A-Za-z][A-Za-z0-9-_]*$";
28
+ };
29
+ readonly order: {
30
+ readonly type: "number";
31
+ readonly minimum: 0;
32
+ };
33
+ readonly title: {
34
+ readonly type: "string";
35
+ readonly minLength: 1;
36
+ };
37
+ readonly area: {
38
+ readonly type: "string";
39
+ readonly minLength: 1;
40
+ };
41
+ readonly priority: {
42
+ readonly type: "string";
43
+ readonly enum: readonly ["P0", "P1", "P2", "P3"];
44
+ };
45
+ readonly size: {
46
+ readonly type: "string";
47
+ readonly enum: readonly ["XS", "S", "M", "L", "XL"];
48
+ };
49
+ readonly risk: {
50
+ readonly type: "string";
51
+ readonly enum: readonly ["Low", "Medium", "High"];
52
+ };
53
+ readonly depends_on: {
54
+ readonly type: "array";
55
+ readonly items: {
56
+ readonly type: "string";
57
+ };
58
+ };
59
+ readonly summary: {
60
+ readonly type: "string";
61
+ readonly minLength: 1;
62
+ };
63
+ readonly acceptance: {
64
+ readonly type: "array";
65
+ readonly items: {
66
+ readonly type: "string";
67
+ };
68
+ readonly minItems: 1;
69
+ };
70
+ readonly required_tests: {
71
+ readonly type: "array";
72
+ readonly items: {
73
+ readonly type: "string";
74
+ };
75
+ readonly minItems: 1;
76
+ };
77
+ readonly likely_files: {
78
+ readonly type: "array";
79
+ readonly items: {
80
+ readonly type: "string";
81
+ };
82
+ };
83
+ readonly rollback: {
84
+ readonly type: readonly ["string", "null"];
85
+ };
86
+ readonly notes: {
87
+ readonly type: readonly ["string", "null"];
88
+ };
89
+ };
90
+ };
91
+ export declare const TICKETS_FILE_SCHEMA: {
92
+ readonly type: "object";
93
+ readonly required: readonly ["tickets"];
94
+ readonly properties: {
95
+ readonly tickets: {
96
+ readonly type: "array";
97
+ readonly items: {
98
+ readonly type: "object";
99
+ readonly required: readonly ["id", "order", "title", "area", "priority", "size", "risk", "depends_on", "summary", "acceptance", "required_tests", "likely_files"];
100
+ readonly additionalProperties: true;
101
+ readonly properties: {
102
+ readonly id: {
103
+ readonly type: "string";
104
+ readonly pattern: "^[A-Za-z][A-Za-z0-9-_]*$";
105
+ };
106
+ readonly order: {
107
+ readonly type: "number";
108
+ readonly minimum: 0;
109
+ };
110
+ readonly title: {
111
+ readonly type: "string";
112
+ readonly minLength: 1;
113
+ };
114
+ readonly area: {
115
+ readonly type: "string";
116
+ readonly minLength: 1;
117
+ };
118
+ readonly priority: {
119
+ readonly type: "string";
120
+ readonly enum: readonly ["P0", "P1", "P2", "P3"];
121
+ };
122
+ readonly size: {
123
+ readonly type: "string";
124
+ readonly enum: readonly ["XS", "S", "M", "L", "XL"];
125
+ };
126
+ readonly risk: {
127
+ readonly type: "string";
128
+ readonly enum: readonly ["Low", "Medium", "High"];
129
+ };
130
+ readonly depends_on: {
131
+ readonly type: "array";
132
+ readonly items: {
133
+ readonly type: "string";
134
+ };
135
+ };
136
+ readonly summary: {
137
+ readonly type: "string";
138
+ readonly minLength: 1;
139
+ };
140
+ readonly acceptance: {
141
+ readonly type: "array";
142
+ readonly items: {
143
+ readonly type: "string";
144
+ };
145
+ readonly minItems: 1;
146
+ };
147
+ readonly required_tests: {
148
+ readonly type: "array";
149
+ readonly items: {
150
+ readonly type: "string";
151
+ };
152
+ readonly minItems: 1;
153
+ };
154
+ readonly likely_files: {
155
+ readonly type: "array";
156
+ readonly items: {
157
+ readonly type: "string";
158
+ };
159
+ };
160
+ readonly rollback: {
161
+ readonly type: readonly ["string", "null"];
162
+ };
163
+ readonly notes: {
164
+ readonly type: readonly ["string", "null"];
165
+ };
166
+ };
167
+ };
168
+ };
169
+ };
170
+ };
@@ -0,0 +1,10 @@
1
+ import type { TicketsConfig } from "./config.js";
2
+ import type { TicketDef } from "./ticketSchema.js";
3
+ import type { TicketState, StateDb } from "./stateDb.js";
4
+ export interface ValidationIssue {
5
+ pass: 1 | 2 | 3 | 4;
6
+ severity: "error" | "warn";
7
+ message: string;
8
+ }
9
+ export declare function runAllValidation(config: TicketsConfig, projectDir: string, ticketDefs: TicketDef[], states: Map<string, TicketState>, db: StateDb): ValidationIssue[];
10
+ export declare function formatValidationIssues(issues: ValidationIssue[]): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * A minimal async iterable backed by a push queue. Producers call `push`;
3
+ * consumers iterate with `for await`. Iteration ends after `close()`.
4
+ */
5
+ export declare class AsyncQueue<T> implements AsyncIterable<T> {
6
+ private items;
7
+ private waiters;
8
+ private closed;
9
+ push(item: T): void;
10
+ close(): void;
11
+ [Symbol.asyncIterator](): AsyncIterator<T>;
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-foreman",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "An orchestrator that keeps Codex CLI / Claude Code builders moving through their step list unattended. Part of Rafi.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -14,6 +14,24 @@
14
14
  "bin": {
15
15
  "ai-foreman": "./dist/index.js"
16
16
  },
17
+ "exports": {
18
+ "./cli/tickets.js": {
19
+ "types": "./dist/cli/tickets.d.ts",
20
+ "default": "./dist/cli/tickets.js"
21
+ },
22
+ "./cli/start.js": {
23
+ "types": "./dist/cli/start.d.ts",
24
+ "default": "./dist/cli/start.js"
25
+ },
26
+ "./cli/status.js": {
27
+ "types": "./dist/cli/status.d.ts",
28
+ "default": "./dist/cli/status.js"
29
+ },
30
+ "./cli/doctor.js": {
31
+ "types": "./dist/cli/doctor.d.ts",
32
+ "default": "./dist/cli/doctor.js"
33
+ }
34
+ },
17
35
  "files": [
18
36
  "dist",
19
37
  "README.md",
@@ -33,8 +51,10 @@
33
51
  "engines": {
34
52
  "node": ">=20"
35
53
  },
54
+ "optionalDependencies": {
55
+ "@anthropic-ai/claude-agent-sdk": "^0.3.148"
56
+ },
36
57
  "dependencies": {
37
- "@anthropic-ai/claude-agent-sdk": "^0.3.148",
38
58
  "@clack/prompts": "^1.4.0",
39
59
  "ajv": "^8.20.0",
40
60
  "ajv-formats": "^3.0.1",
@@ -42,7 +62,7 @@
42
62
  "commander": "^12.1.0",
43
63
  "luxon": "^3.7.2",
44
64
  "yaml": "^2.5.1",
45
- "special-agents": "0.1.0"
65
+ "special-agents": "0.3.0"
46
66
  },
47
67
  "devDependencies": {
48
68
  "@types/better-sqlite3": "^7.6.13",