ai-foreman 1.0.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.
- package/README.md +523 -0
- package/dist/adapters/claude.js +150 -0
- package/dist/adapters/codex.js +155 -0
- package/dist/adapters/types.js +4 -0
- package/dist/cli/events.js +45 -0
- package/dist/cli/tickets.js +482 -0
- package/dist/config.js +119 -0
- package/dist/foreman.js +445 -0
- package/dist/index.js +300 -0
- package/dist/log.js +18 -0
- package/dist/markers.js +20 -0
- package/dist/notify.js +49 -0
- package/dist/permissions/policy.js +84 -0
- package/dist/roles.js +49 -0
- package/dist/tickets/blockers.js +22 -0
- package/dist/tickets/commands.js +438 -0
- package/dist/tickets/config.js +133 -0
- package/dist/tickets/events.js +19 -0
- package/dist/tickets/importer.js +11 -0
- package/dist/tickets/queue.js +62 -0
- package/dist/tickets/renderMarkdown.js +223 -0
- package/dist/tickets/stateDb.js +252 -0
- package/dist/tickets/ticketLoader.js +84 -0
- package/dist/tickets/ticketSchema.js +31 -0
- package/dist/tickets/validate.js +74 -0
- package/dist/util/asyncQueue.js +40 -0
- package/foreman.yaml +98 -0
- package/package.json +60 -0
|
@@ -0,0 +1,40 @@
|
|
|
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 class AsyncQueue {
|
|
6
|
+
items = [];
|
|
7
|
+
waiters = [];
|
|
8
|
+
closed = false;
|
|
9
|
+
push(item) {
|
|
10
|
+
if (this.closed)
|
|
11
|
+
return;
|
|
12
|
+
const waiter = this.waiters.shift();
|
|
13
|
+
if (waiter)
|
|
14
|
+
waiter({ value: item, done: false });
|
|
15
|
+
else
|
|
16
|
+
this.items.push(item);
|
|
17
|
+
}
|
|
18
|
+
close() {
|
|
19
|
+
if (this.closed)
|
|
20
|
+
return;
|
|
21
|
+
this.closed = true;
|
|
22
|
+
let waiter;
|
|
23
|
+
while ((waiter = this.waiters.shift())) {
|
|
24
|
+
waiter({ value: undefined, done: true });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
[Symbol.asyncIterator]() {
|
|
28
|
+
return {
|
|
29
|
+
next: () => {
|
|
30
|
+
if (this.items.length > 0) {
|
|
31
|
+
return Promise.resolve({ value: this.items.shift(), done: false });
|
|
32
|
+
}
|
|
33
|
+
if (this.closed) {
|
|
34
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
35
|
+
}
|
|
36
|
+
return new Promise((resolve) => this.waiters.push(resolve));
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
package/foreman.yaml
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Foreman configuration. Any field omitted here falls back to the built-in
|
|
2
|
+
# defaults in src/config.ts. This file is read from the *project* directory
|
|
3
|
+
# passed to `foreman start`, so each project can tune its own policy.
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
# Bash commands are auto-approved only when EVERY segment (split on && || ; |)
|
|
7
|
+
# starts with one of these prefixes.
|
|
8
|
+
allowBash:
|
|
9
|
+
- npm test
|
|
10
|
+
- npm run
|
|
11
|
+
- npm install
|
|
12
|
+
- npm ci
|
|
13
|
+
- npx tsc
|
|
14
|
+
- "node "
|
|
15
|
+
- "pnpm "
|
|
16
|
+
- "yarn "
|
|
17
|
+
- git status
|
|
18
|
+
- git diff
|
|
19
|
+
- git add
|
|
20
|
+
- git commit
|
|
21
|
+
- git log
|
|
22
|
+
- git branch
|
|
23
|
+
- git checkout
|
|
24
|
+
- git restore
|
|
25
|
+
- git stash
|
|
26
|
+
- ls
|
|
27
|
+
- "cat "
|
|
28
|
+
- "mkdir "
|
|
29
|
+
- foreman tickets
|
|
30
|
+
- pytest
|
|
31
|
+
- "python "
|
|
32
|
+
- "python3 "
|
|
33
|
+
- "make "
|
|
34
|
+
- "cargo "
|
|
35
|
+
- go test
|
|
36
|
+
- go build
|
|
37
|
+
|
|
38
|
+
# If a command contains any of these substrings it always escalates,
|
|
39
|
+
# regardless of the allow list.
|
|
40
|
+
escalateBash:
|
|
41
|
+
- rm -rf
|
|
42
|
+
- rm -r
|
|
43
|
+
- sudo
|
|
44
|
+
- git push
|
|
45
|
+
- git reset --hard
|
|
46
|
+
- git clean
|
|
47
|
+
- curl
|
|
48
|
+
- wget
|
|
49
|
+
- ssh
|
|
50
|
+
- scp
|
|
51
|
+
- docker
|
|
52
|
+
- kubectl
|
|
53
|
+
- chmod 777
|
|
54
|
+
- "> /dev"
|
|
55
|
+
- ":(){"
|
|
56
|
+
- mkfs
|
|
57
|
+
- "dd if="
|
|
58
|
+
|
|
59
|
+
# Non-Bash tools auto-approved (file writes are still confined to the worktree).
|
|
60
|
+
allowTools:
|
|
61
|
+
- Read
|
|
62
|
+
- Glob
|
|
63
|
+
- Grep
|
|
64
|
+
- Edit
|
|
65
|
+
- Write
|
|
66
|
+
- MultiEdit
|
|
67
|
+
- NotebookEdit
|
|
68
|
+
- TodoWrite
|
|
69
|
+
|
|
70
|
+
# Tools that always escalate (e.g. network access).
|
|
71
|
+
escalateTools:
|
|
72
|
+
- WebFetch
|
|
73
|
+
- WebSearch
|
|
74
|
+
|
|
75
|
+
notifications:
|
|
76
|
+
# When enabled, a desktop notification fires whenever the builder emits
|
|
77
|
+
# STEP_STATUS: needs_input — useful if you've walked away and need a nudge
|
|
78
|
+
# to come back to the terminal to answer.
|
|
79
|
+
#
|
|
80
|
+
# Platform support:
|
|
81
|
+
# macOS — built-in (osascript)
|
|
82
|
+
# Linux — requires notify-send (libnotify)
|
|
83
|
+
# WSL — Windows toast via powershell.exe (no install required)
|
|
84
|
+
#
|
|
85
|
+
# Default: false. Set to true to enable.
|
|
86
|
+
enabled: false
|
|
87
|
+
|
|
88
|
+
qa:
|
|
89
|
+
# After every STEP_STATUS: done (and plan_complete), foreman runs a free QA
|
|
90
|
+
# pass: the builder triple-checks accuracy, test existence, test execution,
|
|
91
|
+
# ticket satisfaction, and confidence. If QA reports issues, foreman drives
|
|
92
|
+
# a fix → re-QA cycle until the builder emits qa_pass (capped at 3 cycles).
|
|
93
|
+
# QA turns do NOT count against --steps.
|
|
94
|
+
#
|
|
95
|
+
# The CLI flag --no-qa overrides this per-run.
|
|
96
|
+
#
|
|
97
|
+
# Default: true.
|
|
98
|
+
enabled: true
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ai-foreman",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "An orchestrator that keeps Codex CLI / Claude Code builders moving through their step list unattended. Part of Rafi.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/ttante/foreman.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/ttante/foreman/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/ttante/foreman#readme",
|
|
14
|
+
"bin": {
|
|
15
|
+
"ai-foreman": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"foreman.yaml",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"claude",
|
|
25
|
+
"claude-code",
|
|
26
|
+
"codex",
|
|
27
|
+
"agent",
|
|
28
|
+
"orchestrator",
|
|
29
|
+
"automation",
|
|
30
|
+
"llm",
|
|
31
|
+
"cli"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.148",
|
|
38
|
+
"@clack/prompts": "^1.4.0",
|
|
39
|
+
"ajv": "^8.20.0",
|
|
40
|
+
"ajv-formats": "^3.0.1",
|
|
41
|
+
"better-sqlite3": "^12.10.0",
|
|
42
|
+
"commander": "^12.1.0",
|
|
43
|
+
"luxon": "^3.7.2",
|
|
44
|
+
"yaml": "^2.5.1",
|
|
45
|
+
"special-agents": "0.1.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
49
|
+
"@types/luxon": "^3.7.1",
|
|
50
|
+
"@types/node": "^20.14.0",
|
|
51
|
+
"tsx": "^4.19.0",
|
|
52
|
+
"typescript": "^5.6.0"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsc -p tsconfig.build.json",
|
|
56
|
+
"dev": "tsx src/index.ts",
|
|
57
|
+
"test": "tsx --test test/*.test.ts",
|
|
58
|
+
"typecheck": "tsc --noEmit"
|
|
59
|
+
}
|
|
60
|
+
}
|