Skip to content

feat(workflows): inline sub-agent definitions on DAG nodes#1276

Merged
Wirasm merged 2 commits intodevfrom
feat/inline-agents
Apr 19, 2026
Merged

feat(workflows): inline sub-agent definitions on DAG nodes#1276
Wirasm merged 2 commits intodevfrom
feat/inline-agents

Conversation

@Wirasm
Copy link
Copy Markdown
Collaborator

@Wirasm Wirasm commented Apr 17, 2026

Summary

  • Problem: Workflow authors who want per-node sub-agents invokable via Task must author loose .claude/agents/*.md files on disk. Definitions live outside the workflow YAML — hurts self-containment, portability, and discoverability.
  • Why it matters: Map-reduce workflow patterns (Haiku fan-out + Sonnet reduce) want to define per-workflow helper agents. Every such pattern shipped today bloats .claude/agents/. Inline agents let the entire workflow travel in one YAML file.
  • What changed: New Claude-only DAG-node field agents: — map of {agentId: {description, prompt, model?, tools?, disallowedTools?, skills?, maxTurns?}} passed straight through to Claude Agent SDK's options.agents. Schema validation, provider-capability gate, validator warnings for non-Claude providers.
  • What did not change (scope boundary): workflow-level agents: (deferred to v2), per-agent mcpServers, criticalSystemReminder_EXPERIMENTAL, and web UI editor — YAML-only authoring in v1; the existing YAML code view round-trips the field without data loss.

UX Journey

Before

```
author workflow file tree sub-agent loading
────────────── ───────── ─────────────────
write workflow ──────▶ .archon/workflows/my.yaml
want Haiku fan-out:
create agent file ──▶ .claude/agents/ loose file on disk,
brief-gen.md ships separately
reference in prompt: from the workflow
Task(subagent_type='brief-gen', ...)
```

After

```
author workflow file tree sub-agent loading
────────────── ───────── ─────────────────
write workflow ──────▶ .archon/workflows/my.yaml [+] inline in same
agents: YAML as workflow
brief-gen:
model: haiku
prompt: ...
reference in prompt:
Task(subagent_type='brief-gen', ...)
```

Architecture Diagram

Before

```
YAML packages/workflows packages/providers
──── ────────────────── ──────────────────
node.skills ──▶ dagNodeSchema ──────────▶ NodeConfig.skills
├─ ClaudeProvider:
│ options.agents[dag-node-skills]
├─ Codex: ignored + cap warning
└─ Pi: ignored + cap warning
```

After

```
YAML packages/workflows packages/providers
──── ────────────────── ──────────────────
node.skills ────────▶ dagNodeSchema ──────────────▶ NodeConfig.skills
│ │
│ [] │
▼ ▼
node.agents [+] ════▶ agentDefinitionSchema [+] ═══▶ NodeConfig.agents [+]
(kebab-case keys) │
├─ ClaudeProvider [
]:
│ options.agents
│ MERGE: skills wrapper
│ + inline agents, user
│ wins on ID collision
├─ Codex: ignored + cap warn [+]
└─ Pi: ignored + cap warn [+]

Validator []: new capability-mismatch warning mirroring the skills pattern.
dag-executor [
]: new capCheck entry surfaces warning to user via platform.
```

Connection inventory:

From To Status Notes
`dagNodeBaseSchema` `agents` field new Zod record, kebab-case keys, AgentDefinition value schema
Schema transform `NodeConfig.agents` new Structural passthrough; `@archon/providers/types` stays SDK-dep-free
`ClaudeProvider.sendQuery` `options.agents` modified Merges AFTER skills block — user-defined agents win on ID collision
`ProviderCapabilities` `agents: boolean` new Required field; TS forces all providers to declare
`validator.ts` capability warning new Non-Claude providers warn and ignore field
`dag-executor.ts` capCheck `agents` entry new Platform notification when capability mismatched

Label Snapshot

  • Risk: `risk: low`
  • Size: `size: M`
  • Scope: `workflows`, `providers`
  • Module: `workflows:schemas/dag-node`, `providers:claude/provider`

Change Metadata

  • Change type: `feature`
  • Primary scope: `workflows`

Linked Issue

  • Closes #
  • Related #
  • Depends on #
  • Supersedes #

(No existing issue — this is an ad-hoc enhancement uncovered while building a workflow that wanted inline Haiku sub-agents.)

Validation Evidence (required)

```bash
bun run validate # check:bundled, type-check, lint, format:check, test — all pass
```

Manual end-to-end smoke: authored a workflow (`repo-triage`) with an inline Haiku `brief-gen` sub-agent, ran it live against the repo. Observed:

  • Log: `claude.inline_agents_registered agentIds=["brief-gen"]` from `packages/providers/src/claude/provider.ts`
  • Sub-agent actually invokable via the SDK's `Task` tool from the main prompt node
  • Resulting GitHub comments successfully posted by the sub-agent fan-out

New tests added:

  • `packages/workflows/src/dag-executor.test.ts` — schema validation (valid maps, missing `description`/`prompt`, empty map rejected, kebab-case enforcement, field stripped on bash/script/loop nodes); dag-executor passthrough of `nodeConfig.agents`; Codex capability warning
  • `packages/providers/src/claude/provider.test.ts` — translation to `options.agents`; merge with `skills:` wrapper; user wins on collision; `options.agent` (singular) untouched when only inline agents present

Security Impact (required)

  • New permissions/capabilities? No — `agents:` is strictly a subset of what `skills:` already exposes (both write to `options.agents`)
  • New external network calls? No
  • Secrets/tokens handling changed? No
  • File system access scope changed? No

Compatibility / Migration

  • Backward compatible? Yes — strictly additive schema field. Workflows without `agents:` are unaffected; behavior is byte-for-byte identical.
  • Config/env changes? No
  • Database migration needed? No

Human Verification (required)

Verified scenarios:

  • Minimal workflow with one inline Haiku agent loads, runs, and the sub-agent is Task-invocable end-to-end (authored `.archon/workflows/repo-triage.yaml` and ran against real GitHub)
  • Codex node with `agents:` field emits the capability warning and ignores the field
  • Inline `agents:` merged with existing `skills:` on the same node — user-defined agents win on ID collision with the internal `dag-node-skills` wrapper

Edge cases checked:

  • Empty `agents: {}` map → schema rejection
  • Agent definition missing `description` or `prompt` → schema error
  • `agents:` on bash / script / loop / approval / cancel nodes → warning emitted, field stripped (matches `skills:` behavior)
  • Agent ID not kebab-case (`BriefGen`, `brief_gen`, leading dash) → schema error with helpful message
  • Reserved ID `dag-node-skills` collision — allowed by design; user definition wins, logged

What was not verified:

  • Web UI editor for inline agents (deliberately out of scope for v1 — YAML-only; `NodeInspector` ignores the field; YAML code view round-trips it via the regenerated `api.generated.d.ts`)
  • Pi provider with `agents:` at runtime (capability is `false`; validator warns but runtime path is not exercised)

Side Effects / Blast Radius (required)

  • Affected subsystems: every DAG node that sets `skills:` already flows through the same `options.agents` code path in `ClaudeProvider.sendQuery`. The new merge logic is the only behavioral change for existing nodes — if a node has `skills:` but no `agents:`, behavior is byte-identical (skills wrapper remains sole occupant of `options.agents`).
  • Potential unintended effects: none on existing workflows. A workflow that later adds `agents:` alongside `skills:` gets the merge; collision behavior is documented.
  • Guardrails/monitoring: new structured log event `claude.inline_agents_registered` with `agentIds` list — easy to grep for real-world usage.

Rollback Plan (required)

  • Fast rollback path: `git revert` this PR. No migrations, no data state, no config toggles.
  • Feature flags: none — gated via `ProviderCapabilities.agents` per provider (Claude only).
  • Observable failure symptoms: schema validation errors on workflow load (`agents` field malformed); capability warnings in `dag-executor` logs (`dag.unsupported_capabilities`); runtime errors from the Claude Agent SDK only if its `options.agents` contract changes — same exposure as the existing `skills:` translation at `packages/providers/src/claude/provider.ts:445`.

Risks and Mitigations

  • Risk: inline agents can define the internal `dag-node-skills` wrapper ID and silently override Archon's skills translation.
    • Mitigation: documented as intentional ("user wins on collision" per design review); provider logs `claude.inline_agents_registered` with the full `agentIds` list so the collision is observable; covered by test `merges inline agents with skills wrapper; user wins on ID collision`.
  • Risk: Claude Agent SDK's `options.agents` shape changes upstream and both the existing `skills:` wrapper and new inline `agents:` break together.
    • Mitigation: single dep point at `packages/providers/src/claude/provider.ts:~440` — both code paths flow through the same translation block and would be fixed in one place. Test coverage catches shape drift.

Summary by CodeRabbit

  • New Features

    • Added inline sub-agent definitions via agents: field in workflow configurations for Claude, enabling parallel sub-agent invocation via the Task tool. User-supplied agents take precedence over internal wrappers on ID collisions.
  • Documentation

    • Updated workflow authoring guide with inline sub-agent configuration schema and constraints (kebab-case IDs, required fields, provider limitations).
    • Added provider capability matrix clarifying Claude-only agent support.
    • Linked inline sub-agents documentation to skills guide.
  • Provider Support

    • Claude: Enabled inline agents support.
    • Codex and Pi: Marked agents unsupported with user-facing warnings.

Add `agents:` node field letting workflow YAML define Claude Agent SDK
sub-agents inline, keyed by kebab-case ID. The main agent can spawn
them via the Task tool — useful for map-reduce patterns where a cheap
model briefs items and a stronger model reduces.

Authors no longer need standalone `.claude/agents/*.md` files for
workflow-scoped helpers; the definitions live with the workflow.

Claude only. Codex and community providers without the capability
emit a capability warning and ignore the field. Merges with the
internal `dag-node-skills` wrapper when `skills:` is also set —
user-defined agents win on ID collision.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

Adds a new per-node agents field for inline Claude sub-agent definitions in DAG workflows, with schema, type, provider-capability, executor propagation, validation, and tests; unsupported providers warn and ignore the field.

Changes

Cohort / File(s) Summary
Docs
CLAUDE.md, packages/docs-web/src/content/docs/guides/authoring-workflows.md, packages/docs-web/src/content/docs/guides/skills.md, CHANGELOG.md, packages/docs-web/src/content/docs/getting-started/ai-assistants.md
Documented new agents node option (Inline sub-agents), merging behavior with skills:, kebab-case ID constraint, provider support notes, and checklist update.
Types & Public API
packages/providers/src/types.ts, packages/web/src/lib/api.generated.d.ts
Added NodeConfig.agents?: Record<string, AgentDefinition> and ProviderCapabilities.agents: boolean; updated generated DagNode typing to include agents.
Schemas & Validation
packages/workflows/src/schemas/dag-node.ts, packages/workflows/src/schemas/index.ts
Added agentDefinitionSchema and AgentDefinition type; dagNodeBaseSchema now accepts validated kebab-case agents map; re-exported schema/type in index.
Provider Capabilities
packages/providers/src/claude/capabilities.ts, packages/providers/src/codex/capabilities.ts, packages/providers/src/community/pi/capabilities.ts, packages/providers/src/registry.test.ts
Declared agents capability flag per provider (claude: true, others: false) and updated mock/test capability objects.
Claude Provider Logic
packages/providers/src/claude/provider.ts, packages/providers/src/claude/provider.test.ts
applyNodeConfig overlays nodeConfig.agents onto options.agents after skills-wrapper; user agents override on ID collision with a logged warning; tests cover propagation, merging, and warnings.
Executor & Runtime Validation
packages/workflows/src/dag-executor.ts, packages/workflows/src/validator.ts, packages/workflows/src/dag-executor.test.ts, packages/workflows/src/validator.test.ts
resolveNodeProviderAndModel and executor now include agents in capability checks and NodeConfig; validator emits warnings when provider lacks agents; tests added for propagation, parsing, validation, and unsupported-provider warnings.
Other
packages/providers/src/types.ts (detailed additions), packages/workflows/src/schemas/dag-node.ts (exports)
Type/schema surface expanded to export AgentDefinition; small related updates across tests and index exports.

Sequence Diagram

sequenceDiagram
    participant Parser as Workflow Parser
    participant Validator as Validator
    participant Executor as DAG Executor
    participant Provider as Claude Provider
    participant SDK as Claude SDK

    Parser->>Validator: parse node (includes agents?)
    Validator->>Validator: validate agents schema & provider caps
    alt provider lacks agents
        Validator->>Parser: emit warning (field: 'agents', hint: 'claude')
    end
    Parser->>Executor: pass normalized node (agents)
    Executor->>Provider: sendQuery(nodeConfig { agents, skills, ... })
    Provider->>Provider: merge nodeConfig.agents with skills-wrapper agents
    Provider->>Provider: log warning if 'dag-node-skills' overridden
    Provider->>SDK: call with options.agents (inline sub-agents)
    SDK->>SDK: register inline sub-agents
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰
I nibbled at the DAG today,
Kebab-keyed agents hopped to play,
Claude sprouts friends inside each node,
They merge and dance along the road,
A tiny hop — workflows gleam away!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main feature: inline sub-agent definitions on DAG nodes in workflow YAML.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all required template sections: problem, why it matters, what changed, scope boundaries, UX journey, architecture, validation evidence, security impact, compatibility, human verification, and rollback plan.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/inline-agents

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/web/src/lib/api.generated.d.ts (1)

2519-2532: ⚠️ Potential issue | 🟡 Minor

Regenerate OpenAPI schema to include the new agents capability flag.

The agents: boolean field is already in the source schema (packages/providers/src/types.ts:179) with documentation, and the workflow validator actively checks caps.agents (line 409 of packages/workflows/src/validator.ts). However, the auto-generated OpenAPI schema in packages/web/src/lib/api.generated.d.ts (lines 2519–2532) is missing this field entirely, meaning web clients consuming /api/providers won't know which providers support inline agents.

Regenerate the OpenAPI schema from the backend source definition to sync the generated type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/web/src/lib/api.generated.d.ts` around lines 2519 - 2532, The
generated API types are missing the new ProviderCapabilities.agents boolean
flag; regenerate the OpenAPI/type generation so
packages/web/src/lib/api.generated.d.ts includes "agents: boolean" to match the
source definition (packages/providers/src/types.ts) and the runtime validator
(packages/workflows/src/validator.ts which checks caps.agents). Re-run the
OpenAPI/type generation step (or the script that produces api.generated.d.ts)
from the backend schema, verify ProviderCapabilities now contains agents, and
commit the updated generated file.
🧹 Nitpick comments (4)
packages/providers/src/types.ts (1)

126-142: Structural shape is justified by the contract-module no-SDK rule.

Normally the guideline would be to import AgentDefinition from @anthropic-ai/claude-agent-sdk, but this file is the SDK-free contract layer (see the HARD RULE at the top), and the JSDoc explicitly notes the shape mirrors the SDK's AgentDefinition. One thing to watch: if Claude SDK's AgentDefinition drifts (e.g. adds a required field or renames one), this structural type won't catch it — consider a type-compat assertion in packages/providers/src/claude/provider.ts where SDK types are available, e.g.:

// in claude/provider.ts, near where nodeConfig.agents is consumed
const _compat: AgentDefinition = {} as NonNullable<NodeConfig['agents']>[string];

to fail the build if the shapes diverge.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/providers/src/types.ts` around lines 126 - 142, The agents
structural type in packages/providers/src/types.ts may drift from the SDK's
AgentDefinition; to detect divergences at build time, add a type-compat
assertion in packages/providers/src/claude/provider.ts where nodeConfig.agents
is consumed: create a compile-time assignment forcing an alias like
AgentDefinition = NonNullable<NodeConfig['agents']>[string] (using the SDK's
AgentDefinition type from `@anthropic-ai/claude-agent-sdk`) so the TypeScript
compiler fails the build if the shapes diverge; reference AgentDefinition,
NodeConfig, and the agents property when adding this assertion.
packages/workflows/src/dag-executor.ts (1)

288-288: Minor: empty-map check differs slightly from validator.

node.agents !== undefined && Object.keys(node.agents).length > 0 means an agents: {} node will not emit the runtime capability warning, whereas the validator (see validator.ts L409) warns on any truthy object. In practice agents: {} is a no-op so this difference is benign — flagging only for consistency. If you want them aligned, drop the Object.keys(...).length > 0 predicate here (mirroring the other cap checks like hooks/mcp which only test for !== undefined).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/workflows/src/dag-executor.ts` at line 288, The runtime capability
check for agents in the array entry inside dag-executor.ts currently uses
node.agents !== undefined && Object.keys(node.agents).length > 0 which differs
from the validator behavior; change this predicate to mirror the other
capability checks by removing the Object.keys(...).length > 0 part so it simply
tests node.agents !== undefined (update the array entry that contains ['agents',
'agents', ...] accordingly) to keep consistency with validator.ts and the
hooks/mcp checks.
packages/docs-web/src/content/docs/guides/authoring-workflows.md (1)

1160-1160: Numbering nit: 12b. breaks the ordered list.

Consider renumbering the trailing items (13–19 become 14–20) so the list stays monotonic, or fold agents into item 12 alongside skills since they are closely related.

Proposed fix
-12. **`skills:`** — preload skills into Claude nodes for domain expertise
-12b. **`agents:`** — inline Claude sub-agent definitions invokable via the `Task` tool
-13. **`effort` / `thinking`** — control reasoning depth and thinking mode per node or workflow (Claude only)
+12. **`skills:`** — preload skills into Claude nodes for domain expertise
+13. **`agents:`** — inline Claude sub-agent definitions invokable via the `Task` tool (Claude only)
+14. **`effort` / `thinking`** — control reasoning depth and thinking mode per node or workflow (Claude only)

(and bump the remaining items 14–19 → 15–20)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/docs-web/src/content/docs/guides/authoring-workflows.md` at line
1160, Replace the non-monotonic list item labeled "12b." with a properly
numbered entry: either merge the "agents" description into item "12" next to
"skills" or renumber it as "13." and increment all following list items (change
13–19 to 14–20); locate the paragraph containing the "12b. **`agents:`**" token
in the authoring-workflows.md content and apply the chosen renumbering so the
ordered list remains sequential.
packages/providers/src/claude/provider.ts (1)

453-464: Duplicate claude.inline_agents_registered log per sendQuery.

applyNodeConfig is invoked twice: once on a throwaway tempOptions at Line 911–912 to pre-compute warnings, and then again per attempt at Line 953–954. That means claude.inline_agents_registered (and claude.skills_agent_created, which is pre-existing) fires at least twice for every workflow node that uses inline agents, and N+1 times with N retries. It also redundantly materialises the merged map on tempOptions that is then discarded.

Consider splitting warning computation from option mutation, or gating the info log to only fire on the real options path (e.g. skip when options is the throwaway). Non-blocking since the only effect is log noise, but worth cleaning up since this path will hit every inline-agent node.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/providers/src/claude/provider.ts` around lines 453 - 464,
applyNodeConfig is mutating options and unconditionally emitting
getLog().info('claude.inline_agents_registered'), which causes duplicate logs
because applyNodeConfig is invoked once with a throwaway tempOptions and again
with the real options; change applyNodeConfig to accept a small flag (e.g.
dryRun or emitLogs:boolean) or detect a sentinel on tempOptions and skip
emitting the info log when dryRun/emitLogs is false (or when options._isTemp is
true), and only merge nodeConfig.agents into the real options.agents and call
getLog().info({ agentIds: ... }, 'claude.inline_agents_registered') when
emitting is enabled; reference applyNodeConfig, the options.agents merge,
tempOptions, and getLog().info('claude.inline_agents_registered') when making
the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/workflows/src/schemas/dag-node.ts`:
- Line 127: AGENT_ID_REGEX currently allows trailing and consecutive hyphens;
replace its pattern so IDs must start with one or more lowercase letters/digits
and then may have zero or more groups of a single hyphen followed by one or more
lowercase letters/digits (this disallows leading/trailing hyphens and
consecutive hyphens). Update the AGENT_ID_REGEX constant accordingly and
run/adjust any validation tests that rely on agent ID shape so invalid values
like "foo-", "a--b", or "brief-gen-" are rejected at schema validation time
rather than downstream in the Claude Agent SDK.

---

Outside diff comments:
In `@packages/web/src/lib/api.generated.d.ts`:
- Around line 2519-2532: The generated API types are missing the new
ProviderCapabilities.agents boolean flag; regenerate the OpenAPI/type generation
so packages/web/src/lib/api.generated.d.ts includes "agents: boolean" to match
the source definition (packages/providers/src/types.ts) and the runtime
validator (packages/workflows/src/validator.ts which checks caps.agents). Re-run
the OpenAPI/type generation step (or the script that produces
api.generated.d.ts) from the backend schema, verify ProviderCapabilities now
contains agents, and commit the updated generated file.

---

Nitpick comments:
In `@packages/docs-web/src/content/docs/guides/authoring-workflows.md`:
- Line 1160: Replace the non-monotonic list item labeled "12b." with a properly
numbered entry: either merge the "agents" description into item "12" next to
"skills" or renumber it as "13." and increment all following list items (change
13–19 to 14–20); locate the paragraph containing the "12b. **`agents:`**" token
in the authoring-workflows.md content and apply the chosen renumbering so the
ordered list remains sequential.

In `@packages/providers/src/claude/provider.ts`:
- Around line 453-464: applyNodeConfig is mutating options and unconditionally
emitting getLog().info('claude.inline_agents_registered'), which causes
duplicate logs because applyNodeConfig is invoked once with a throwaway
tempOptions and again with the real options; change applyNodeConfig to accept a
small flag (e.g. dryRun or emitLogs:boolean) or detect a sentinel on tempOptions
and skip emitting the info log when dryRun/emitLogs is false (or when
options._isTemp is true), and only merge nodeConfig.agents into the real
options.agents and call getLog().info({ agentIds: ... },
'claude.inline_agents_registered') when emitting is enabled; reference
applyNodeConfig, the options.agents merge, tempOptions, and
getLog().info('claude.inline_agents_registered') when making the change.

In `@packages/providers/src/types.ts`:
- Around line 126-142: The agents structural type in
packages/providers/src/types.ts may drift from the SDK's AgentDefinition; to
detect divergences at build time, add a type-compat assertion in
packages/providers/src/claude/provider.ts where nodeConfig.agents is consumed:
create a compile-time assignment forcing an alias like AgentDefinition =
NonNullable<NodeConfig['agents']>[string] (using the SDK's AgentDefinition type
from `@anthropic-ai/claude-agent-sdk`) so the TypeScript compiler fails the build
if the shapes diverge; reference AgentDefinition, NodeConfig, and the agents
property when adding this assertion.

In `@packages/workflows/src/dag-executor.ts`:
- Line 288: The runtime capability check for agents in the array entry inside
dag-executor.ts currently uses node.agents !== undefined &&
Object.keys(node.agents).length > 0 which differs from the validator behavior;
change this predicate to mirror the other capability checks by removing the
Object.keys(...).length > 0 part so it simply tests node.agents !== undefined
(update the array entry that contains ['agents', 'agents', ...] accordingly) to
keep consistency with validator.ts and the hooks/mcp checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2045a604-6ecf-4183-a743-7c80451dfc6e

📥 Commits

Reviewing files that changed from the base of the PR and between d89bc76 and d30c861.

📒 Files selected for processing (15)
  • CLAUDE.md
  • packages/docs-web/src/content/docs/guides/authoring-workflows.md
  • packages/providers/src/claude/capabilities.ts
  • packages/providers/src/claude/provider.test.ts
  • packages/providers/src/claude/provider.ts
  • packages/providers/src/codex/capabilities.ts
  • packages/providers/src/codex/provider.test.ts
  • packages/providers/src/community/pi/capabilities.ts
  • packages/providers/src/registry.test.ts
  • packages/providers/src/types.ts
  • packages/web/src/lib/api.generated.d.ts
  • packages/workflows/src/dag-executor.test.ts
  • packages/workflows/src/dag-executor.ts
  • packages/workflows/src/schemas/dag-node.ts
  • packages/workflows/src/validator.ts

Comment thread packages/workflows/src/schemas/dag-node.ts Outdated
@Wirasm
Copy link
Copy Markdown
Collaborator Author

Wirasm commented Apr 17, 2026

Related to #1118 — overlapping area or partial fix.

@Wirasm
Copy link
Copy Markdown
Collaborator Author

Wirasm commented Apr 18, 2026

PR Review Summary — 7 agents, findings below

Critical Issues (1)

Agent Issue Location
code-reviewer agentDefinitionSchema / AgentDefinition not re-exported from the schemas index — violates the "schemas/index.ts re-exports all" rule in CLAUDE.md. Every peer schema (incl. sandboxSettingsSchema/SandboxSettings) is listed there. packages/workflows/src/schemas/index.ts

Important Issues (3)

Agent Issue Location
silent-failure-hunter Collision with reserved dag-node-skills ID silently neuters the skills: wrapper. User-wins-on-collision is documented in the code comment and tested, but the user gets no runtime signal — only an info-level claude.inline_agents_registered log. A warn-level log (and preferably a platform message) when 'dag-node-skills' in nodeConfig.agents is set alongside skills: would surface the silent override. packages/providers/src/claude/provider.ts:463
type-design-analyzer NodeConfig.agents is a hand-written structural duplicate of agentDefinitionSchema (violates the project's "use z.infer, never parallel hand-crafted interfaces" rule). The justification — keeping @archon/providers/types SDK-dep-free — is real, but a circular dep prevents the clean fix. Options: extract a minimal agentDefinition contract into a lower package (@archon/paths already has zero @archon/* deps), or accept the duplicate with a CI guard for drift. Same root cause as the as NonNullable<Options['agents']> cast in provider.ts. packages/providers/src/types.ts:126-143
pr-test-analyzer validateWorkflowResources agents-capability warning has zero test coverage (rating 7/10). A Codex-capability mock test mirroring the existing skills test would cover this. packages/workflows/src/validator.ts:409

Suggestions (6)

Agent Suggestion Location
code-simplifier Redundant runtime guard — after schema parsing, node.agents is either undefined or a valid record. typeof node.agents === 'object' adds noise without safety. Match the pattern of the adjacent hooks check. packages/workflows/src/validator.ts:409
code-simplifier Object.keys(node.agents).length > 0 is unreachable — schema's .refine already rejects empty maps. Simplify to node.agents !== undefined to match hooks/mcp. packages/workflows/src/dag-executor.ts:288
comment-analyzer agentDefinitionSchema docstring's parenthetical "(out of v1 scope)" is a time-sensitive phrase that will rot when mcpServers is added. The surrounding sentence already explains the omission — drop the parenthetical. packages/workflows/src/schemas/dag-node.ts:112
comment-analyzer AGENT_ID_REGEX inline comment restates the name — no WHY. Drop. packages/workflows/src/schemas/dag-node.ts:126
type-design-analyzer AGENT_ID_REGEX permits trailing hyphens (abc-), which conventionally violates kebab-case. Minor expression flaw. packages/workflows/src/schemas/dag-node.ts:127
pr-test-analyzer Schema stripping tested only on bash nodes — add parallel parseWorkflow tests for script: and loop: nodes (rating 6/10). packages/workflows/src/dag-executor.test.ts

Strengths

  • Provider translation tests — the three tests (passthrough, options.agent singular untouched, skills-wrapper merge with user-wins) cover the three distinct behaviors of the new block precisely and behaviorally.
  • Schema test surface — full five failure modes covered (valid map, missing description, missing prompt, empty map, non-kebab ID).
  • Capability flag discipline — required boolean forces all providers to declare; Claude/Codex/Pi/mock all updated consistently.
  • Comment at provider.ts:453-457 — the collision-ordering explanation and options.agent vs options.agents distinction are high-value, non-obvious WHY.
  • BASH_NODE_AI_FIELDS disciplineagents correctly added, auto-propagates to SCRIPT_NODE_AI_FIELDS and LOOP_NODE_AI_FIELDS via filter.
  • agents → NodeConfigoptions.agents pass-through is consistent with the established skills: pattern (same dep point, same degradation semantics).

Documentation Gaps

File Issue Fix
packages/docs-web/src/content/docs/guides/authoring-workflows.md:1160 12b. breaks numbered-list sequence after item 12 Renumber to 13; bump existing 13-19 up by one
packages/docs-web/src/content/docs/getting-started/ai-assistants.md Pi provider capability table missing an agents row, leaving Pi users without explicit guidance Add Inline agents (agents:) | ❌ | Claude-only; ignored with warning row
packages/docs-web/src/content/docs/guides/authoring-workflows.md:408-436 New "Inline sub-agents" section doesn't explain when to prefer agents: YAML vs .claude/agents/*.md files Add 1-2 sentences on workflow-specific vs project-wide sub-agents
packages/docs-web/src/content/docs/guides/skills.md Skills Related section doesn't cross-link agents:, despite the two fields composing (with documented collision behavior) Add Related link to #inline-sub-agents
CHANGELOG.md No [Unreleased] entry for this user-facing DAG node field (Pi provider from same batch has one) Add Added-section entry referencing #1276

Verdict

NEEDS FIXES before merge.

Recommended Actions

  1. Add agentDefinitionSchema + AgentDefinition to packages/workflows/src/schemas/index.ts re-exports (critical).
  2. Either (a) emit a warn-level log and user-facing platform message when 'dag-node-skills' in nodeConfig.agents, or (b) schema-level reject that reserved ID in superRefine. Silent capability removal is exactly what Fail Fast means to prevent.
  3. Drop the redundant typeof node.agents === 'object' (validator.ts:409) and Object.keys(...).length > 0 (dag-executor.ts:288).
  4. Drop the "(out of v1 scope)" parenthetical in the agentDefinitionSchema docstring — rot-prone.
  5. Add validator test for the agents capability warning and schema stripping tests for script/loop nodes.
  6. Renumber 12b. in authoring-workflows.md; add Pi capability-table row and CHANGELOG entry.
  7. (Follow-up, optional but recommended) Plan the NodeConfig.agents duplication fix — extract a minimal agent-definition contract into a lower package so z.infer can be used end-to-end.

Critical:
- Re-export agentDefinitionSchema + AgentDefinition from schemas/index.ts
  (matches the "schemas/index.ts re-exports all" convention).

Important:
- Surface user-override of internal 'dag-node-skills' wrapper: warn-level
  provider log + platform message to the user when agents: redefines the
  reserved ID alongside skills:. User-wins behavior preserved (by design)
  but silent capability removal is now observable.
- Add validator test coverage for the agents-capability warning (codex
  node with agents: → warning; claude node → no warning; no-agents
  field → no warning).
- Strengthen NodeConfig.agents duplicate-type comment explaining the
  intentional circular-dep avoidance and pointing at the Zod schema as
  authoritative source. Actual extraction is follow-up work.

Simplifications:
- Drop redundant typeof check in validator (schema already enforces).
- Drop unreachable Object.keys(...).length > 0 check in dag-executor.
- Drop rot-prone "(out of v1 scope)" parenthetical.
- Drop WHAT-only comment on AGENT_ID_REGEX.
- Tighten AGENT_ID_REGEX to reject trailing/double hyphens
  (/^[a-z0-9]+(-[a-z0-9]+)*$/).

Tests:
- parseWorkflow strips agents on script: and loop: nodes (parallel to
  the existing bash: coverage).
- provider emits warn log on dag-node-skills collision; no warn on
  non-colliding inline agents.

Docs:
- Renumber authoring-workflows Summary section (12b → 13; bump 13-19).
- Add Pi capability-table row for inline agents (❌, Claude-only).
- Add when-to-use guidance (agents: vs .claude/agents/*.md) in the
  new "Inline sub-agents" section.
- Cross-link skills.md Related → inline-sub-agents.
- CHANGELOG [Unreleased] Added entry for #1276.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/providers/src/types.ts (1)

126-151: Consider a CI guard to detect drift against agentDefinitionSchema.

The hand-written duplicate is justified (circular-dep contract layer), and the docstring acknowledges the drift risk. To reduce the chance of silent divergence before the follow-up extraction lands, consider a small CI check that type-asserts shape-compatibility, e.g. in a test file that imports both:

import type { z } from '@hono/zod-openapi';
import type { agentDefinitionSchema } from '@archon/workflows/schemas';
import type { NodeConfig } from '@archon/providers/types';

type SchemaAgent = z.infer<typeof agentDefinitionSchema>;
type InlineAgent = NonNullable<NodeConfig['agents']>[string];
// Bidirectional assignability — fails to compile if either side drifts
const _a: SchemaAgent = {} as InlineAgent;
const _b: InlineAgent = {} as SchemaAgent;

This keeps the contract layer SDK-free while failing fast on drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/providers/src/types.ts` around lines 126 - 151, Add a compile-time
CI guard that asserts the hand-written agents shape in NodeConfig stays
type-compatible with the authoritative agentDefinitionSchema: create a test
module that imports agentDefinitionSchema from '@archon/workflows/schemas' and
NodeConfig from '@archon/providers/types', define SchemaAgent = z.infer<typeof
agentDefinitionSchema> and InlineAgent =
NonNullable<NodeConfig['agents']>[string], then add bidirectional assignability
checks (assign InlineAgent to SchemaAgent and vice versa) so the TypeScript
build fails if either side drifts; ensure the test is included in CI so any
divergence between agentDefinitionSchema and the agents field is detected.
packages/workflows/src/dag-executor.test.ts (1)

2472-2515: Codex-agents warning assertion is too loose.

messages.find(m => m.includes('agents') && m.includes('codex')) will also match the skills warning text (e.g. "skills … translated to agents for codex") if it were ever emitted here. Since the node sets agents (not skills), the current test passes, but the assertion doesn't pin the warning to the agents-capability path. Consider tightening to the exact warning phrase used by the validator/executor (e.g. 'inline agents' or "not supported by provider 'codex'") to avoid false positives if skills/agents warnings ever co-occur.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/workflows/src/dag-executor.test.ts` around lines 2472 - 2515, The
test's warning lookup is too loose: instead of using messages.find(m =>
m.includes('agents') && m.includes('codex')), tighten the assertion to match the
exact warning emitted by the executor/validator (for example the phrase "inline
agents" or "not supported by provider 'codex'"); update the predicate used to
build `warning` (in the test case that calls executeDagWorkflow and inspects
platform.sendMessage calls) to search for that exact phrase or a precise regex
so the test pins the agents-capability warning path rather than accidentally
matching a skills-related message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/providers/src/types.ts`:
- Around line 126-151: Add a compile-time CI guard that asserts the hand-written
agents shape in NodeConfig stays type-compatible with the authoritative
agentDefinitionSchema: create a test module that imports agentDefinitionSchema
from '@archon/workflows/schemas' and NodeConfig from '@archon/providers/types',
define SchemaAgent = z.infer<typeof agentDefinitionSchema> and InlineAgent =
NonNullable<NodeConfig['agents']>[string], then add bidirectional assignability
checks (assign InlineAgent to SchemaAgent and vice versa) so the TypeScript
build fails if either side drifts; ensure the test is included in CI so any
divergence between agentDefinitionSchema and the agents field is detected.

In `@packages/workflows/src/dag-executor.test.ts`:
- Around line 2472-2515: The test's warning lookup is too loose: instead of
using messages.find(m => m.includes('agents') && m.includes('codex')), tighten
the assertion to match the exact warning emitted by the executor/validator (for
example the phrase "inline agents" or "not supported by provider 'codex'");
update the predicate used to build `warning` (in the test case that calls
executeDagWorkflow and inspects platform.sendMessage calls) to search for that
exact phrase or a precise regex so the test pins the agents-capability warning
path rather than accidentally matching a skills-related message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a2c3648-eb2c-432f-a56c-62497177807c

📥 Commits

Reviewing files that changed from the base of the PR and between d30c861 and c43ce1f.

📒 Files selected for processing (13)
  • CHANGELOG.md
  • packages/docs-web/src/content/docs/getting-started/ai-assistants.md
  • packages/docs-web/src/content/docs/guides/authoring-workflows.md
  • packages/docs-web/src/content/docs/guides/skills.md
  • packages/providers/src/claude/provider.test.ts
  • packages/providers/src/claude/provider.ts
  • packages/providers/src/types.ts
  • packages/workflows/src/dag-executor.test.ts
  • packages/workflows/src/dag-executor.ts
  • packages/workflows/src/schemas/dag-node.ts
  • packages/workflows/src/schemas/index.ts
  • packages/workflows/src/validator.test.ts
  • packages/workflows/src/validator.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/docs-web/src/content/docs/guides/authoring-workflows.md
  • packages/workflows/src/validator.ts
  • CHANGELOG.md
  • packages/docs-web/src/content/docs/guides/skills.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/workflows/src/dag-executor.ts
  • packages/providers/src/claude/provider.ts
  • packages/providers/src/claude/provider.test.ts
  • packages/workflows/src/schemas/dag-node.ts

@Wirasm Wirasm merged commit 60eeb00 into dev Apr 19, 2026
4 checks passed
Wirasm added a commit that referenced this pull request Apr 19, 2026
Adds .archon/workflows/repo-triage.yaml: a self-contained periodic
maintenance workflow that uses inline sub-agents (Claude SDK agents:
field introduced in #1276) for map-reduce across open issues and PRs.

Six DAG nodes, three-layer topology:
- Layer 1 (parallel): triage-issues, link-prs, closed-pr-dedup-check,
  stale-nudge
- Layer 2: closed-dedup-check (reads triage-issues state)
- Layer 3: digest (synthesises all prior nodes + writes markdown)

Capabilities per node:
- triage-issues: delegates labeling to on-disk triage-agent; inline
  brief-gen Haiku for duplicate detection; 3-day auto-close clock
  for unanswered duplicate warnings
- link-prs: conservative PR ↔ issue cross-refs via inline pr-issue-
  matcher Haiku, Sonnet re-verifies fully-addresses claims before
  suggesting Closes #X; auto-nudges on low-quality PR template fill
  with first-run grandfather guard (snapshot-only, no nudge spam)
- closed-dedup-check: cross-matches open issues against recently-
  closed ones via inline closed-brief-gen Haiku; same 3-day clock
- closed-pr-dedup-check: flags open PRs duplicating recently-closed
  PRs via inline pr-brief-gen Haiku; comment-only, never closes PRs
- stale-nudge: 60-day inactivity pings (configurable); no auto-close
- digest: synthesises per-node outputs + reads state files to emit
  $ARTIFACTS_DIR/digest.md with clickable GitHub comment links

Env-gated rollout knobs:
- DRY_RUN=1 (read-only; prints [DRY] lines, no gh/state mutations)
- SKIP_PR_LINK=1, SKIP_CLOSED_DEDUP=1, SKIP_CLOSED_PR_DEDUP=1,
  SKIP_STALE_NUDGE=1
- STALE_DAYS=N (stale-nudge window; default 60)

Cross-run state under .archon/state/ (gitignored):
- triage-state.json        briefs + pendingDedupComments
- closed-dedup-state.json  closedBriefs + closedMatchComments
- closed-pr-dedup-state.json openBriefs + closedBriefs + matches
- pr-state.json            linkedPrs + commentIds + templateAdherence
- stale-nudge-state.json   nudged (with updatedAtAtNudge for re-nudge)

Every bot comment:
- @-tags the target human (reporter for issues, author for PRs)
- Tracks comment ID in state for traceability
- Is idempotent — re-runs skip existing comments

Intended use: invoke periodically (`archon workflow run repo-triage
--no-worktree`) once a scheduler lands; live state persists across
runs so previously-flagged items reconcile correctly.

.gitignore: adds .archon/state/ for cross-run memory files.
Wirasm added a commit that referenced this pull request Apr 20, 2026
…iku sub-agents (#1293)

* feat(workflows): add repo-triage — 6-node periodic maintenance workflow

Adds .archon/workflows/repo-triage.yaml: a self-contained periodic
maintenance workflow that uses inline sub-agents (Claude SDK agents:
field introduced in #1276) for map-reduce across open issues and PRs.

Six DAG nodes, three-layer topology:
- Layer 1 (parallel): triage-issues, link-prs, closed-pr-dedup-check,
  stale-nudge
- Layer 2: closed-dedup-check (reads triage-issues state)
- Layer 3: digest (synthesises all prior nodes + writes markdown)

Capabilities per node:
- triage-issues: delegates labeling to on-disk triage-agent; inline
  brief-gen Haiku for duplicate detection; 3-day auto-close clock
  for unanswered duplicate warnings
- link-prs: conservative PR ↔ issue cross-refs via inline pr-issue-
  matcher Haiku, Sonnet re-verifies fully-addresses claims before
  suggesting Closes #X; auto-nudges on low-quality PR template fill
  with first-run grandfather guard (snapshot-only, no nudge spam)
- closed-dedup-check: cross-matches open issues against recently-
  closed ones via inline closed-brief-gen Haiku; same 3-day clock
- closed-pr-dedup-check: flags open PRs duplicating recently-closed
  PRs via inline pr-brief-gen Haiku; comment-only, never closes PRs
- stale-nudge: 60-day inactivity pings (configurable); no auto-close
- digest: synthesises per-node outputs + reads state files to emit
  $ARTIFACTS_DIR/digest.md with clickable GitHub comment links

Env-gated rollout knobs:
- DRY_RUN=1 (read-only; prints [DRY] lines, no gh/state mutations)
- SKIP_PR_LINK=1, SKIP_CLOSED_DEDUP=1, SKIP_CLOSED_PR_DEDUP=1,
  SKIP_STALE_NUDGE=1
- STALE_DAYS=N (stale-nudge window; default 60)

Cross-run state under .archon/state/ (gitignored):
- triage-state.json        briefs + pendingDedupComments
- closed-dedup-state.json  closedBriefs + closedMatchComments
- closed-pr-dedup-state.json openBriefs + closedBriefs + matches
- pr-state.json            linkedPrs + commentIds + templateAdherence
- stale-nudge-state.json   nudged (with updatedAtAtNudge for re-nudge)

Every bot comment:
- @-tags the target human (reporter for issues, author for PRs)
- Tracks comment ID in state for traceability
- Is idempotent — re-runs skip existing comments

Intended use: invoke periodically (`archon workflow run repo-triage
--no-worktree`) once a scheduler lands; live state persists across
runs so previously-flagged items reconcile correctly.

.gitignore: adds .archon/state/ for cross-run memory files.

* feat(workflows/repo-triage): post digest to Slack when SLACK_WEBHOOK is set

Extends the digest node with an optional Slack-post step after the
canonical digest.md artifact is written. Uses Slack incoming webhook
(no bot token required beyond the incoming-webhook scope).

Behavior:
- SLACK_WEBHOOK unset → skipped silently with a one-line note
- DRY_RUN=1 → prints full payload, does not curl
- Otherwise → POSTs a compact (<3500 char) mrkdwn-formatted summary
  containing headline numbers, this-run comment index (clickable
  GitHub URLs), pending items, and a path reference to digest.md
- curl failure or non-ok Slack response is logged but does not fail
  the node — digest.md on disk remains authoritative
- Intermediate Slack text written to $ARTIFACTS_DIR/digest-slack.txt
  for traceability; payload JSON assembled via jq and written to
  $ARTIFACTS_DIR/slack-payload.json before curl posts it

Slack mrkdwn conversion rules baked into the prompt (no tables, link
shape <url|text>, single-asterisk bold) so Sonnet emits a variant
that renders cleanly in Slack rather than being sent raw.

The webhook URL is read from the operator's environment (Archon
auto-loads ~/.archon/.env on CLI startup — put SLACK_WEBHOOK=... there).

* fix(workflows/repo-triage): address PR #1293 review feedback

Critical (3):
- `gh issue close --reason "not planned"` (space, not underscore) — the
  CLI expects lowercase with a space; `not_planned` fails at runtime.
  Fixed in both auto-close paths (triage-issues step 8, closed-dedup-
  check step 7).
- link-prs step 7 state save was sparse `{ sha, processedAt, related,
  fullyAddresses }`, overwriting `commentIds` / `templateNudgedAt` /
  `templateAdherence`. Changed to explicit merge that spreads existing
  entry first so per-run captured fields survive.
- Corrupt-JSON state files previously treated as first-run default
  (silent `pendingDedupComments` reset → 3-day clock restarts forever).
  All five state-load sites now abort loudly on JSON.parse throw;
  ENOENT/empty continue to default-shape.

Important (7):
- Sub-agents (`brief-gen`, `closed-brief-gen`, `pr-brief-gen`,
  `pr-issue-matcher`) emit `ERROR: <reason>` on gh failures rather than
  partial/fabricated JSON. Orchestrator detects the sentinel, logs the
  failed ID + first 200 chars of raw response, tracks in a failed-list,
  and aborts the cluster/match pass if ≥50% of items failed (avoids
  acting on bad data).
- `pr-brief-gen` now sets `diffTruncated: true` when the 30k-char diff
  cap hits; link-prs verify pass downgrades any `fully-addresses` claim
  to `related` when either side's brief was truncated.
- 3-day auto-close validates `postedAt` parses as ISO-8601 before the
  elapsed-time comparison; corrupt timestamps are logged and skipped,
  never acted on.
- `gh issue close` failure path no longer drops state — sets
  `closeAttemptFailed: true` on the entry for next-run retry. Only
  drops on exit 0.
- `closed-pr-dedup-check` idempotency check (`gh pr view --json comments`)
  now aborts the post on fetch failure rather than falling through —
  prevents double-posts on gh hiccups.
- `triage-agent` label pass has preflight `test -f` check for
  `.claude/agents/triage-agent.md`; skips the pass with a clear log if
  the file is missing rather than firing Task calls that fail obscurely.
- `brief-gen` template-adherence wording flipped from "Ignore … as
  'filled'" (ambiguous, read as affirmative) to explicit "A section
  counts as MISSING when …", matching the `pr-issue-matcher` phrasing.

Minor:
- `stale-nudge` idempotency check uses substring "has been quiet for"
  instead of a prefix check that never matched (posted body starts
  with @<author>).
- `closed-dedup-check` distinguishes "upstream crashed" (missing/corrupt
  triage-state.json, or `lastRunAt == null`) from "legitimately quiet
  day" (state present, briefs empty) — different log lines.
- Slack curl adds `-w "\nHTTP_STATUS:%{http_code}"` + `2>&1` so TLS /
  4xx / 5xx errors are visible in captured output.
- `stateReason` values from `gh issue view --json stateReason` are
  UPPERCASE (`COMPLETED`, `NOT_PLANNED`); documented and instruct
  sub-agent to normalize to lowercase for consistency.

Docs:
- CLAUDE.md repo-level `.archon/` tree now lists `state/`.
- archon-directories.md tree adds `state/` + `scripts/` (both were
  missing) with purpose descriptions.

Deferred (worth doing as a follow-up, not blocking):
- DRY/SKIP preamble duplication (~30-50 lines across 5 nodes).
- Explicit `BASELINE_IS_EMPTY` capture in link-prs (current derived
  check works but is a load-bearing model instruction).
- Digest `WARNING` prefix block when upstream nodes are missing
  outputs — today's "(output unavailable)" sub-line is functional.
- Pre-existing README workflow-count (17 → 20) and table gaps — not
  caused by this PR.
@Wirasm Wirasm mentioned this pull request Apr 22, 2026
@Wirasm Wirasm deleted the feat/inline-agents branch April 27, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant