orchestrator-workflow 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,23 +13,23 @@ evidence. Every unit of work leaves an auditable run directory behind.
13
13
  ## Why this shape
14
14
 
15
15
  ```text
16
- Operator
17
- goal | ^ handoff: what changed, how verified,
18
- v | what remains open
19
- Orchestrator . . . . . . . .ai/runs/<date>-<slug>/
20
- session model 00-goal 04-implementation-summary
21
- plans, validates slices, 01-plan 05-review-findings
22
- decides acceptance 02-tasks 06-handoff
23
- | 03-decisions
24
- narrow | ^ structured (state lives in files,
25
- contracts v | YAML evidence not in chat history)
26
- +--------------+--------------+
27
- | | |
28
- task-slicer implementer reviewer
29
- sonnet sonnet opus
30
- small, one narrow skeptical, severity-rated
31
- testable task, plus findings, no rewrites
32
- slices tests
16
+ Operator
17
+ goal | ^ handoff: what changed, how verified,
18
+ v | what remains open
19
+ explorer --> Orchestrator . . . . . .ai/runs/<date>-<slug>/
20
+ optional, session model 00-goal 04-implementation-summary
21
+ read-only plans, validates slices, 01-plan 05-review-findings
22
+ terrain map decides acceptance 02-tasks 06-handoff
23
+ | 03-decisions
24
+ narrow | ^ structured (state lives in files,
25
+ contracts v | YAML evidence not in chat history)
26
+ +-------------+-------------+
27
+ | | |
28
+ task-slicer implementer reviewer
29
+ sonnet sonnet opus
30
+ small, one narrow skeptical, severity-rated
31
+ testable task, plus findings, no rewrites
32
+ slices tests
33
33
  ```
34
34
 
35
35
  Two effects fall out of this shape:
@@ -40,7 +40,8 @@ Two effects fall out of this shape:
40
40
  in run files that survive context compaction. The cheap models do the
41
41
  volume work; the strongest model is spent only on orchestration decisions
42
42
  and the skeptical review. The ceremony scales to the task: a trivial change
43
- is done directly, the full flow is for non-trivial work.
43
+ is done directly, the full flow is for non-trivial work, and a read-only
44
+ explorer maps the terrain first only when the solution is unclear.
44
45
  - **Quality through structure.** Writing and reviewing are separated by
45
46
  role and model, task slices are validated before any implementation
