@elie-laloum/outpost 1.1.2 → 1.1.3
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/CHANGELOG.md +9 -0
- package/README.md +19 -191
- package/package.json +9 -6
- package/README.fr.md +0 -251
- package/ROADMAP.md +0 -34
- package/docs/api.md +0 -147
- package/docs/architecture.fr.md +0 -37
- package/docs/architecture.md +0 -57
- package/docs/migration-1.1.fr.md +0 -44
- package/docs/migration-1.1.md +0 -38
- package/docs/operations.md +0 -101
- package/docs/providers.md +0 -119
- package/docs/workflows.md +0 -101
package/docs/workflows.md
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# Workflows
|
|
2
|
-
|
|
3
|
-
Tasks form a directed acyclic graph. Each task declares its dependencies with `after`, and can only read successful values from those dependencies. Declaration order does not affect scheduling. A workflow validates duplicate keys, missing dependencies and cycles before any task runs.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { task, workflow } from "@elie-laloum/outpost";
|
|
7
|
-
|
|
8
|
-
const analyze = task({
|
|
9
|
-
key: "analyze",
|
|
10
|
-
perform: async () => ({ needed: true }),
|
|
11
|
-
});
|
|
12
|
-
const change = task({
|
|
13
|
-
key: "change",
|
|
14
|
-
after: [analyze],
|
|
15
|
-
condition: (context) => context.value(analyze).needed,
|
|
16
|
-
timeoutMs: 300_000,
|
|
17
|
-
retry: {
|
|
18
|
-
attempts: 3,
|
|
19
|
-
delayMs: 500,
|
|
20
|
-
accepts: (error) => error instanceof Error,
|
|
21
|
-
},
|
|
22
|
-
perform: async (context) => {
|
|
23
|
-
context.signal.throwIfAborted();
|
|
24
|
-
return "changed";
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const delivery = workflow("delivery", [analyze, change]);
|
|
29
|
-
console.log(delivery.diagram());
|
|
30
|
-
const result = await delivery.start({ concurrency: 2, stopOnError: true });
|
|
31
|
-
result.unwrap();
|
|
32
|
-
console.log(result.value(change));
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
`TaskContext` includes `signal`, one-based `attempt`, `executionId`, and typed `value(task)`. A condition runs before the first attempt. False conditions skip the task and its descendants. Retries occur only on failure, within the declared attempt budget, and can be filtered with `accepts`. Delays respect cancellation.
|
|
36
|
-
|
|
37
|
-
Task deadlines are **cooperative**: task code must honor `context.signal`. The scheduler waits for active work to clean up, preventing abandoned work from mutating resources after a workflow returns. Sandbox operations honor the signal. Arbitrary callbacks that ignore it cannot be forcibly stopped by JavaScript.
|
|
38
|
-
|
|
39
|
-
`stopOnError` defaults to true and aborts active siblings after the first failure. Set false to let independent branches finish. Failed/skipped dependencies skip descendants. External cancellation returns a cancelled workflow. Observers receive start/task/retry/finish events and cannot change outcomes; their exceptions are collected in `observerErrors`.
|
|
40
|
-
|
|
41
|
-
`WorkflowResult` contains immutable task records, errors, observer errors, status, execution ID, typed value access and `unwrap()`. `unwrap` throws `WorkflowFailure` for failed/cancelled results. The error retains the full result.
|
|
42
|
-
|
|
43
|
-
## Sandbox tasks
|
|
44
|
-
|
|
45
|
-
- `agentTask({ key, sandbox, request })` dispatches through an existing sandbox. `request(context)` produces the prompt/options.
|
|
46
|
-
- `commandTask({ key, sandbox, command })` executes a command and fails the task on nonzero status. The command may be a function of context.
|
|
47
|
-
- `isolatedTask({ key, request })` owns a one-shot sandbox/workspace for that task. `request(context)` supplies the complete dispatch configuration.
|
|
48
|
-
|
|
49
|
-
Use dependencies to serialize tasks sharing a sandbox. Use `isolatedTask` with distinct named workspaces for fanout. Parallel temporary integration branches serialize their host merge stage, but semantically conflicting changes still require human resolution.
|
|
50
|
-
|
|
51
|
-
## Issue campaigns
|
|
52
|
-
|
|
53
|
-
`campaign` is the application-level orchestration service for issue delivery. A `Backlog` supplies `list(signal)`, `get(id, signal)` and `close(id, signal)`. Each issue has an id, title, optional body and optional `blockedBy` ids. Blocked issues are excluded while their dependencies remain open.
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
import { campaign, codex, claude, githubBacklog } from "@elie-laloum/outpost";
|
|
57
|
-
import { docker } from "@elie-laloum/outpost/providers/docker";
|
|
58
|
-
|
|
59
|
-
const result = await campaign({
|
|
60
|
-
agent: codex(),
|
|
61
|
-
planner: claude(),
|
|
62
|
-
reviewer: codex(),
|
|
63
|
-
merger: codex(),
|
|
64
|
-
provider: docker(),
|
|
65
|
-
backlog: githubBacklog({ label: "outpost-ready" }),
|
|
66
|
-
cycles: 10,
|
|
67
|
-
concurrency: 3,
|
|
68
|
-
implementationPasses: 100,
|
|
69
|
-
reviewPasses: 1,
|
|
70
|
-
standards:
|
|
71
|
-
"Follow repository conventions, test behavior and keep comments brief.",
|
|
72
|
-
observe: (event) => console.log(event.phase, event.cycle, event.issue),
|
|
73
|
-
});
|
|
74
|
-
console.log(result.reason, result.issues);
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Each cycle refreshes the backlog. The planner returns validated assignments with unique issue ids and new branch names. Unknown issues, invalid branches and duplicate assignments fail before implementation. `planner: false` takes ready issues in order, up to the concurrency limit.
|
|
78
|
-
|
|
79
|
-
Each issue owns a named workspace and one sandbox. Implementation and optional review share that sandbox; review inspects the full diff against the cycle's base commit. An implementation without commits skips review and closure. A failed issue is recorded while independent issues finish. `reviewer: false` disables review.
|
|
80
|
-
|
|
81
|
-
Completed branches enter a separate integration sandbox, even when only one branch completed. The merger resolves conflicts, validates the result and commits corrections. Outpost verifies that the original issue commits are ancestors of the integrated result and rejects uncommitted leftovers. Only after integration into the host branch does it close the issues. Merge failure retains the workspace; tracker closure failure is reported after integration and requires reconciliation before rerunning.
|
|
82
|
-
|
|
83
|
-
The campaign stops on an empty or blocked backlog, no progress, cancellation, or the cycle limit. The result distinguishes `empty`, `blocked`, `no-progress` and `limit`, and records each issue as `empty`, `failed` or `merged`. Positive integer limits are validated before work starts.
|
|
84
|
-
|
|
85
|
-
## Starter templates
|
|
86
|
-
|
|
87
|
-
| Template | Structure |
|
|
88
|
-
| ------------- | ---------------------------------------------------------------------------------- |
|
|
89
|
-
| `blank` | One dispatch with a configurable objective. |
|
|
90
|
-
| `iterate` | Sequential campaign; reloads the tracker each cycle. |
|
|
91
|
-
| `review` | Sequential implementation and conditional warm review per issue. |
|
|
92
|
-
| `plan` | Typed plan, separate issue branches, bounded concurrent execution and integration. |
|
|
93
|
-
| `plan-review` | Planned parallel execution with a warm review for each changed issue. |
|
|
94
|
-
|
|
95
|
-
Without a tracker, a campaign starter wraps the command-line objective as one in-memory issue. With `--tracker github`, `beads` or `custom`, the tracker supplies the workload. Limits and role adapters are editable at the top level of the generated call; standards live in `.outpost/STANDARDS.md`.
|
|
96
|
-
|
|
97
|
-
GitHub uses authenticated host `gh`, paginates all issue pages, excludes pull requests and applies the configured label. `--label NAME` creates/updates the label and configures filtering. Declare `GH_TOKEN` in `.outpost/.env` or authenticate `gh` directly. The connector follows the official [GitHub CLI pagination contract](https://cli.github.com/manual/gh_api).
|
|
98
|
-
|
|
99
|
-
Beads uses host `bd ready --json --limit 0`, `bd show` and `bd close`. Install and initialize [Beads](https://github.com/gastownhall/beads) on the host before running. Selecting Beads also installs its pinned CLI in the generated container image.
|
|
100
|
-
|
|
101
|
-
The custom starter implements three HTTP operations: GET `issues?state=open`, GET `issues/:id`, POST `issues/:id/close`. Set `OUTPOST_TRACKER_URL` on the host and adapt authentication/pagination in `tickets.ts` or `tickets.mts`. `.outpost/TRACKER.md` documents the contract. Keep tracker mutation in the host connector so agents do not close issues before integration.
|