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.
@@ -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.