@agent-relay/factory 0.0.0 → 0.1.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.
- package/README.md +182 -23
- package/bin/factory.mjs +7 -0
- package/dist/cli/fleet.d.ts +81 -0
- package/dist/cli/fleet.d.ts.map +1 -0
- package/dist/cli/fleet.js +571 -0
- package/dist/cli/fleet.js.map +1 -0
- package/dist/config/schema.d.ts +1313 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +320 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants/linear.d.ts +6 -0
- package/dist/constants/linear.d.ts.map +1 -0
- package/dist/constants/linear.js +21 -0
- package/dist/constants/linear.js.map +1 -0
- package/dist/constants/slack.d.ts +3 -0
- package/dist/constants/slack.d.ts.map +1 -0
- package/dist/constants/slack.js +3 -0
- package/dist/constants/slack.js.map +1 -0
- package/dist/dispatch/templates.d.ts +52 -0
- package/dist/dispatch/templates.d.ts.map +1 -0
- package/dist/dispatch/templates.js +118 -0
- package/dist/dispatch/templates.js.map +1 -0
- package/dist/fleet/create-fleet.d.ts +14 -0
- package/dist/fleet/create-fleet.d.ts.map +1 -0
- package/dist/fleet/create-fleet.js +15 -0
- package/dist/fleet/create-fleet.js.map +1 -0
- package/dist/fleet/ensure-relay-broker.d.ts +24 -0
- package/dist/fleet/ensure-relay-broker.d.ts.map +1 -0
- package/dist/fleet/ensure-relay-broker.js +56 -0
- package/dist/fleet/ensure-relay-broker.js.map +1 -0
- package/dist/fleet/internal-fleet-client.d.ts +90 -0
- package/dist/fleet/internal-fleet-client.d.ts.map +1 -0
- package/dist/fleet/internal-fleet-client.js +602 -0
- package/dist/fleet/internal-fleet-client.js.map +1 -0
- package/dist/fleet/relay-fleet-client.d.ts +105 -0
- package/dist/fleet/relay-fleet-client.d.ts.map +1 -0
- package/dist/fleet/relay-fleet-client.js +509 -0
- package/dist/fleet/relay-fleet-client.js.map +1 -0
- package/dist/github/index.d.ts +5 -0
- package/dist/github/index.d.ts.map +1 -0
- package/dist/github/index.js +3 -0
- package/dist/github/index.js.map +1 -0
- package/dist/github/merge-gate.d.ts +47 -0
- package/dist/github/merge-gate.d.ts.map +1 -0
- package/dist/github/merge-gate.js +147 -0
- package/dist/github/merge-gate.js.map +1 -0
- package/dist/github/probe-closer.d.ts +15 -0
- package/dist/github/probe-closer.d.ts.map +1 -0
- package/dist/github/probe-closer.js +67 -0
- package/dist/github/probe-closer.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/issue-key-match.d.ts +3 -0
- package/dist/issue-key-match.d.ts.map +1 -0
- package/dist/issue-key-match.js +22 -0
- package/dist/issue-key-match.js.map +1 -0
- package/dist/linear/state-resolver.d.ts +26 -0
- package/dist/linear/state-resolver.d.ts.map +1 -0
- package/dist/linear/state-resolver.js +285 -0
- package/dist/linear/state-resolver.js.map +1 -0
- package/dist/mount/local-mount-preflight.d.ts +9 -0
- package/dist/mount/local-mount-preflight.d.ts.map +1 -0
- package/dist/mount/local-mount-preflight.js +149 -0
- package/dist/mount/local-mount-preflight.js.map +1 -0
- package/dist/mount/relayfile-binary.d.ts +9 -0
- package/dist/mount/relayfile-binary.d.ts.map +1 -0
- package/dist/mount/relayfile-binary.js +177 -0
- package/dist/mount/relayfile-binary.js.map +1 -0
- package/dist/mount/relayfile-cloud-mount-client.d.ts +123 -0
- package/dist/mount/relayfile-cloud-mount-client.d.ts.map +1 -0
- package/dist/mount/relayfile-cloud-mount-client.js +427 -0
- package/dist/mount/relayfile-cloud-mount-client.js.map +1 -0
- package/dist/node/factory-node.d.ts +59 -0
- package/dist/node/factory-node.d.ts.map +1 -0
- package/dist/node/factory-node.js +351 -0
- package/dist/node/factory-node.js.map +1 -0
- package/dist/node/factory.node.d.ts +3 -0
- package/dist/node/factory.node.d.ts.map +1 -0
- package/dist/node/factory.node.js +5 -0
- package/dist/node/factory.node.js.map +1 -0
- package/dist/orchestrator/batch-tracker.d.ts +42 -0
- package/dist/orchestrator/batch-tracker.d.ts.map +1 -0
- package/dist/orchestrator/batch-tracker.js +125 -0
- package/dist/orchestrator/batch-tracker.js.map +1 -0
- package/dist/orchestrator/factory.d.ts +58 -0
- package/dist/orchestrator/factory.d.ts.map +1 -0
- package/dist/orchestrator/factory.js +4372 -0
- package/dist/orchestrator/factory.js.map +1 -0
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +4 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/process-identity.d.ts +23 -0
- package/dist/orchestrator/process-identity.d.ts.map +1 -0
- package/dist/orchestrator/process-identity.js +122 -0
- package/dist/orchestrator/process-identity.js.map +1 -0
- package/dist/orchestrator/reaper.d.ts +60 -0
- package/dist/orchestrator/reaper.d.ts.map +1 -0
- package/dist/orchestrator/reaper.js +293 -0
- package/dist/orchestrator/reaper.js.map +1 -0
- package/dist/ports/fleet.d.ts +101 -0
- package/dist/ports/fleet.d.ts.map +1 -0
- package/dist/ports/fleet.js +2 -0
- package/dist/ports/fleet.js.map +1 -0
- package/dist/ports/index.d.ts +5 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/mount.d.ts +56 -0
- package/dist/ports/mount.d.ts.map +1 -0
- package/dist/ports/mount.js +2 -0
- package/dist/ports/mount.js.map +1 -0
- package/dist/ports/state.d.ts +61 -0
- package/dist/ports/state.d.ts.map +1 -0
- package/dist/ports/state.js +2 -0
- package/dist/ports/state.js.map +1 -0
- package/dist/ports/system.d.ts +15 -0
- package/dist/ports/system.d.ts.map +1 -0
- package/dist/ports/system.js +2 -0
- package/dist/ports/system.js.map +1 -0
- package/dist/ports/writeback.d.ts +25 -0
- package/dist/ports/writeback.d.ts.map +1 -0
- package/dist/ports/writeback.js +2 -0
- package/dist/ports/writeback.js.map +1 -0
- package/dist/safety/factory-scope.d.ts +16 -0
- package/dist/safety/factory-scope.d.ts.map +1 -0
- package/dist/safety/factory-scope.js +107 -0
- package/dist/safety/factory-scope.js.map +1 -0
- package/dist/state/in-memory-state-store.d.ts +31 -0
- package/dist/state/in-memory-state-store.d.ts.map +1 -0
- package/dist/state/in-memory-state-store.js +115 -0
- package/dist/state/in-memory-state-store.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +2 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/store.d.ts +29 -0
- package/dist/state/store.d.ts.map +1 -0
- package/dist/state/store.js +26 -0
- package/dist/state/store.js.map +1 -0
- package/dist/subscriptions/common.d.ts +7 -0
- package/dist/subscriptions/common.d.ts.map +1 -0
- package/dist/subscriptions/common.js +59 -0
- package/dist/subscriptions/common.js.map +1 -0
- package/dist/subscriptions/event-client.d.ts +40 -0
- package/dist/subscriptions/event-client.d.ts.map +1 -0
- package/dist/subscriptions/event-client.js +234 -0
- package/dist/subscriptions/event-client.js.map +1 -0
- package/dist/subscriptions/globs.d.ts +5 -0
- package/dist/subscriptions/globs.d.ts.map +1 -0
- package/dist/subscriptions/globs.js +50 -0
- package/dist/subscriptions/globs.js.map +1 -0
- package/dist/subscriptions/index.d.ts +8 -0
- package/dist/subscriptions/index.d.ts.map +1 -0
- package/dist/subscriptions/index.js +5 -0
- package/dist/subscriptions/index.js.map +1 -0
- package/dist/subscriptions/linear-filter.d.ts +26 -0
- package/dist/subscriptions/linear-filter.d.ts.map +1 -0
- package/dist/subscriptions/linear-filter.js +143 -0
- package/dist/subscriptions/linear-filter.js.map +1 -0
- package/dist/subscriptions/specs.d.ts +44 -0
- package/dist/subscriptions/specs.d.ts.map +1 -0
- package/dist/subscriptions/specs.js +195 -0
- package/dist/subscriptions/specs.js.map +1 -0
- package/dist/testing/fakes.d.ts +114 -0
- package/dist/testing/fakes.d.ts.map +1 -0
- package/dist/testing/fakes.js +219 -0
- package/dist/testing/fakes.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/triage/heuristic.d.ts +42 -0
- package/dist/triage/heuristic.d.ts.map +1 -0
- package/dist/triage/heuristic.js +326 -0
- package/dist/triage/heuristic.js.map +1 -0
- package/dist/triage/index.d.ts +7 -0
- package/dist/triage/index.d.ts.map +1 -0
- package/dist/triage/index.js +5 -0
- package/dist/triage/index.js.map +1 -0
- package/dist/triage/llm.d.ts +11 -0
- package/dist/triage/llm.d.ts.map +1 -0
- package/dist/triage/llm.js +48 -0
- package/dist/triage/llm.js.map +1 -0
- package/dist/triage/schema.d.ts +344 -0
- package/dist/triage/schema.d.ts.map +1 -0
- package/dist/triage/schema.js +37 -0
- package/dist/triage/schema.js.map +1 -0
- package/dist/triage/tiered.d.ts +8 -0
- package/dist/triage/tiered.d.ts.map +1 -0
- package/dist/triage/tiered.js +47 -0
- package/dist/triage/tiered.js.map +1 -0
- package/dist/types.d.ts +212 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook/handler.d.ts +22 -0
- package/dist/webhook/handler.d.ts.map +1 -0
- package/dist/webhook/handler.js +57 -0
- package/dist/webhook/handler.js.map +1 -0
- package/dist/webhook/index.d.ts +5 -0
- package/dist/webhook/index.d.ts.map +1 -0
- package/dist/webhook/index.js +3 -0
- package/dist/webhook/index.js.map +1 -0
- package/dist/webhook/registrar.d.ts +16 -0
- package/dist/webhook/registrar.d.ts.map +1 -0
- package/dist/webhook/registrar.js +50 -0
- package/dist/webhook/registrar.js.map +1 -0
- package/dist/writeback/github.d.ts +6 -0
- package/dist/writeback/github.d.ts.map +1 -0
- package/dist/writeback/github.js +48 -0
- package/dist/writeback/github.js.map +1 -0
- package/dist/writeback/index.d.ts +6 -0
- package/dist/writeback/index.d.ts.map +1 -0
- package/dist/writeback/index.js +4 -0
- package/dist/writeback/index.js.map +1 -0
- package/dist/writeback/linear.d.ts +41 -0
- package/dist/writeback/linear.d.ts.map +1 -0
- package/dist/writeback/linear.js +286 -0
- package/dist/writeback/linear.js.map +1 -0
- package/dist/writeback/shared.d.ts +7 -0
- package/dist/writeback/shared.d.ts.map +1 -0
- package/dist/writeback/shared.js +29 -0
- package/dist/writeback/shared.js.map +1 -0
- package/dist/writeback/slack.d.ts +16 -0
- package/dist/writeback/slack.d.ts.map +1 -0
- package/dist/writeback/slack.js +104 -0
- package/dist/writeback/slack.js.map +1 -0
- package/package.json +54 -9
- package/scripts/com.agentrelay.factory-canary.plist.example +53 -0
- package/scripts/factory-canary.sh +89 -0
- package/index.d.ts +0 -2
- package/index.js +0 -7
package/README.md
CHANGED
|
@@ -1,30 +1,189 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Agent Workforce Factory
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
reservation** — the real package (orchestrator, triage engine, GitHub merge-gate,
|
|
5
|
-
fleet client, StateStore, config) is extracted here from `pear/packages/factory-sdk`
|
|
6
|
-
by the **p4** workflow in the factory build-out stack.
|
|
3
|
+
**Turn issues into reviewed pull requests, automatically.**
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Point the factory at your ticketing system (Linear, GitHub, Shortcut, Asana etc) and it does the loop a human
|
|
6
|
+
otherwise babysits: it discovers the issues that are ready, decides how to tackle
|
|
7
|
+
each one, spawns coding agents to implement and review the change, opens a PR,
|
|
8
|
+
drives it through a merge gate, and closes the issue — all inside a safety scope
|
|
9
|
+
you define, so it only ever acts on work you've explicitly opted in.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Why use it
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
- **Clear the small-but-real backlog.** The well-scoped fixes and chores that pile
|
|
14
|
+
up get done without a person shepherding each one.
|
|
15
|
+
- **It only touches what you allow.** A safety gate (title prefix + team) means
|
|
16
|
+
the factory dispatches *exactly* the issues you mark for it and ignores
|
|
17
|
+
everything else — opt-in by construction.
|
|
18
|
+
- **Real PRs, not blind merges.** Every change goes through an implement → review
|
|
19
|
+
→ merge-gate flow and lands as a normal PR. It defaults to *never* auto-merging
|
|
20
|
+
until you turn that on.
|
|
21
|
+
- **You stay in the loop.** It posts threaded status to Slack and can ask a human
|
|
22
|
+
for clarification mid-task when an issue is ambiguous.
|
|
23
|
+
- **Drop in by label.** Hand it new work just by labeling a Linear or GitHub
|
|
24
|
+
issue — no new tooling in your day-to-day.
|
|
25
|
+
|
|
26
|
+
A good fit when you have a steady stream of scoped issues and want them turned
|
|
27
|
+
into PRs without standing up your own agent orchestration.
|
|
28
|
+
|
|
29
|
+
## How it works
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
discover ready issues → triage (how to do it) → dispatch agents (implement + review)
|
|
33
|
+
→ open PR → merge gate → close issue
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Each step is gated by your config and the safety scope. Issues outside the scope
|
|
37
|
+
are pulled but never dispatched.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @agent-relay/factory
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The factory talks to a relay broker through the **`agent-relay`** sidecar; install
|
|
46
|
+
and sign in to that separately (it's a peer of this package). Once installed, the
|
|
47
|
+
CLI is available as `factory`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
factory factory run-once --config ./factory.config.json --dry-run
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> Yes, `factory factory` — the `factory` CLI groups its commands under a `factory`
|
|
54
|
+
> subcommand. From a source checkout instead of an npm install, run
|
|
55
|
+
> `npm ci && npm run build` first, then `node bin/factory.mjs factory <action> …`.
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
1. **Write a minimal config** (`factory.config.json`). Only `workspaceId` and a
|
|
60
|
+
repo route are required:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"workspaceId": "your-workspace-id",
|
|
65
|
+
"repos": {
|
|
66
|
+
"byLabel": { "pear": "AgentWorkforce/pear" },
|
|
67
|
+
"clonePaths": { "AgentWorkforce/pear": "/path/to/your/pear/checkout" },
|
|
68
|
+
"default": "AgentWorkforce/pear"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`workspaceId` is your relay workspace; `repos.byLabel` maps a Linear label to a
|
|
74
|
+
repo; `clonePaths` tells the agent where that repo lives locally so it has
|
|
75
|
+
somewhere to make changes.
|
|
76
|
+
|
|
77
|
+
2. **Plan a cycle without touching anything** — `--dry-run` discovers and triages
|
|
78
|
+
but writes nothing and spawns no agents:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
factory factory run-once --config ./factory.config.json --dry-run
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
3. **Let it work for real:**
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# One discovery→dispatch cycle, then exit.
|
|
88
|
+
factory factory run-once --config ./factory.config.json
|
|
89
|
+
|
|
90
|
+
# Or run continuously as a daemon (the production form).
|
|
91
|
+
factory factory start --mode live --config ./factory.config.json
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
> **Pulled some issues but dispatched none?** That's the safety gate doing its
|
|
95
|
+
> job — the issues are real but outside your scope. See
|
|
96
|
+
> [Tell it what to work on](#tell-it-what-to-work-on).
|
|
97
|
+
|
|
98
|
+
## Commands
|
|
99
|
+
|
|
100
|
+
| Command | What it does |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `factory run-once` | One discover→triage→dispatch cycle, then exit. Honors `--dry-run`. |
|
|
103
|
+
| `factory loop` | A bounded multi-iteration loop, then exit. |
|
|
104
|
+
| `factory start --mode live` | Long-lived daemon — the production entrypoint. Runs until you stop it. |
|
|
105
|
+
| `factory status` | Print current factory status as JSON. |
|
|
106
|
+
| `factory triage <KEY\|path>` | Triage one issue and print the decision. |
|
|
107
|
+
| `factory dispatch <KEY\|path>` | Triage + dispatch one issue. Honors `--dry-run`. |
|
|
108
|
+
| `factory canary <KEY\|path>` | Assert a known "Ready for Agent" issue is dispatch-ready by the real dry-run triage path. Prints `{ok,issue,status,reason}`; exits non-zero (with the skip reason) if it isn't. |
|
|
109
|
+
|
|
110
|
+
Global options work anywhere in the args: `--config <path>`, `--dry-run`,
|
|
111
|
+
`--backend <internal|relay>`. The internal backend reuses a relay broker that's
|
|
112
|
+
already running for your workspace, and starts one if none is.
|
|
113
|
+
|
|
114
|
+
(There are a few more operational commands — `loop-status`, `kill-loop`,
|
|
115
|
+
`reap-orphans`, `close-probe` — for running the daemon in production.)
|
|
116
|
+
|
|
117
|
+
### Scheduled sync-fidelity canary
|
|
118
|
+
|
|
119
|
+
`factory canary` is the regression detector for upstream sync drift: if a synced
|
|
120
|
+
issue stops carrying enough state to be dispatchable (e.g. the Linear sync
|
|
121
|
+
regresses to records without `state.id`), a known-good issue flips from
|
|
122
|
+
dispatch-ready to skipped. Run it on a schedule against a standing "Ready for
|
|
123
|
+
Agent" canary issue and alert on failure.
|
|
124
|
+
|
|
125
|
+
`scripts/factory-canary.sh` wraps the command for cron/launchd: it runs from your
|
|
126
|
+
deployment dir (reusing the running relay broker), bounds a hung run, and posts a
|
|
127
|
+
Slack alert via `FACTORY_CANARY_SLACK_WEBHOOK` on failure. See
|
|
128
|
+
`scripts/com.agentrelay.factory-canary.plist.example` for an every-6h launchd
|
|
129
|
+
template.
|
|
130
|
+
|
|
131
|
+
## Tell it what to work on
|
|
132
|
+
|
|
133
|
+
Two ways to hand the factory an issue — both are just labeling/titling, nothing
|
|
134
|
+
to install:
|
|
135
|
+
|
|
136
|
+
| Source | What you do | Result |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| **Linear** | Title it `[factory] <task>`, set the team + a repo label, move it to **Ready for Agent** | dispatched directly |
|
|
139
|
+
| **GitHub** | Add the **`factory`** label to the issue | mirrored into a `[factory]` Linear issue, then dispatched |
|
|
140
|
+
|
|
141
|
+
The **safety gate** is what keeps this opt-in: by default the factory only
|
|
142
|
+
dispatches an issue whose **title starts with your configured prefix** *and* whose
|
|
143
|
+
**team matches** your configured team. Everything else is ignored. Loosen it
|
|
144
|
+
deliberately — it's the main guardrail.
|
|
145
|
+
|
|
146
|
+
> Tip: `[factory-e2e]` is reserved for the factory's own self-test soak (its PRs
|
|
147
|
+
> auto-close). For real work you want to keep, use the `[factory]` prefix.
|
|
148
|
+
|
|
149
|
+
## Run it as a fleet node (optional)
|
|
150
|
+
|
|
151
|
+
The package also ships a fleet **node definition** so a machine can advertise
|
|
152
|
+
`spawn:claude` / `spawn:codex` / `workflow:run` to the cloud and run agents in the
|
|
153
|
+
checkouts it owns:
|
|
17
154
|
|
|
18
|
-
**Reserve the name now (manual, no provenance — that's fine for a reservation):**
|
|
19
155
|
```bash
|
|
20
|
-
|
|
21
|
-
|
|
156
|
+
agent-relay fleet serve @agent-relay/factory/node
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
It reads its node config from `./factory.node.json` (or `$FACTORY_NODE_CONFIG`).
|
|
160
|
+
Prefer to build the definition yourself?
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { createFactoryNodeDefinition, readFactoryNodeConfigSync } from '@agent-relay/factory'
|
|
164
|
+
|
|
165
|
+
export default createFactoryNodeDefinition({ config: readFactoryNodeConfigSync() })
|
|
22
166
|
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
167
|
+
|
|
168
|
+
## Configuration
|
|
169
|
+
|
|
170
|
+
Pass a JSON file via `--config`. Beyond the two required fields above, useful
|
|
171
|
+
knobs include issue **routing** (`repos.byLabel` / `byProject` / `keywordRules` /
|
|
172
|
+
`default`), the **safety gate** (`safety.requireTitlePrefix`, `safety.requireTeamKey`),
|
|
173
|
+
`mergePolicy` (defaults to `never`), per-role **model** overrides, and an optional
|
|
174
|
+
**Slack** channel for status threads.
|
|
175
|
+
|
|
176
|
+
The full schema — every field and default — is validated by Zod at load time, so
|
|
177
|
+
an invalid config fails fast with a field-level error. See
|
|
178
|
+
[`src/config/schema.ts`](src/config/schema.ts) for the authoritative reference,
|
|
179
|
+
and [`test/fixtures/factory.config.json`](test/fixtures/factory.config.json) for a
|
|
180
|
+
worked example (including offline fixture mode).
|
|
181
|
+
|
|
182
|
+
## Notes
|
|
183
|
+
|
|
184
|
+
- The daemon is headless by design; tools like Pear can consume this package and
|
|
185
|
+
wrap it, but the published CLI is `factory`.
|
|
186
|
+
- The published `dist/` is plain ESM, runnable directly by Node (`node bin/factory.mjs`)
|
|
187
|
+
and importable by ESM consumers.
|
|
188
|
+
- For production operation (the live-daemon + reaper backstop model, heartbeats,
|
|
189
|
+
and `gh`-auth preconditions), see the operations notes alongside the config schema.
|
package/bin/factory.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { dirname, join } from 'node:path'
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
4
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
5
|
+
const entry = join(here, '..', 'dist', 'cli', 'fleet.js')
|
|
6
|
+
const mod = await import(pathToFileURL(entry).href)
|
|
7
|
+
await mod.main(process.argv.slice(2))
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createFactory, createFleet, ensureRelayBroker, type Capability, type Factory, type FactoryConfig, type FleetBackend, type FleetClient, type GhRunner, type FactoryStateResolution, type MountClient, type ProbeCloser, type RelayfileCloudMountClientConfig, type ResolvedFactoryWorkspace } from '../index.js';
|
|
2
|
+
interface FleetCliDeps {
|
|
3
|
+
fleet?: FleetClient;
|
|
4
|
+
mount?: MountClient;
|
|
5
|
+
createFactory?: typeof createFactory;
|
|
6
|
+
createFleet?: typeof createFleet;
|
|
7
|
+
ensureRelayBroker?: typeof ensureRelayBroker;
|
|
8
|
+
cloudMountFromConfig?: (config?: RelayfileCloudMountClientConfig) => Promise<MountClient>;
|
|
9
|
+
resolveWorkspace?: () => Promise<ResolvedFactoryWorkspace>;
|
|
10
|
+
resolveStates?: (mount: MountClient, config: FactoryConfig) => Promise<FactoryStateResolution>;
|
|
11
|
+
ensureLocalMount?: (workspaceId: string, startDir: string, options?: {
|
|
12
|
+
acceptableWorkspaceIds?: readonly string[];
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
waitForStopSignal?: () => Promise<number | void>;
|
|
15
|
+
stdout?: Pick<NodeJS.WriteStream, 'write'>;
|
|
16
|
+
stderr?: Pick<NodeJS.WriteStream, 'write'>;
|
|
17
|
+
probeCloser?: ProbeCloser;
|
|
18
|
+
probePrGhRunner?: GhRunner;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
stopSignalProcessLike?: Pick<NodeJS.Process, 'once' | 'off'>;
|
|
21
|
+
daemonExit?: (code: number) => void;
|
|
22
|
+
flushDaemonOutput?: () => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
interface GlobalOptions {
|
|
25
|
+
backend: FleetBackend;
|
|
26
|
+
config?: string;
|
|
27
|
+
dryRun: boolean;
|
|
28
|
+
}
|
|
29
|
+
type ParsedCommand = {
|
|
30
|
+
kind: 'spawn';
|
|
31
|
+
input: {
|
|
32
|
+
capability: Capability;
|
|
33
|
+
name?: string;
|
|
34
|
+
node?: 'self' | string;
|
|
35
|
+
task?: string;
|
|
36
|
+
model?: string;
|
|
37
|
+
sessionRef?: string;
|
|
38
|
+
cwd?: string;
|
|
39
|
+
};
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'roster';
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'release';
|
|
44
|
+
name: string;
|
|
45
|
+
reason?: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'factory';
|
|
48
|
+
action: 'run-once' | 'loop' | 'status' | 'loop-status' | 'kill-loop' | 'reap-orphans';
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'factory';
|
|
51
|
+
action: 'start';
|
|
52
|
+
mode?: 'live';
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'factory-canary';
|
|
55
|
+
issue: string;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'factory-triage';
|
|
58
|
+
issue: string;
|
|
59
|
+
} | {
|
|
60
|
+
kind: 'factory-dispatch';
|
|
61
|
+
issue: string;
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'factory-close-probe';
|
|
64
|
+
prNumber: number;
|
|
65
|
+
repo: string;
|
|
66
|
+
issue: string;
|
|
67
|
+
};
|
|
68
|
+
export declare function runFleetCli(argv: string[], deps?: FleetCliDeps): Promise<number>;
|
|
69
|
+
export declare function parseFleetCommand(args: string[]): ParsedCommand;
|
|
70
|
+
export declare function parseGlobalOptions(argv: string[]): {
|
|
71
|
+
globals: GlobalOptions;
|
|
72
|
+
args: string[];
|
|
73
|
+
};
|
|
74
|
+
export declare function resolveBrokerConnectionPath(startCwd?: string): string | undefined;
|
|
75
|
+
export declare function installFactoryStopSignalHandlers(factory: Factory, opts?: {
|
|
76
|
+
exit?: (code: number) => void;
|
|
77
|
+
processLike?: Pick<NodeJS.Process, 'once' | 'off'>;
|
|
78
|
+
}): () => void;
|
|
79
|
+
export declare function main(argv?: string[]): Promise<void>;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=fleet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../src/cli/fleet.ts"],"names":[],"mappings":"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"}
|