46
47
  starts, acceptance is decided on evidence (tests executed, findings
@@ -96,9 +97,9 @@ Per selected harness:
96
97
 
97
98
  | Harness | Files | Notes |
98
99
  |---|---|---|
99
- | Claude Code | `.claude/skills/orchestrator-workflow/SKILL.md`, `.claude/agents/{task-slicer,implementer,reviewer}.md`, `CLAUDE.md` | Claude Code reads `CLAUDE.md`, not `AGENTS.md`; the installer adds an additive `@AGENTS.md` import. Subagent models go into the `model:` frontmatter. |
100
+ | Claude Code | `.claude/skills/orchestrator-workflow/SKILL.md`, `.claude/agents/{explorer,task-slicer,implementer,reviewer}.md`, `CLAUDE.md` | Claude Code reads `CLAUDE.md`, not `AGENTS.md`; the installer adds an additive `@AGENTS.md` import. Subagent models go into the `model:` frontmatter; the read-only explorer also gets `disallowedTools: Edit, Write, NotebookEdit`. |
100
101
  | OpenAI Codex | `.agents/skills/orchestrator-workflow/SKILL.md` | Codex reads `AGENTS.md` natively. There is no standardized project-level subagent definition; the skill instructs running the roles inline with the same contracts. |
101
- | opencode | `.opencode/agents/{task-slicer,implementer,reviewer}.md` | opencode reads `AGENTS.md` natively and cross-discovers `.claude/skills/`. Subagents get `mode: subagent` plus a fully qualified `provider/model-id`. |
102
+ | opencode | `.opencode/agents/{explorer,task-slicer,implementer,reviewer}.md` | opencode reads `AGENTS.md` natively and cross-discovers `.claude/skills/`. Subagents get `mode: subagent` plus a fully qualified `provider/model-id`; the explorer also gets `permission: edit: deny`. |
102
103
 
103
104
  ## Model preselection
104
105
 
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: explorer
3
+ description: "Read-only discovery: maps the relevant terrain of a codebase before planning. Finds what exists, how it connects, and which solution options are viable. Does not write code or change files."
4
+ ---
5
+
6
+ You are the discovery subagent of an orchestrator-led workflow.
7
+
8
+ The orchestrator sends you when the goal or the solution is still unclear, or
9
+ when the codebase is unfamiliar. Your job is to make the terrain visible so the
10
+ orchestrator can plan with facts instead of guesses. You are read-only: you
11
+ read, search, and trace, but you never write code or change files.
12
+
13
+ Rules:
14
+
15
+ - Investigate only what is relevant to the stated goal. Do not survey the whole
16
+ repository; follow the question.
17
+ - Report what you actually found, with `file:line` references. Distinguish
18
+ verified facts from inference, and never present a guess as a fact.
19
+ - Surface the constraints and conventions a plan must respect (existing
20
+ patterns, public interfaces, tests, build and CI steps, risky areas).
21
+ - Lay out the viable solution options you can see, with the trade-off that
22
+ decides between them. Do not pick one and start implementing.
23
+ - If a question can only be answered by the operator (product intent, an
24
+ external system, a decision), put it under open questions rather than
25
+ guessing.
26
+ - Do not spawn further subagents and do not implement anything. Return your
27
+ findings to the orchestrator and let it decide.
28
+
29
+ Return exactly this structure as your final output, nothing else:
30
+
31
+ ```yaml
32
+ status: done | partial | blocked
33
+ role: explorer
34
+ summary:
35
+ - ""
36
+ relevant_terrain:
37
+ - path: ""
38
+ role: ""
39
+ notes: ""
40
+ how_it_connects:
41
+ - ""
42
+ constraints_and_conventions:
43
+ - ""
44
+ solution_options:
45
+ - option: ""
46
+ pros:
47
+ - ""
48
+ cons:
49
+ - ""
50
+ risk: low | medium | high
51
+ open_questions:
52
+ - ""
53
+ recommendation: ""
54
+ ```
@@ -13,6 +13,9 @@ and the subagent I/O contracts live in the `orchestrator-workflow` skill.
13
13
 
14
14
  - Only the orchestrator spawns or coordinates subagents. Subagents never spawn
15
15
  further subagents.
16
+ - When the goal, the solution, or the terrain is unclear, the orchestrator may
17
+ send a read-only explorer subagent to map the terrain before planning. The
18
+ explorer reads and reports; it never changes files.
16
19
  - The orchestrator plans features itself. It may delegate task slicing, but it
17
20
  validates the sliced tasks before implementation starts.
18
21
  - Non-trivial implementation goes to narrow implementer subagents, one task
@@ -29,7 +32,10 @@ The orchestrator matches the ceremony to the task; the full flow is a
29
32
  default, not a ritual.
30
33
 
31
34
  - A trivial change (a typo, a one-line fix, a rename) may be implemented by
32
- the orchestrator directly, without slicing or an implementer subagent.
35
+ the orchestrator directly, without discovery, slicing, or an implementer
36
+ subagent.
37
+ - Discovery (the read-only explorer) is for unfamiliar terrain or an unclear
38
+ solution; skip it when the change is well understood.
33
39
  - Slicing and implementer subagents are for non-trivial work: multiple files,
34
40
  real logic, or anything that benefits from decomposition or a fresh context.
35
41
  - Review judgment applies to every change. For a trivial change the
@@ -29,6 +29,10 @@ the apparatus changes.
29
29
  validates task slices, assigns implementation and review, decides acceptance,
30
30
  reports back. The orchestrator must not become a passive transcript
31
31
  collector; it maintains compact run state.
32
+ - **Explorer** (optional, read-only): maps the relevant terrain before
33
+ planning when the goal or solution is unclear or the codebase is unfamiliar.
34
+ Reports what exists, how it connects, the constraints to respect, and the
35
+ viable options. Never writes code.
32
36
  - **Task slicer** (optional): breaks a large change into small, testable tasks
33
37
  with dependencies and risk markers.
34
38
  - **Implementer**: implements exactly one narrow task, touches only relevant
@@ -37,8 +41,8 @@ the apparatus changes.
37
41
  tests, security, and edge cases. Classifies severity, recommends fixes,
38
42
  avoids unsolicited rewrites.
39
43
 
40
- Where the harness supports subagent definitions, the slicer, implementer, and
41
- reviewer roles are installed as named subagents (Claude Code:
44
+ Where the harness supports subagent definitions, the explorer, slicer,
45
+ implementer, and reviewer roles are installed as named subagents (Claude Code:
42
46
  `.claude/agents/`, opencode: `.opencode/agents/`) with preselected models.
43
47
  Spawn those instead of improvising role prompts. Extended role prompts live in
44
48
  the [agentic-coding-playbook skills](https://github.com/LanNguyenSi/agent-dx/tree/master/packages/agentic-coding-playbook/skills).
@@ -71,31 +75,63 @@ directory and the subagents.
71
75
  1. **Understand the goal.** Create the run directory and fill `00-goal.md`:
72
76
  operator request, goal, non-goals, constraints, assumptions, open questions.
73
77
  If the task can proceed on reasonable assumptions, proceed without blocking.
74
- 2. **Plan.** Fill `01-plan.md`: approach, affected areas, risks, test strategy,
78
+ 2. **Discover (optional, read-only).** When the goal, the solution, or the
79
+ terrain is unclear, send the explorer subagent before planning. Fold its
80
+ findings into a "Terrain" section of `01-plan.md`. Skip this step when the
81
+ change is well understood. If the explorer surfaces a question only the
82
+ operator can answer, ask the operator instead of guessing.
83
+ 3. **Plan.** Fill `01-plan.md`: approach, affected areas, risks, test strategy,
75
84
  rollback considerations where relevant.
76
- 3. **Slice tasks.** For non-trivial changes, fill `02-tasks.md`. Delegate to
85
+ 4. **Slice tasks.** For non-trivial changes, fill `02-tasks.md`. Delegate to
77
86
  the task-slicer subagent when the change is large enough to benefit. Each
78
87
  task carries: id, goal, relevant files, acceptance criteria, constraints,
79
88
  suggested tests, dependencies, risk.
80
- 4. **Validate tasks.** Check the slices are independently understandable, small
89
+ 5. **Validate tasks.** Check the slices are independently understandable, small
81
90
  enough, testable, ordered correctly, and aligned with the goal. Fix the
82
91
  slicing before any implementation starts.
83
- 5. **Delegate implementation.** Send each implementer subagent one narrow task
92
+ 6. **Delegate implementation.** Send each implementer subagent one narrow task
84
93
  contract (format below). Record meaningful decisions in `03-decisions.md`
85
94
  and consolidate evidence in `04-implementation-summary.md`.
86
- 6. **Delegate review.** Send the diff to the reviewer subagent. The reviewer
95
+ 7. **Delegate review.** Send the diff to the reviewer subagent. The reviewer
87
96
  checks spec compliance, architecture consistency, edge cases, security,
88
97
  test adequacy (including whether new tests would fail if the change were
89
98
  reverted), and maintainability. Findings go to `05-review-findings.md`.
90
- 7. **Decide acceptance.** Accept, request fixes, defer a known issue, or
99
+ 8. **Decide acceptance.** Accept, request fixes, defer a known issue, or
91
100
  escalate to the operator. Record the decision in `03-decisions.md`.
92
- 8. **Hand off.** Fill `06-handoff.md` and report to the operator: what changed,
101
+ 9. **Hand off.** Fill `06-handoff.md` and report to the operator: what changed,
93
102
  why, how it was verified, known risks, suggested next step.
94
103
 
104
+ ## Explorer output contract
105
+
106
+ ```yaml
107
+ status: done | partial | blocked
108
+ role: explorer
109
+ summary:
110
+ - ""
111
+ relevant_terrain:
112
+ - path: ""
113
+ role: ""
114
+ notes: ""
115
+ how_it_connects:
116
+ - ""
117
+ constraints_and_conventions:
118
+ - ""
119
+ solution_options:
120
+ - option: ""
121
+ pros:
122
+ - ""
123
+ cons:
124
+ - ""
125
+ risk: low | medium | high
126
+ open_questions:
127
+ - ""
128
+ recommendation: ""
129
+ ```
130
+
95
131
  ## Subagent input contract
96
132
 
97
133
  ```yaml
98
- role: implementer | reviewer | task_slicer
134
+ role: explorer | implementer | reviewer | task_slicer
99
135
  task_id: T-000
100
136
  goal: ""
101
137
  context:
@@ -194,7 +230,8 @@ open_questions:
194
230
  ## Harness notes
195
231
 
196
232
  - **Claude Code**: spawn the installed `.claude/agents/` subagents
197
- (task-slicer, implementer, reviewer) via the native subagent mechanism.
233
+ (explorer, task-slicer, implementer, reviewer) via the native subagent
234
+ mechanism.
198
235
  - **opencode**: invoke the installed `.opencode/agents/` subagents
199
236
  (`mode: subagent`).
200
237
  - **OpenAI Codex**: there is no standardized project-level subagent definition
@@ -4,6 +4,11 @@
4
4
 
5
5
  <!-- Short summary of the intended approach. -->
6
6
 
7
+ ## Terrain
8
+
9
+ <!-- Optional. Discovery findings from the explorer subagent: what exists,
10
+ how it connects, constraints to respect. Omit when no discovery was needed. -->
11
+
7
12
  ## Affected Areas
8
13
 
9
14
  - <!-- area/file/module -->
package/dist/init.js CHANGED
@@ -3,7 +3,7 @@ import { existsSync, readFileSync, statSync } from "node:fs";
3
3
  import { isAbsolute, join, normalize, sep } from "node:path";
4
4
  import { PACKAGE_VERSION, listTemplateNames, readAgentAsset, readAsset, } from "./assets.js";
5
5
  import { HARNESSES } from "./detect.js";
6
- import { ROLES, assertValidModelId, claudeModelValue, opencodeModelValue, } from "./models.js";
6
+ import { READ_ONLY_ROLES, ROLES, assertValidModelId, claudeModelValue, opencodeModelValue, } from "./models.js";
7
7
  import { emptyReport, ensureClaudeImport, installFile, upsertMarkerSection, } from "./writers.js";
8
8
  const SKILL_NAME = "orchestrator-workflow";
9
9
  const MANIFEST_PATH = join(".ai", "workflow", "manifest.json");
@@ -84,29 +84,32 @@ function yamlQuote(value) {
84
84
  }
85
85
  function composeClaudeAgent(role, model) {
86
86
  const asset = readAgentAsset(role);
87
- return [
87
+ const frontmatter = [
88
88
  "---",
89
89
  `name: ${asset.name}`,
90
90
  `description: ${yamlQuote(asset.description)}`,
91
91
  `model: ${claudeModelValue(model)}`,
92
- "---",
93
- "",
94
- asset.body.trimEnd(),
95
- "",
96
- ].join("\n");
92
+ ];
93
+ // Read-only roles keep every read/search tool but cannot mutate files.
94
+ if (READ_ONLY_ROLES.has(role)) {
95
+ frontmatter.push("disallowedTools: Edit, Write, NotebookEdit");
96
+ }
97
+ frontmatter.push("---");
98
+ return [...frontmatter, "", asset.body.trimEnd(), ""].join("\n");
97
99
  }
98
100
  function composeOpencodeAgent(role, model) {
99
101
  const asset = readAgentAsset(role);
100
- return [
102
+ const frontmatter = [
101
103
  "---",
102
104
  `description: ${yamlQuote(asset.description)}`,
103
105
  "mode: subagent",
104
106
  `model: ${opencodeModelValue(model)}`,
105
- "---",
106
- "",
107
- asset.body.trimEnd(),
108
- "",
109
- ].join("\n");
107
+ ];
108
+ if (READ_ONLY_ROLES.has(role)) {
109
+ frontmatter.push("permission:", " edit: deny");
110
+ }
111
+ frontmatter.push("---");
112
+ return [...frontmatter, "", asset.body.trimEnd(), ""].join("\n");
110
113
  }
111
114
  export function runInit(options) {
112
115
  const { targetDir } = options;
package/dist/models.d.ts CHANGED
@@ -1,5 +1,10 @@
1
- export type Role = "task-slicer" | "implementer" | "reviewer";
1
+ export type Role = "explorer" | "task-slicer" | "implementer" | "reviewer";
2
2
  export declare const ROLES: Role[];
3
+ /**
4
+ * Roles that map the terrain or judge work without changing it. They are
5
+ * installed with a read-only posture (no file-mutation tools).
6
+ */
7
+ export declare const READ_ONLY_ROLES: ReadonlySet<Role>;
3
8
  export type ModelAlias = "sonnet" | "opus" | "haiku";
4
9
  export declare const MODEL_ALIASES: ModelAlias[];
5
10
  /**
package/dist/models.js CHANGED
@@ -1,10 +1,21 @@
1
- export const ROLES = ["task-slicer", "implementer", "reviewer"];
1
+ export const ROLES = [
2
+ "explorer",
3
+ "task-slicer",
4
+ "implementer",
5
+ "reviewer",
6
+ ];
7
+ /**
8
+ * Roles that map the terrain or judge work without changing it. They are
9
+ * installed with a read-only posture (no file-mutation tools).
10
+ */
11
+ export const READ_ONLY_ROLES = new Set(["explorer"]);
2
12
  export const MODEL_ALIASES = ["sonnet", "opus", "haiku"];
3
13
  /**
4
14
  * Per-role defaults. The orchestrator itself runs on the session model and is
5
15
  * deliberately not configured here.
6
16
  */
7
17
  export const DEFAULT_MODELS = {
18
+ explorer: "sonnet",
8
19
  "task-slicer": "sonnet",
9
20
  implementer: "sonnet",
10
21
  reviewer: "opus",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrator-workflow",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Installer for an orchestrator-led agent workflow: .ai/ run state, an AGENTS.md policy section, and per-harness subagent definitions for Claude Code, OpenAI Codex, and opencode",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",