singleton-pipeline 0.4.0-beta.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/LICENSE +21 -0
- package/README.md +200 -0
- package/docs/reference.md +1038 -0
- package/package.json +75 -0
- package/packages/cli/package.json +18 -0
- package/packages/cli/src/commands/new.js +440 -0
- package/packages/cli/src/commands/repl.js +551 -0
- package/packages/cli/src/executor.js +2646 -0
- package/packages/cli/src/index.js +107 -0
- package/packages/cli/src/parser.js +78 -0
- package/packages/cli/src/runners/_shared.js +83 -0
- package/packages/cli/src/runners/claude.js +119 -0
- package/packages/cli/src/runners/codex-instructions.js +75 -0
- package/packages/cli/src/runners/codex.js +162 -0
- package/packages/cli/src/runners/copilot.js +208 -0
- package/packages/cli/src/runners/index.js +20 -0
- package/packages/cli/src/runners/opencode.js +265 -0
- package/packages/cli/src/scanner.js +47 -0
- package/packages/cli/src/security/policy.js +126 -0
- package/packages/cli/src/shell.js +542 -0
- package/packages/cli/src/theme.js +46 -0
- package/packages/cli/src/timeline.js +146 -0
- package/packages/server/package.json +11 -0
- package/packages/server/src/index.js +43 -0
- package/packages/server/src/routes/agents.js +32 -0
- package/packages/server/src/routes/files.js +42 -0
- package/packages/server/src/routes/pipelines.js +74 -0
- package/packages/web/dist/assets/index-CCFWfCA2.css +1 -0
- package/packages/web/dist/assets/index-CnKytBly.js +55 -0
- package/packages/web/dist/index.html +13 -0
- package/packages/web/package.json +23 -0
|
@@ -0,0 +1,1038 @@
|
|
|
1
|
+
# Singleton Reference
|
|
2
|
+
|
|
3
|
+
This document is the detailed reference for Singleton.
|
|
4
|
+
|
|
5
|
+
Use the main [README](../README.md) for the product overview and quickstart.
|
|
6
|
+
Use this file when you need exact behavior, node semantics, command details, or execution rules.
|
|
7
|
+
|
|
8
|
+
## Table of contents
|
|
9
|
+
|
|
10
|
+
- [Terminology](#terminology)
|
|
11
|
+
- [Project workspace](#project-workspace)
|
|
12
|
+
- [Agent model](#agent-model)
|
|
13
|
+
- [Pipeline model](#pipeline-model)
|
|
14
|
+
- [Security model](#security-model)
|
|
15
|
+
- [Node types](#node-types)
|
|
16
|
+
- [References](#references)
|
|
17
|
+
- [Execution model](#execution-model)
|
|
18
|
+
- [Debug mode](#debug-mode)
|
|
19
|
+
- [Deliverables vs intermediates](#deliverables-vs-intermediates)
|
|
20
|
+
- [Run artifacts](#run-artifacts)
|
|
21
|
+
- [Multi-provider model](#multi-provider-model)
|
|
22
|
+
- [CLI commands](#cli-commands)
|
|
23
|
+
- [REPL commands](#repl-commands)
|
|
24
|
+
- [`/commit-last`](#commit-last)
|
|
25
|
+
- [Builder](#builder)
|
|
26
|
+
- [Full pipeline example](#full-pipeline-example)
|
|
27
|
+
- [Troubleshooting](#troubleshooting)
|
|
28
|
+
|
|
29
|
+
## Terminology
|
|
30
|
+
|
|
31
|
+
- **project**: the target codebase where Singleton runs
|
|
32
|
+
- **agent**: a Markdown file with a `## Config` section and a prompt
|
|
33
|
+
- **pipeline**: a directed graph of inputs and agent steps
|
|
34
|
+
- **run**: one execution of a pipeline
|
|
35
|
+
- **deliverable**: a real project file written outside `.singleton`
|
|
36
|
+
- **intermediate**: a report, plan, log, or temporary artifact written inside `.singleton`
|
|
37
|
+
|
|
38
|
+
## Project workspace
|
|
39
|
+
|
|
40
|
+
Singleton is project-local. A typical target project looks like this:
|
|
41
|
+
|
|
42
|
+
```txt
|
|
43
|
+
my-project/
|
|
44
|
+
.singleton/
|
|
45
|
+
agents/
|
|
46
|
+
agents.json
|
|
47
|
+
pipelines/
|
|
48
|
+
runs/
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Meaning:
|
|
52
|
+
|
|
53
|
+
- `.singleton/agents/` contains Singleton-native agents
|
|
54
|
+
- `.singleton/agents.json` is the scan cache
|
|
55
|
+
- `.singleton/pipelines/` contains saved pipeline definitions
|
|
56
|
+
- `.singleton/runs/` contains versioned run artifacts and manifests
|
|
57
|
+
|
|
58
|
+
Compatibility sources:
|
|
59
|
+
|
|
60
|
+
- `.claude/agents/` is scanned as a legacy or external source
|
|
61
|
+
- `AGENTS.md` and `AGENTS.override.md` are not agents; they are Codex project instructions
|
|
62
|
+
|
|
63
|
+
## Agent model
|
|
64
|
+
|
|
65
|
+
Agents are Markdown files.
|
|
66
|
+
|
|
67
|
+
Minimal structure:
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
# Agent Title
|
|
71
|
+
|
|
72
|
+
## Config
|
|
73
|
+
|
|
74
|
+
- **id**: my-agent
|
|
75
|
+
- **description**: What the agent does
|
|
76
|
+
- **inputs**: input_a, input_b
|
|
77
|
+
- **outputs**: output_a
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Prompt
|
|
82
|
+
|
|
83
|
+
Your prompt here.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Required fields
|
|
87
|
+
|
|
88
|
+
- `id`
|
|
89
|
+
- `description`
|
|
90
|
+
- `inputs`
|
|
91
|
+
- `outputs`
|
|
92
|
+
|
|
93
|
+
### Optional fields
|
|
94
|
+
|
|
95
|
+
- `tags`
|
|
96
|
+
- `provider`
|
|
97
|
+
- `model`
|
|
98
|
+
- `runner_agent`
|
|
99
|
+
- `permission_mode`
|
|
100
|
+
- `estimated_tokens`
|
|
101
|
+
- `security_profile`
|
|
102
|
+
- `allowed_paths`
|
|
103
|
+
- `blocked_paths`
|
|
104
|
+
|
|
105
|
+
### Field semantics
|
|
106
|
+
|
|
107
|
+
- `id` — stable identifier used in scans and step definitions
|
|
108
|
+
- `description` — human-readable summary shown in scan output and tooling
|
|
109
|
+
- `inputs` — comma-separated list of logical inputs exposed to the prompt
|
|
110
|
+
- `outputs` — comma-separated list of logical outputs expected from the step
|
|
111
|
+
- `tags` — optional categorization
|
|
112
|
+
- `provider` — execution backend, currently `claude`, `codex`, `copilot`, or experimental `opencode`
|
|
113
|
+
- `model` — provider-specific model name
|
|
114
|
+
- `runner_agent` — provider-side agent name; currently used by Copilot and OpenCode `--agent` options
|
|
115
|
+
- `permission_mode` — applies to Claude only, ignored for Codex runs
|
|
116
|
+
- `estimated_tokens` — optional metadata for planning
|
|
117
|
+
- `security_profile` — Singleton write policy profile
|
|
118
|
+
- `allowed_paths` — comma-separated write allowlist used by `restricted-write`
|
|
119
|
+
- `blocked_paths` — comma-separated additional write blocklist
|
|
120
|
+
|
|
121
|
+
### Provider resolution
|
|
122
|
+
|
|
123
|
+
When running a step, Singleton resolves provider in this order:
|
|
124
|
+
|
|
125
|
+
1. `step.provider`
|
|
126
|
+
2. `agent.provider`
|
|
127
|
+
3. fallback to `claude`
|
|
128
|
+
|
|
129
|
+
Model resolution:
|
|
130
|
+
|
|
131
|
+
1. `step.model`
|
|
132
|
+
2. `agent.model`
|
|
133
|
+
3. no explicit model
|
|
134
|
+
|
|
135
|
+
Runner agent resolution (Copilot and OpenCode):
|
|
136
|
+
|
|
137
|
+
1. `step.runner_agent`
|
|
138
|
+
2. `agent.runner_agent`
|
|
139
|
+
3. no explicit runner agent, so the provider uses its default agent
|
|
140
|
+
|
|
141
|
+
Permission mode resolution (Claude only):
|
|
142
|
+
|
|
143
|
+
1. `step.permission_mode`
|
|
144
|
+
2. `agent.permission_mode`
|
|
145
|
+
3. no explicit permission mode
|
|
146
|
+
|
|
147
|
+
Security policy resolution:
|
|
148
|
+
|
|
149
|
+
1. `step.security_profile`
|
|
150
|
+
2. `agent.security_profile`
|
|
151
|
+
3. `.singleton/security.json` `default_profile`
|
|
152
|
+
4. fallback to `workspace-write`
|
|
153
|
+
|
|
154
|
+
Path policy fields are resolved the same way:
|
|
155
|
+
|
|
156
|
+
1. step-level `allowed_paths` / `blocked_paths`
|
|
157
|
+
2. agent-level `allowed_paths` / `blocked_paths`
|
|
158
|
+
3. `.singleton/security.json` `allowed_paths` / `blocked_paths`
|
|
159
|
+
4. default built-in protections
|
|
160
|
+
|
|
161
|
+
If `step.provider` overrides `agent.provider`, the step value wins silently — the agent's preference is treated as a default, not a constraint.
|
|
162
|
+
|
|
163
|
+
## Security model
|
|
164
|
+
|
|
165
|
+
Singleton has its own project-root policy layer. It is separate from provider permissions.
|
|
166
|
+
|
|
167
|
+
- **Policy** in the run recap means Singleton's policy for the step.
|
|
168
|
+
- `permission_mode` is provider-specific. Today it mainly matters for Claude, for example `bypassPermissions`.
|
|
169
|
+
- A step can therefore show `restricted-write · perm:bypassPermissions`: Claude is allowed to use write tools, but Singleton still validates and monitors the allowed paths.
|
|
170
|
+
- Copilot receives provider-native tool permissions generated from the resolved Singleton policy.
|
|
171
|
+
- OpenCode receives provider-native permissions through runtime config, and Singleton still applies write-time and post-run validation afterwards.
|
|
172
|
+
|
|
173
|
+
### Security profiles
|
|
174
|
+
|
|
175
|
+
Supported profiles:
|
|
176
|
+
|
|
177
|
+
- `read-only` — the step may read files and produce pipeline outputs, but it must not modify project files.
|
|
178
|
+
- `workspace-write` — the step may write project files, except protected or blocked paths.
|
|
179
|
+
- `restricted-write` — the step may write only inside `allowed_paths`.
|
|
180
|
+
- `dangerous` — disables built-in blocked-path checks, but still forbids writes outside the project root.
|
|
181
|
+
|
|
182
|
+
Built-in protected paths:
|
|
183
|
+
|
|
184
|
+
- `.git`
|
|
185
|
+
- `node_modules`
|
|
186
|
+
- `.env`
|
|
187
|
+
- `.env.*`
|
|
188
|
+
- `.ssh`
|
|
189
|
+
|
|
190
|
+
Local tooling directories such as `.idea` and `.vscode` are ignored by post-run snapshots to avoid IDE noise, but they should still be blocked or excluded through project security config.
|
|
191
|
+
|
|
192
|
+
### Project security config
|
|
193
|
+
|
|
194
|
+
A project can define `.singleton/security.json`.
|
|
195
|
+
|
|
196
|
+
Example:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"default_profile": "workspace-write",
|
|
201
|
+
"blocked_paths": [
|
|
202
|
+
".env",
|
|
203
|
+
".env.*",
|
|
204
|
+
".git",
|
|
205
|
+
".idea",
|
|
206
|
+
".vscode",
|
|
207
|
+
"dist",
|
|
208
|
+
"node_modules"
|
|
209
|
+
],
|
|
210
|
+
"commit": {
|
|
211
|
+
"exclude_paths": [
|
|
212
|
+
".singleton",
|
|
213
|
+
".idea",
|
|
214
|
+
".vscode",
|
|
215
|
+
"dist",
|
|
216
|
+
"node_modules"
|
|
217
|
+
],
|
|
218
|
+
"require_confirmation": true
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Resolution order:
|
|
224
|
+
|
|
225
|
+
1. step-level fields
|
|
226
|
+
2. agent-level fields
|
|
227
|
+
3. `.singleton/security.json`
|
|
228
|
+
4. Singleton defaults
|
|
229
|
+
|
|
230
|
+
### Step-level policy
|
|
231
|
+
|
|
232
|
+
Pipeline steps can override the agent or project defaults.
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"agent": "fix-executor",
|
|
237
|
+
"agent_file": ".singleton/agents/fix-executor.md",
|
|
238
|
+
"security_profile": "restricted-write",
|
|
239
|
+
"allowed_paths": [
|
|
240
|
+
"src",
|
|
241
|
+
"vite.config.ts",
|
|
242
|
+
"CLAUDE.md"
|
|
243
|
+
],
|
|
244
|
+
"inputs": {
|
|
245
|
+
"plan": "$PIPE:planner.plan"
|
|
246
|
+
},
|
|
247
|
+
"outputs": {
|
|
248
|
+
"execution_report": "$FILE:.singleton/output/execution.md"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`allowed_paths` accepts both files and directories.
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"allowed_paths": ["src"]
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
This allows writes to `src/App.vue`, `src/styles/main.scss`, `src/components/Button.vue`, etc.
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"allowed_paths": ["src/securitySmoke.ts"]
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
This allows only that exact file.
|
|
270
|
+
|
|
271
|
+
### Agent prompt injection
|
|
272
|
+
|
|
273
|
+
Singleton injects the resolved policy into each step prompt.
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
|
|
277
|
+
```txt
|
|
278
|
+
<security_policy>
|
|
279
|
+
security_profile: restricted-write
|
|
280
|
+
allowed_paths:
|
|
281
|
+
- src/securitySmoke.ts
|
|
282
|
+
blocked_paths:
|
|
283
|
+
- .git
|
|
284
|
+
- node_modules
|
|
285
|
+
- .env
|
|
286
|
+
|
|
287
|
+
Rules:
|
|
288
|
+
- You may modify project files only inside allowed_paths.
|
|
289
|
+
- If the requested change requires files outside allowed_paths, stop and explain it in your output.
|
|
290
|
+
- Internal run artifacts are handled by Singleton; do not write into .singleton manually.
|
|
291
|
+
</security_policy>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
This reduces accidental violations, but it is not trusted as the only enforcement layer.
|
|
295
|
+
|
|
296
|
+
### Enforcement layers
|
|
297
|
+
|
|
298
|
+
Singleton checks security in three places:
|
|
299
|
+
|
|
300
|
+
- **Preflight**: validates unsafe sinks, unknown profiles, missing `allowed_paths` for `restricted-write`, and provider permissions before calling an LLM CLI.
|
|
301
|
+
- **Write-time**: validates `$FILE` and `$FILES` writes immediately before Singleton writes them.
|
|
302
|
+
- **Post-run validation**: snapshots the project before and after each step, detects real project changes, and checks them against the step policy.
|
|
303
|
+
|
|
304
|
+
This matters because provider CLIs can edit files directly through their own tools. Post-run validation detects those direct edits even if they did not go through `$FILE` or `$FILES`.
|
|
305
|
+
|
|
306
|
+
### Copilot tool permissions
|
|
307
|
+
|
|
308
|
+
For `provider: copilot`, Singleton converts the resolved security policy to Copilot CLI permission flags.
|
|
309
|
+
|
|
310
|
+
Mapping:
|
|
311
|
+
|
|
312
|
+
- `read-only` — allows `read`, denies `write`, `shell`, `url`, and `memory`.
|
|
313
|
+
- `restricted-write` — allows `read` and `write(...)` only for each `allowed_paths` entry.
|
|
314
|
+
- `workspace-write` — allows `read` and `write`, while still denying dangerous shell defaults such as `git push`.
|
|
315
|
+
- `dangerous` — uses Copilot's broad tool mode and keeps explicit deny rules where possible.
|
|
316
|
+
|
|
317
|
+
Examples:
|
|
318
|
+
|
|
319
|
+
```txt
|
|
320
|
+
restricted-write + allowed_paths: src, vite.config.ts
|
|
321
|
+
→ --allow-tool=read
|
|
322
|
+
→ --allow-tool=write(src/**)
|
|
323
|
+
→ --allow-tool=write(vite.config.ts)
|
|
324
|
+
→ --deny-tool=shell(git push)
|
|
325
|
+
→ --deny-tool=url
|
|
326
|
+
→ --deny-tool=memory
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Copilot permissions reduce risk before the step runs. Singleton still performs write-time and post-run validation afterwards.
|
|
330
|
+
|
|
331
|
+
### OpenCode security status
|
|
332
|
+
|
|
333
|
+
For `provider: opencode`, Singleton runs the local OpenCode CLI in non-interactive mode.
|
|
334
|
+
|
|
335
|
+
Current V1 behavior:
|
|
336
|
+
|
|
337
|
+
- `security_profile: dangerous` passes `--dangerously-skip-permissions`
|
|
338
|
+
- every other profile avoids broad OpenCode permission bypass
|
|
339
|
+
- Singleton injects OpenCode native permissions through `OPENCODE_CONFIG_CONTENT`
|
|
340
|
+
- if `runner_agent` is set, Singleton also injects the same permissions under `agent.<runner_agent>.permission`
|
|
341
|
+
- `read-only` maps to `edit: deny`, `bash: deny`, `webfetch: deny`, `websearch: deny`, and `external_directory: deny`
|
|
342
|
+
- `restricted-write` maps `allowed_paths` to OpenCode `edit` path rules
|
|
343
|
+
- `workspace-write` allows edit operations inside the workspace while keeping `external_directory` denied
|
|
344
|
+
- Singleton still validates declared `$FILE` / `$FILES` sinks before writing
|
|
345
|
+
- Singleton still detects real project file changes after each step
|
|
346
|
+
- read-only and restricted-write violations are blocked by Singleton post-run validation
|
|
347
|
+
|
|
348
|
+
OpenCode permissions are provider-native, but Singleton still keeps write-time and post-run validation as a second layer.
|
|
349
|
+
|
|
350
|
+
### Security violations
|
|
351
|
+
|
|
352
|
+
In non-interactive CLI mode, a post-run violation fails the pipeline.
|
|
353
|
+
|
|
354
|
+
In the REPL/TUI, Singleton pauses:
|
|
355
|
+
|
|
356
|
+
```txt
|
|
357
|
+
Security violation: continue, stop, or diff? (c/s/d)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Actions:
|
|
361
|
+
|
|
362
|
+
- `c` / `continue` — continue the pipeline.
|
|
363
|
+
- `s` / `stop` / Enter — stop the pipeline.
|
|
364
|
+
- `d` / `diff` — print a bounded `git diff` preview for the violated files.
|
|
365
|
+
|
|
366
|
+
Diff previews are intentionally limited to avoid flooding the terminal.
|
|
367
|
+
|
|
368
|
+
### Run status on failure
|
|
369
|
+
|
|
370
|
+
Real runs write a manifest even when the pipeline fails after it has started.
|
|
371
|
+
|
|
372
|
+
Failed manifests include:
|
|
373
|
+
|
|
374
|
+
- `status: "failed"`
|
|
375
|
+
- `error.message`
|
|
376
|
+
- completed step stats
|
|
377
|
+
- intermediates already produced
|
|
378
|
+
- deliverables detected before failure
|
|
379
|
+
|
|
380
|
+
`.singleton/runs/latest` still points to the failed run so it can be inspected.
|
|
381
|
+
|
|
382
|
+
### Recommended pattern
|
|
383
|
+
|
|
384
|
+
Use strict policies for multi-step pipelines:
|
|
385
|
+
|
|
386
|
+
- scouts, auditors, planners, and reviewers: `read-only`
|
|
387
|
+
- code writers: `restricted-write` with the smallest reasonable `allowed_paths`
|
|
388
|
+
- broad project refactors: `restricted-write` with a directory like `src`
|
|
389
|
+
- avoid `dangerous` except for local experiments
|
|
390
|
+
|
|
391
|
+
For Claude writers that need file tools, set both layers explicitly:
|
|
392
|
+
|
|
393
|
+
```json
|
|
394
|
+
{
|
|
395
|
+
"security_profile": "restricted-write",
|
|
396
|
+
"allowed_paths": ["src"],
|
|
397
|
+
"permission_mode": "bypassPermissions"
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
This lets Claude write, while Singleton still constrains and validates the result.
|
|
402
|
+
|
|
403
|
+
## Pipeline model
|
|
404
|
+
|
|
405
|
+
A pipeline is a directed graph serialized as JSON.
|
|
406
|
+
|
|
407
|
+
Conceptually:
|
|
408
|
+
|
|
409
|
+
- input nodes provide runtime values or file paths
|
|
410
|
+
- agent nodes represent executable steps
|
|
411
|
+
- edges connect outputs to downstream inputs
|
|
412
|
+
|
|
413
|
+
At runtime, Singleton executes steps in dependency order.
|
|
414
|
+
Dependencies are derived from the serialized references used in step inputs, especially `$PIPE:...`.
|
|
415
|
+
|
|
416
|
+
A complete example is in [Full pipeline example](#full-pipeline-example).
|
|
417
|
+
|
|
418
|
+
## Node types
|
|
419
|
+
|
|
420
|
+
### Input node
|
|
421
|
+
|
|
422
|
+
Purpose:
|
|
423
|
+
|
|
424
|
+
- capture a runtime text value
|
|
425
|
+
- capture a runtime file path
|
|
426
|
+
|
|
427
|
+
Typical shape:
|
|
428
|
+
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"id": "input-spec",
|
|
432
|
+
"type": "input",
|
|
433
|
+
"data": {
|
|
434
|
+
"label": "spec",
|
|
435
|
+
"subtype": "file",
|
|
436
|
+
"value": ""
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Relevant fields:
|
|
442
|
+
|
|
443
|
+
- `id` — referenced later through `$INPUT:<id>`
|
|
444
|
+
- `label` — user-facing prompt label
|
|
445
|
+
- `subtype` — `text` or `file`
|
|
446
|
+
- `value` — optional default value
|
|
447
|
+
|
|
448
|
+
Behavior:
|
|
449
|
+
|
|
450
|
+
- in normal runs, missing values are prompted interactively
|
|
451
|
+
- in dry-runs, placeholder values are injected
|
|
452
|
+
- for `file` inputs, the value is treated as a path and resolved through the file loader
|
|
453
|
+
|
|
454
|
+
### Agent node
|
|
455
|
+
|
|
456
|
+
Purpose:
|
|
457
|
+
|
|
458
|
+
- represent one executable step bound to an agent file
|
|
459
|
+
|
|
460
|
+
In saved pipelines, agent nodes are converted into `steps[]`.
|
|
461
|
+
|
|
462
|
+
Typical step shape:
|
|
463
|
+
|
|
464
|
+
```json
|
|
465
|
+
{
|
|
466
|
+
"agent": "code-generator",
|
|
467
|
+
"agent_file": ".singleton/agents/code-generator.md",
|
|
468
|
+
"inputs": {
|
|
469
|
+
"spec": "$INPUT:input-spec"
|
|
470
|
+
},
|
|
471
|
+
"outputs": {
|
|
472
|
+
"source_code": "$FILE:src/generated/output.js"
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## References
|
|
478
|
+
|
|
479
|
+
Singleton uses four reference types.
|
|
480
|
+
|
|
481
|
+
### `$INPUT:<id>`
|
|
482
|
+
|
|
483
|
+
Use when a step needs a runtime value from an input node.
|
|
484
|
+
|
|
485
|
+
```json
|
|
486
|
+
{ "request": "$INPUT:input-request" }
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Behavior:
|
|
490
|
+
|
|
491
|
+
- resolves to a string value
|
|
492
|
+
- if the input node subtype is `file`, Singleton treats the resolved value as a path and reads the file(s)
|
|
493
|
+
|
|
494
|
+
### `$FILE:<path>`
|
|
495
|
+
|
|
496
|
+
Read or write a single file.
|
|
497
|
+
|
|
498
|
+
```json
|
|
499
|
+
{ "spec": "$FILE:docs/spec.md" }
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Behavior:
|
|
503
|
+
|
|
504
|
+
- **input side**: file content is read and injected into the prompt as `<file path="...">...</file>`
|
|
505
|
+
- **output side**: after the step finishes, the value mapped to that output key is written verbatim to the target path. The agent's output is treated as a raw string — no JSON parsing, no transformation.
|
|
506
|
+
- writes happen between the step that produced the value and the next step that depends on it
|
|
507
|
+
- target paths are validated against the project root before writing
|
|
508
|
+
|
|
509
|
+
### `$PIPE:<agent>.<output>`
|
|
510
|
+
|
|
511
|
+
Pass one step output to another.
|
|
512
|
+
|
|
513
|
+
```json
|
|
514
|
+
{ "source_code": "$PIPE:code-generator.source_code" }
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Behavior:
|
|
518
|
+
|
|
519
|
+
- references a previous step output kept in memory during the run
|
|
520
|
+
- drives dependency ordering — `$PIPE` is what makes the graph topological
|
|
521
|
+
- must point to an already-available upstream step output, otherwise preflight fails
|
|
522
|
+
|
|
523
|
+
### `$FILES:<dir>`
|
|
524
|
+
|
|
525
|
+
Use when a step needs to create multiple files from one output.
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
{ "files": "$FILES:src/generated" }
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
The agent must return a JSON-parseable string with this shape:
|
|
532
|
+
|
|
533
|
+
```json
|
|
534
|
+
[
|
|
535
|
+
{ "path": "a.js", "content": "..." },
|
|
536
|
+
{ "path": "b.js", "content": "..." }
|
|
537
|
+
]
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Behavior:
|
|
541
|
+
|
|
542
|
+
- the runner parses the agent output as JSON; if parsing fails the step is reported as failed
|
|
543
|
+
- each entry is written relative to the target base directory
|
|
544
|
+
- paths are validated against the project root before writing
|
|
545
|
+
|
|
546
|
+
## Execution model
|
|
547
|
+
|
|
548
|
+
Each run goes through these phases:
|
|
549
|
+
|
|
550
|
+
1. load pipeline JSON
|
|
551
|
+
2. resolve project root
|
|
552
|
+
3. collect runtime inputs
|
|
553
|
+
4. run preflight checks
|
|
554
|
+
5. execute each step in order
|
|
555
|
+
6. write step intermediates and declared deliverables
|
|
556
|
+
7. validate post-step project changes against the step policy
|
|
557
|
+
8. detect final deliverables
|
|
558
|
+
9. write a run manifest, including failed runs
|
|
559
|
+
10. print a run summary
|
|
560
|
+
|
|
561
|
+
### Preflight
|
|
562
|
+
|
|
563
|
+
Preflight is always the first visible system step.
|
|
564
|
+
|
|
565
|
+
It validates:
|
|
566
|
+
|
|
567
|
+
- input presence
|
|
568
|
+
- input file resolution
|
|
569
|
+
- agent file existence
|
|
570
|
+
- agent parsing
|
|
571
|
+
- provider validity
|
|
572
|
+
- provider CLI availability
|
|
573
|
+
- security profile validity
|
|
574
|
+
- project security config
|
|
575
|
+
- `$INPUT` references
|
|
576
|
+
- `$PIPE` references
|
|
577
|
+
- `$FILE` input resolution
|
|
578
|
+
- unsafe sink paths
|
|
579
|
+
|
|
580
|
+
Possible outcomes:
|
|
581
|
+
|
|
582
|
+
- **info**
|
|
583
|
+
- **warning**
|
|
584
|
+
- **error**
|
|
585
|
+
|
|
586
|
+
Errors stop the run before any provider CLI is called.
|
|
587
|
+
|
|
588
|
+
### Dry-run
|
|
589
|
+
|
|
590
|
+
Dry-run:
|
|
591
|
+
|
|
592
|
+
- skips actual provider CLI calls
|
|
593
|
+
- still runs pipeline loading and preflight
|
|
594
|
+
- still resolves the execution plan
|
|
595
|
+
- still renders the recap
|
|
596
|
+
|
|
597
|
+
Use it to validate a pipeline structure safely.
|
|
598
|
+
|
|
599
|
+
## Debug mode
|
|
600
|
+
|
|
601
|
+
Debug mode pauses before and after each agent step.
|
|
602
|
+
|
|
603
|
+
```bash
|
|
604
|
+
singleton run --pipeline .singleton/pipelines/my-pipeline.json --debug
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
In the REPL:
|
|
608
|
+
|
|
609
|
+
```txt
|
|
610
|
+
/run my-pipeline --debug
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Before each step, Singleton displays:
|
|
614
|
+
|
|
615
|
+
- step number
|
|
616
|
+
- agent id
|
|
617
|
+
- provider
|
|
618
|
+
- model
|
|
619
|
+
- security profile
|
|
620
|
+
- permission mode when present
|
|
621
|
+
- expected outputs
|
|
622
|
+
- resolved inputs
|
|
623
|
+
|
|
624
|
+
Available actions:
|
|
625
|
+
|
|
626
|
+
| Action | Alias | Behavior |
|
|
627
|
+
| ------ | ----- | -------- |
|
|
628
|
+
| `continue` | `c` | run the step normally |
|
|
629
|
+
| `inspect` | `i` | print the full system prompt and user message that will be sent to the provider |
|
|
630
|
+
| `edit` | `e` | override resolved inputs for this run only |
|
|
631
|
+
| `skip` | `s` | skip the current step and register placeholder outputs |
|
|
632
|
+
| `abort` | `a` | stop the pipeline before the step runs |
|
|
633
|
+
|
|
634
|
+
After each executed step, Singleton displays:
|
|
635
|
+
|
|
636
|
+
- parsed outputs
|
|
637
|
+
- files written through declared `$FILE` / `$FILES` sinks
|
|
638
|
+
- project files changed during the step
|
|
639
|
+
- output warnings, such as empty parsed outputs
|
|
640
|
+
|
|
641
|
+
Post-step actions:
|
|
642
|
+
|
|
643
|
+
| Action | Alias | Behavior |
|
|
644
|
+
| ------ | ----- | -------- |
|
|
645
|
+
| `continue` | `c` | continue to the next step |
|
|
646
|
+
| `output` | `o` | print the parsed outputs in full |
|
|
647
|
+
| `raw output` | `r` | print the raw provider response before Singleton parsed it |
|
|
648
|
+
| `diff` | `d` | print git diff previews for detected project changes |
|
|
649
|
+
| `replay` | `p` | restore project file changes from the previous attempt, optionally edit inputs, and rerun the same step |
|
|
650
|
+
| `abort` | `a` | stop the pipeline after the current step |
|
|
651
|
+
|
|
652
|
+
Edited inputs are runtime-only:
|
|
653
|
+
|
|
654
|
+
- the pipeline JSON is not modified
|
|
655
|
+
- the source agent Markdown is not modified
|
|
656
|
+
- downstream `$PIPE` references receive the runtime output produced after the edited prompt
|
|
657
|
+
- Singleton warns that editing one input may not override other inputs or the agent prompt
|
|
658
|
+
- after editing, Singleton can immediately show the final prompt
|
|
659
|
+
- edited input tags are marked with `debug-edited="true"` in prompt preview
|
|
660
|
+
|
|
661
|
+
Replay is scoped to the current step:
|
|
662
|
+
|
|
663
|
+
- project files changed by the previous attempt are restored before the next attempt
|
|
664
|
+
- intermediate run artifacts from previous attempts are kept for traceability
|
|
665
|
+
- the step output registry is reset before rerun so downstream `$PIPE` references use the final attempt
|
|
666
|
+
- the final recap and manifest report the final attempt, plus an `attempts` count
|
|
667
|
+
- duration, turns, and cost are cumulative across attempts
|
|
668
|
+
- replay is capped at 3 replays per step by default
|
|
669
|
+
|
|
670
|
+
Replay has deliberate limits:
|
|
671
|
+
|
|
672
|
+
- skipped folders such as `.git`, `node_modules`, `dist`, `build`, `.next`, `.cache`, and `coverage` are not restored
|
|
673
|
+
- external side effects such as commits, pushes, pull requests, shell state, or network calls are not rolled back
|
|
674
|
+
- if restoration fails, Singleton aborts the pipeline instead of continuing from a mixed filesystem state
|
|
675
|
+
|
|
676
|
+
Debug step artifacts are written at the step root by default. When a step is replayed, Singleton moves the first attempt into `attempt-1` and writes the next attempts into `attempt-2`, `attempt-3`, etc.:
|
|
677
|
+
|
|
678
|
+
```txt
|
|
679
|
+
.singleton/runs/DEBUG-20260501-151230-my-pipeline/01-agent-id/report.md
|
|
680
|
+
.singleton/runs/DEBUG-20260501-151230-my-pipeline/02-agent-id/attempt-1/report.md
|
|
681
|
+
.singleton/runs/DEBUG-20260501-151230-my-pipeline/02-agent-id/attempt-2/report.md
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
During debug prompts, the pipeline log remains scrollable with arrow keys, page up/down, home, and end. The timeline marks the current step as `Paused` until you choose an action.
|
|
685
|
+
|
|
686
|
+
Debug run directories are prefixed with `DEBUG-`:
|
|
687
|
+
|
|
688
|
+
```txt
|
|
689
|
+
.singleton/runs/DEBUG-20260501-151230-my-pipeline/
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Debug runs add a `debugEvents` array to `run-manifest.json`.
|
|
693
|
+
|
|
694
|
+
Each event contains:
|
|
695
|
+
|
|
696
|
+
- timestamp
|
|
697
|
+
- step id
|
|
698
|
+
- phase (`pre-step` or `post-step`)
|
|
699
|
+
- action
|
|
700
|
+
- compact metadata such as edited input names, output names, written files, changed files, or warnings
|
|
701
|
+
|
|
702
|
+
Large prompt/output bodies are not stored in `debugEvents`; use run artifacts and the interactive inspect views for full content.
|
|
703
|
+
|
|
704
|
+
When structured output parsing fails, for example invalid `$FILES` JSON, Singleton writes the raw provider response before failing the step:
|
|
705
|
+
|
|
706
|
+
```txt
|
|
707
|
+
.singleton/runs/<run-id>/<step>/raw-output.md
|
|
708
|
+
.singleton/runs/<debug-run-id>/<step>/attempt-1/raw-output.md
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
## Deliverables vs intermediates
|
|
712
|
+
|
|
713
|
+
Singleton distinguishes between:
|
|
714
|
+
|
|
715
|
+
- **deliverables** — real project files outside `.singleton`
|
|
716
|
+
- **intermediates** — reports, notes, plans, debug artifacts, or output files inside `.singleton`
|
|
717
|
+
|
|
718
|
+
This distinction is used in:
|
|
719
|
+
|
|
720
|
+
- run manifests
|
|
721
|
+
- execution recap
|
|
722
|
+
- `/commit-last`
|
|
723
|
+
|
|
724
|
+
## Run artifacts
|
|
725
|
+
|
|
726
|
+
Each real run creates a versioned directory:
|
|
727
|
+
|
|
728
|
+
```txt
|
|
729
|
+
.singleton/runs/<run-id>/
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Singleton also updates `.singleton/runs/latest` to point at the most recent run.
|
|
733
|
+
|
|
734
|
+
A run manifest looks like this:
|
|
735
|
+
|
|
736
|
+
```json
|
|
737
|
+
{
|
|
738
|
+
"runId": "20260429-162613-codex-security-code-edit-smoke",
|
|
739
|
+
"pipeline": "contact-view-polish-mixed",
|
|
740
|
+
"projectRoot": "/abs/path/to/project",
|
|
741
|
+
"createdAt": "2026-04-28T14:32:11.000Z",
|
|
742
|
+
"status": "done",
|
|
743
|
+
"error": null,
|
|
744
|
+
"deliverables": [
|
|
745
|
+
{ "path": "src/contact-view.js", "absPath": "/abs/path/to/project/src/contact-view.js" }
|
|
746
|
+
],
|
|
747
|
+
"intermediates": [
|
|
748
|
+
{ "path": ".singleton/runs/<run-id>/01-scout/scout.md", "absPath": "/abs/path/to/project/.singleton/runs/<run-id>/01-scout/scout.md" }
|
|
749
|
+
],
|
|
750
|
+
"stats": [
|
|
751
|
+
{
|
|
752
|
+
"agent": "scout",
|
|
753
|
+
"provider": "claude",
|
|
754
|
+
"model": "claude-sonnet-4-6",
|
|
755
|
+
"securityProfile": "read-only",
|
|
756
|
+
"permissionMode": "—",
|
|
757
|
+
"status": "done",
|
|
758
|
+
"seconds": 8.4,
|
|
759
|
+
"turns": 3,
|
|
760
|
+
"cost": 0.012
|
|
761
|
+
}
|
|
762
|
+
]
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
If a run fails after starting, `status` is `failed`, `error.message` is populated, and partial artifacts remain listed.
|
|
767
|
+
|
|
768
|
+
## Multi-provider model
|
|
769
|
+
|
|
770
|
+
Singleton's core model is provider-neutral:
|
|
771
|
+
|
|
772
|
+
- agents are Markdown documents
|
|
773
|
+
- steps are pipeline orchestration units
|
|
774
|
+
- runners adapt those steps to specific CLIs
|
|
775
|
+
|
|
776
|
+
### Claude
|
|
777
|
+
|
|
778
|
+
- executes through the local `claude` CLI
|
|
779
|
+
- supports optional `permission_mode`
|
|
780
|
+
- supports explicit `model`
|
|
781
|
+
|
|
782
|
+
If `permission_mode` is not set, Singleton does not inject one explicitly.
|
|
783
|
+
|
|
784
|
+
### Codex
|
|
785
|
+
|
|
786
|
+
- executes through the local `codex` CLI
|
|
787
|
+
- supports explicit `model`
|
|
788
|
+
- automatically receives project instructions from discovered `AGENTS.md` / `AGENTS.override.md`
|
|
789
|
+
- ignores `permission_mode`
|
|
790
|
+
|
|
791
|
+
`AGENTS.md` is not scanned as a Singleton agent — it is forwarded only as Codex project context.
|
|
792
|
+
|
|
793
|
+
### Copilot
|
|
794
|
+
|
|
795
|
+
- executes through the local `copilot` CLI
|
|
796
|
+
- supports explicit `model`
|
|
797
|
+
- supports optional `runner_agent`, mapped to Copilot's `--agent` option
|
|
798
|
+
- can run without `.github/agents` when no `runner_agent` is set or when Copilot resolves a user-level or organization-level agent
|
|
799
|
+
- repo-level Copilot agent profiles live in `.github/agents/*.agent.md`
|
|
800
|
+
- streams structured output through `--output-format json`
|
|
801
|
+
- maps Singleton security profiles to Copilot `--allow-tool` / `--deny-tool` flags
|
|
802
|
+
- ignores `permission_mode`
|
|
803
|
+
|
|
804
|
+
Example agent config:
|
|
805
|
+
|
|
806
|
+
```md
|
|
807
|
+
- **provider**: copilot
|
|
808
|
+
- **model**: gpt-4.1
|
|
809
|
+
- **runner_agent**: storybook-to-aem
|
|
810
|
+
- **security_profile**: restricted-write
|
|
811
|
+
- **allowed_paths**: src, docs/composants
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
`runner_agent: storybook-to-aem` maps to Copilot's repo profile `.github/agents/storybook-to-aem.agent.md` when present. If the profile is not found locally, Singleton warns instead of failing because Copilot can also resolve user-level or organization-level agents.
|
|
815
|
+
|
|
816
|
+
If `runner_agent` is omitted, Singleton does not pass `--agent`, and Copilot uses its default agent. This is the most portable Copilot setup because it does not require a `.github/agents` directory.
|
|
817
|
+
|
|
818
|
+
In nested demo projects or monorepos, Copilot resolves repo-level agents from the git root it detects. If your pipeline project is nested inside another git repository, either make the nested project a git repository too or place the `.github/agents/*.agent.md` profile at the parent git root.
|
|
819
|
+
|
|
820
|
+
### OpenCode
|
|
821
|
+
|
|
822
|
+
- executes through the local `opencode` CLI
|
|
823
|
+
- runs non-interactively through `opencode run`
|
|
824
|
+
- supports `model` in OpenCode's `provider/model` format
|
|
825
|
+
- supports optional `runner_agent`, mapped to OpenCode's `--agent` option
|
|
826
|
+
- captures JSON events with `--format json` when available
|
|
827
|
+
- maps Singleton security profiles to OpenCode native `permission` config through `OPENCODE_CONFIG_CONTENT`
|
|
828
|
+
- uses Singleton write-time and post-run validation as a second security layer
|
|
829
|
+
- only passes `--dangerously-skip-permissions` for `security_profile: dangerous`
|
|
830
|
+
|
|
831
|
+
Example:
|
|
832
|
+
|
|
833
|
+
```markdown
|
|
834
|
+
- **provider**: opencode
|
|
835
|
+
- **model**: ollama/qwen2.5-coder:14b
|
|
836
|
+
- **runner_agent**: reviewer
|
|
837
|
+
- **security_profile**: read-only
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
If `runner_agent` is omitted, Singleton does not pass `--agent`, and OpenCode uses its default agent.
|
|
841
|
+
|
|
842
|
+
## CLI commands
|
|
843
|
+
|
|
844
|
+
Global flags: every command supports `--help`.
|
|
845
|
+
|
|
846
|
+
Exit codes: `0` on success, non-zero on any failure (preflight, step error, invalid arguments). There is no finer-grained code grid.
|
|
847
|
+
|
|
848
|
+
### `scan`
|
|
849
|
+
|
|
850
|
+
Scan a project for agents and write the agent cache.
|
|
851
|
+
|
|
852
|
+
```bash
|
|
853
|
+
singleton scan /path/to/project
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
What it does:
|
|
857
|
+
|
|
858
|
+
- scans `.singleton/agents`
|
|
859
|
+
- scans `.claude/agents`
|
|
860
|
+
- prints id, description, source, provider, permission mode, inputs, outputs
|
|
861
|
+
- writes `.singleton/agents.json`
|
|
862
|
+
|
|
863
|
+
### `run`
|
|
864
|
+
|
|
865
|
+
Run a pipeline JSON file.
|
|
866
|
+
|
|
867
|
+
```bash
|
|
868
|
+
singleton run --pipeline /path/to/project/.singleton/pipelines/my-pipeline.json
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
Flags:
|
|
872
|
+
|
|
873
|
+
- `--dry-run` — validate without calling any LLM CLI
|
|
874
|
+
- `--verbose` — surface raw provider stdout/stderr
|
|
875
|
+
- `--debug` — pause before each step for inspect/edit/skip/abort controls
|
|
876
|
+
|
|
877
|
+
### `serve`
|
|
878
|
+
|
|
879
|
+
Start the builder API server.
|
|
880
|
+
|
|
881
|
+
```bash
|
|
882
|
+
singleton serve --root /path/to/project
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
### `new`
|
|
886
|
+
|
|
887
|
+
Create a new agent interactively.
|
|
888
|
+
|
|
889
|
+
```bash
|
|
890
|
+
singleton new --root /path/to/project
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
Behavior:
|
|
894
|
+
|
|
895
|
+
- writes to `.singleton/agents`
|
|
896
|
+
- validates id format
|
|
897
|
+
- offers provider/model choices
|
|
898
|
+
- scaffolds `## Config`
|
|
899
|
+
|
|
900
|
+
### `repl`
|
|
901
|
+
|
|
902
|
+
Start the interactive shell.
|
|
903
|
+
|
|
904
|
+
```bash
|
|
905
|
+
singleton
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
## REPL commands
|
|
909
|
+
|
|
910
|
+
```txt
|
|
911
|
+
/run <name> [--dry] [--verbose] [--debug]
|
|
912
|
+
/scan
|
|
913
|
+
/new
|
|
914
|
+
/serve
|
|
915
|
+
/stop
|
|
916
|
+
/commit-last
|
|
917
|
+
/ls
|
|
918
|
+
/help
|
|
919
|
+
/quit
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
Shell features:
|
|
923
|
+
|
|
924
|
+
- autocomplete with `Tab`
|
|
925
|
+
- persistent command history
|
|
926
|
+
- scrollable logs
|
|
927
|
+
- pipeline execution mode
|
|
928
|
+
- debug mode with step checkpoints
|
|
929
|
+
- footer with project status information
|
|
930
|
+
|
|
931
|
+
## `/commit-last`
|
|
932
|
+
|
|
933
|
+
`/commit-last` reads the latest run manifest and:
|
|
934
|
+
|
|
935
|
+
- keeps real project deliverables
|
|
936
|
+
- excludes `.singleton` artifacts
|
|
937
|
+
- excludes paths configured in `.singleton/security.json` `commit.exclude_paths`
|
|
938
|
+
- includes files modified directly during the run
|
|
939
|
+
- previews files before staging
|
|
940
|
+
- asks for confirmation unless disabled by project security config
|
|
941
|
+
- prompts for a commit message
|
|
942
|
+
- runs `git add` on deliverables only
|
|
943
|
+
- creates a Git commit
|
|
944
|
+
|
|
945
|
+
## Builder
|
|
946
|
+
|
|
947
|
+
The web builder is the visual authoring interface served by `singleton serve` + `packages/web` (Vite dev server on port 5173).
|
|
948
|
+
|
|
949
|
+
It lets you:
|
|
950
|
+
|
|
951
|
+
- browse scanned agents and drop them on a canvas as agent nodes
|
|
952
|
+
- add input nodes (`text` or `file`) and bind them to step inputs
|
|
953
|
+
- draw edges from agent outputs to downstream inputs — these become `$PIPE` references
|
|
954
|
+
- bind step outputs to `$FILE` / `$FILES` sinks
|
|
955
|
+
- save the resulting graph as a pipeline JSON in `.singleton/pipelines/`
|
|
956
|
+
|
|
957
|
+
The serialization mapping:
|
|
958
|
+
|
|
959
|
+
- input nodes → `$INPUT:<id>` references
|
|
960
|
+
- graph edges → serialized references
|
|
961
|
+
- topological order → execution order
|
|
962
|
+
|
|
963
|
+
Cycles are rejected at save time.
|
|
964
|
+
|
|
965
|
+
## Full pipeline example
|
|
966
|
+
|
|
967
|
+
Illustrative only — this is not a ready-to-run project. The agents `code-generator` and `code-review` are placeholders to show how the pieces fit together. For executable examples, see `examples/claude-code-review/`, `examples/codex-code-review/`, `examples/mixed-code-review/`, `examples/frontend-audit/`, and `examples/opencode-review/`.
|
|
968
|
+
|
|
969
|
+
A two-step pipeline: a generator writes code from a spec, a reviewer reads that code and emits a report.
|
|
970
|
+
|
|
971
|
+
```json
|
|
972
|
+
{
|
|
973
|
+
"name": "generate-and-review",
|
|
974
|
+
"nodes": [
|
|
975
|
+
{
|
|
976
|
+
"id": "input-spec",
|
|
977
|
+
"type": "input",
|
|
978
|
+
"data": { "label": "spec", "subtype": "file", "value": "" }
|
|
979
|
+
}
|
|
980
|
+
],
|
|
981
|
+
"steps": [
|
|
982
|
+
{
|
|
983
|
+
"agent": "code-generator",
|
|
984
|
+
"agent_file": ".singleton/agents/code-generator.md",
|
|
985
|
+
"inputs": {
|
|
986
|
+
"spec": "$INPUT:input-spec"
|
|
987
|
+
},
|
|
988
|
+
"outputs": {
|
|
989
|
+
"source_code": "$FILE:src/generated/output.js"
|
|
990
|
+
}
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
"agent": "code-review",
|
|
994
|
+
"agent_file": ".singleton/agents/code-review.md",
|
|
995
|
+
"inputs": {
|
|
996
|
+
"source_code": "$PIPE:code-generator.source_code"
|
|
997
|
+
},
|
|
998
|
+
"outputs": {
|
|
999
|
+
"report": "$FILE:.singleton/runs/latest/review.md"
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
]
|
|
1003
|
+
}
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
What this pipeline does at runtime:
|
|
1007
|
+
|
|
1008
|
+
1. prompts the user for the path to the spec file
|
|
1009
|
+
2. runs `code-generator` with the spec content injected as `<file>...</file>`
|
|
1010
|
+
3. writes the generator's output to `src/generated/output.js` (a deliverable)
|
|
1011
|
+
4. runs `code-review` with the generator's output passed via `$PIPE`
|
|
1012
|
+
5. writes the review to `.singleton/runs/latest/review.md` (an intermediate)
|
|
1013
|
+
6. emits a manifest distinguishing the deliverable from the intermediate
|
|
1014
|
+
|
|
1015
|
+
See `examples/mixed-code-review/` for an end-to-end example using both Claude and Codex.
|
|
1016
|
+
|
|
1017
|
+
## Troubleshooting
|
|
1018
|
+
|
|
1019
|
+
**`claude: command not found` (or another provider CLI is missing) during preflight**
|
|
1020
|
+
The corresponding CLI is not in `$PATH`. Install it and ensure it runs standalone before retrying. Singleton never installs or upgrades provider CLIs.
|
|
1021
|
+
|
|
1022
|
+
**Provider call fails immediately with an auth error**
|
|
1023
|
+
The CLI is installed but no active session/credentials. Run the provider's login flow once interactively, then retry.
|
|
1024
|
+
|
|
1025
|
+
**Preflight error: `$PIPE:foo.bar` references unknown step**
|
|
1026
|
+
The upstream step `foo` is missing from the pipeline, or its `outputs` don't declare `bar`. Check both the step list order and the agent's `outputs:` line in `## Config`.
|
|
1027
|
+
|
|
1028
|
+
**Preflight error: unsafe sink path**
|
|
1029
|
+
A `$FILE` or `$FILES` target resolves outside the project root. Singleton refuses to write there. Make the path relative to the project root.
|
|
1030
|
+
|
|
1031
|
+
**`permission_mode` rejected for a Claude step**
|
|
1032
|
+
Only specific values are accepted by the Claude runner. Check the agent's `## Config` and the step override.
|
|
1033
|
+
|
|
1034
|
+
**Step succeeds but no file appears on disk**
|
|
1035
|
+
The step output is kept in memory unless a sink (`$FILE` or `$FILES`) is wired in `outputs`. Without a sink, the value is only available to downstream `$PIPE` references.
|
|
1036
|
+
|
|
1037
|
+
**`$FILES` step fails with a parse error**
|
|
1038
|
+
The agent's output isn't valid JSON of the expected shape. Inspect the raw output with `--verbose` and adjust the prompt to constrain the format.
|