Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .devflow/features/ambient-orchestrator/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Use when modifying the ambient mode hooks (preamble, session-start
category: architecture
directories: [src/assets/scripts/hooks, src/cli/commands/ambient.ts, src/core/plugins.ts]
created: 2026-07-04
updated: 2026-07-15
updated: 2026-08-25
---

# Ambient Orchestrator Mode
Expand Down Expand Up @@ -37,7 +37,7 @@ The orchestrator reminder block carries an inline cross-reference comment markin

### orchestrator-charter.md

A static markdown file at `src/assets/scripts/hooks/assets/orchestrator-charter.md` consumed at runtime by `session-start-orchestrator`. Contains the full orchestrator contract: model-tier routing table (haiku/sonnet/opus), judgment-work carve-outs, delegation rules, the plan-handoff fallback bullet, and a feature-knowledge operating rule. The never-mainline rule explicitly names codebase orientation as delegated work (alongside file edits, builds, multi-file reads, and debug loops). The sonnet tier routes Code agent (write code to a plan; also fixes pre-classified review issues in issue-fix mode) and Skim agent (codebase orientation) — both are defined-execution agents. The feature-knowledge rule (direct delegations only — workflow skills handle their own) instructs the orchestrator to: (1) before delegating non-trivial code work, match the task area against `.devflow/features/index.md` and pass matching KNOWLEDGE.md content as `FEATURE_KNOWLEDGE`; (2) after delegated changes to a covered area, spawn Knowledge (sonnet) to refresh that KB. The charter is 2141 bytes (~535 tokens), well under the 4096-byte runtime cap enforced by the hook.
A static markdown file at `src/assets/scripts/hooks/assets/orchestrator-charter.md` consumed at runtime by `session-start-orchestrator`. Contains the full orchestrator contract: model-tier routing table (haiku/sonnet/opus), judgment-work carve-outs, delegation rules (including a self-contained-delegation operating rule: subagents start with blank context, so every delegation must supply goal, constraints, relevant session decisions and facts, and exact paths — deliverables that draw on the conversation need the substance in the prompt, not a pointer to it), the plan-handoff fallback bullet, and a feature-knowledge operating rule. The never-mainline rule explicitly names codebase orientation as delegated work (alongside file edits, builds, multi-file reads, and debug loops). The sonnet tier routes Code agent (write code to a plan; also fixes pre-classified review issues in issue-fix mode) and Skim agent (codebase orientation) — both are defined-execution agents. The feature-knowledge rule (direct delegations only — workflow skills handle their own) instructs the orchestrator to: (1) before delegating non-trivial code work, match the task area against `.devflow/features/index.md` and pass matching KNOWLEDGE.md content as `FEATURE_KNOWLEDGE`; (2) after delegated changes to a covered area, spawn Knowledge (sonnet) to refresh that KB. The charter is 2452 bytes (~615 tokens), well under the 4096-byte runtime cap enforced by the hook.

### git-marker (sourced helper)

Expand Down Expand Up @@ -116,7 +116,7 @@ The model-tier routing table (haiku/sonnet/opus taxonomy) is a second intentiona

## Constraints

**4096-byte charter cap**: `session-start-orchestrator` exits silently if the charter exceeds 4096 bytes. The test suite pins the exact-4096-byte boundary as an accept case (the hook uses `-gt 4096`, so 4096 is accepted). Growing the charter beyond this cap silently disables it — always check `${#CHARTER}` after edits. The charter is currently 2141 bytes, leaving ~1955 bytes of headroom.
**4096-byte charter cap**: `session-start-orchestrator` exits silently if the charter exceeds 4096 bytes. The test suite pins the exact-4096-byte boundary as an accept case (the hook uses `-gt 4096`, so 4096 is accepted). Growing the charter beyond this cap silently disables it — always check `${#CHARTER}` after edits. The charter is currently 2452 bytes, leaving ~1644 bytes of headroom.

**256-byte prompt head**: The preamble dispatch window is the first 256 bytes post-whitespace-strip. Plan-handoff prompts have zero leading whitespace by definition; the strip is defensive. The window is wide enough for the known prefix but is not semantic detection.

Expand Down Expand Up @@ -160,7 +160,7 @@ The model-tier routing table (haiku/sonnet/opus taxonomy) is a second intentiona

- `src/assets/scripts/hooks/preamble` — UserPromptSubmit hook: dispatch logic, plan-handoff fast-path, orchestrator reminder; cross-reference comment linking to orchestrator-charter.md routing table
- `src/assets/scripts/hooks/session-start-orchestrator` — SessionStart hook: charter file read, size guard, hook-log-init injection log, additionalContext output
- `src/assets/scripts/hooks/assets/orchestrator-charter.md` — Static charter content; the plan-handoff fallback bullet, authoritative model-tier routing table, and feature-knowledge operating rule live here
- `src/assets/scripts/hooks/assets/orchestrator-charter.md` — Static charter content; the plan-handoff fallback bullet, authoritative model-tier routing table, self-contained-delegation operating rule, and feature-knowledge operating rule live here
- `src/assets/scripts/hooks/git-marker` — Sourced pure-bash helper: `df_has_git_marker <dir>` bounded upward walk; direct behavioral tests + no-subprocess source scan in test suite
- `src/cli/commands/ambient.ts` — TypeScript management: `ensureHook`, `addAmbientHook`, `removeAmbientHook`, `hasAmbientHook`, `ambientCommand` (parses settings.json once with try/catch)
- `tests/fixtures/ambient-templates.ts` — Shared constants: `HANDOFF_TEMPLATE` and `REMINDER_TEMPLATE`; imported by shell-hooks.test.ts and integration tests to keep both test layers byte-synchronized
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
- **Orchestrator charter — self-contained delegation**: added an operating rule requiring every subagent delegation to be self-contained (goal, constraints, relevant session facts, exact paths). Deliverables that draw on the conversation (issues, PRs, reports) must carry the substance in the prompt rather than a pointer to it. Charter grows from 2177 → 2452 bytes (~600 tokens), well within the 4096-byte runtime limit.

---

## [2.1.0] - 2026-08-25
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Registry-driven CLI tool with 21 plugins (12 core + 9 optional). Plugins are ent

**Working Memory**: A capture/spawn split across always-on hooks in `src/assets/scripts/hooks/`. Toggleable via `devflow memory --enable/--disable/--status` or `devflow init --memory/--no-memory`. Feature state is stored in `.devflow/config.json` (config-only; feature config is the sole source of truth per ADR-001). `capture-prompt` (UserPromptSubmit, always-on) and `capture-turn` (Stop, always-on) — append the user/assistant turn to `.devflow/memory/.pending-turns.jsonl` via the shared `queue-append` helper (dual-write; see Learning pipeline for the sibling learning queue), which uses mkdir-based locking for queue overflow truncation across concurrent sessions; each queue is gated independently by feature config; neither ever spawns anything. `memory-worker` (Stop, registered immediately after `capture-turn` so append-before-spawn ordering holds by array position) — after the 120s throttle (keyed by `.working-memory-last-trigger` mtime), touches the trigger then spawns `background-memory-update` as a detached `nohup` worker (`claude -p --model claude-sonnet-4-6`). `background-memory-update` (detached worker, not a hook itself) — drains `.pending-turns.jsonl`, calls `claude -p` (prompt on stdin, never argv), rewrites `WORKING-MEMORY.md` with `<!-- memory-head: <sha> branch: <name> -->` on line 1, touches `.last-refresh-ok` on success; holds a 300s-stale worker lock; user-only queue truncated without LLM run. `session-start-memory` (SessionStart) → injects previous memory with git-reconciled header (3-state: A in-sync / B drifted / C refresh-failing) + optional pre-compact snapshot as `additionalContext`; stamp `<!-- memory-head: <sha> branch: <name> -->` on line 1 drives drift detection; also recovers a stale orphaned `.pending-turns.processing` itself (self-contained cold path, no external helper). PreCompact hook → saves git state + WORKING-MEMORY.md snapshot. Memory sections: `## Now`, `## Progress`, `## Decisions`, `## Context`, `## Session Log`. The background-memory-update worker uses rename-to-claim for queue consumption (atomically renames `.pending-turns.jsonl` → `.pending-turns.processing`). Disabling memory writes `memory: false` to feature config — hooks remain registered (shared across features). `removeMemoryHooks` (used by `devflow init --no-memory`) also removes legacy hooks from prior architectures. Use `devflow memory --clear` to clean up pending queue files across projects. Zero-ceremony context preservation.

**Ambient Mode**: Two-hook orchestrator system (git repos only) controlled by a single toggle (`devflow ambient --enable/--disable/--status` or `devflow init`). **`session-start-orchestrator`** (SessionStart, presence-gated) — injects the orchestrator charter (~535 tokens) as `additionalContext` at every session start (startup, `/clear`, resume, compact). The charter establishes the main session as a pure orchestrator: delegate work to model-tiered sub-agents (haiku=mechanical, sonnet=defined execution, opus=analysis/design/research) or full devflow workflow skills; keep only judgment work mainline. Also carries a plan-handoff fallback bullet (SessionStart provably fires even when UserPromptSubmit does not). **`preamble`** (UserPromptSubmit, presence-gated) — three behaviors: (1) if prompt begins `Implement the following plan:` (Claude Code's native plan-mode handoff prefix), injects a directive to immediately invoke `devflow:implement`; (2) slash commands (`/...`) are silenced; (3) all other prompts get a 2-line orchestrator reminder. Both hooks are silent outside git repos. Any legacy `commands.md` rule or `session-start-classification` hook from prior installs is auto-removed on every `devflow ambient --enable/--disable` or `devflow init`.
**Ambient Mode**: Two-hook orchestrator system (git repos only) controlled by a single toggle (`devflow ambient --enable/--disable/--status` or `devflow init`). **`session-start-orchestrator`** (SessionStart, presence-gated) — injects the orchestrator charter (~600 tokens) as `additionalContext` at every session start (startup, `/clear`, resume, compact). The charter establishes the main session as a pure orchestrator: delegate work to model-tiered sub-agents (haiku=mechanical, sonnet=defined execution, opus=analysis/design/research) or full devflow workflow skills; keep only judgment work mainline. Also carries a plan-handoff fallback bullet (SessionStart provably fires even when UserPromptSubmit does not). **`preamble`** (UserPromptSubmit, presence-gated) — three behaviors: (1) if prompt begins `Implement the following plan:` (Claude Code's native plan-mode handoff prefix), injects a directive to immediately invoke `devflow:implement`; (2) slash commands (`/...`) are silenced; (3) all other prompts get a 2-line orchestrator reminder. Both hooks are silent outside git repos. Any legacy `commands.md` rule or `session-start-classification` hook from prior installs is auto-removed on every `devflow ambient --enable/--disable` or `devflow init`.

**Learning pipeline** (directive-spawned background Learning agent — scripts capture and trigger only): `capture-prompt`/`capture-turn`/`capture-question` (all always-on) append every user turn, assistant turn, and answered `AskUserQuestion` to `.devflow/learning/.pending-turns.jsonl`, gated by the `learning` field in feature config (config-only, mirroring memory's ADR-001). `session-start-context` Section 2 (SessionStart, always-on) — when the learning queue is non-empty, or a crashed run left a `.pending-turns.processing` batch older than 900s, it resolves the model (project `.devflow/learning/learning.json` → global `~/.devflow/learning.json` → `opus` default) and emits a `--- LEARNING MAINTENANCE ---` directive instructing the main model to **silently** spawn `Agent(subagent_type="Learning", model=<resolved>, run_in_background: true)` **(never narrated in user-visible text)**; a fresh `.processing` suppresses the directive (a live agent owns the batch); queue emptiness is the natural gate, so there is no throttle. The **Learning agent** (`src/assets/agents/learning.md`, opus, self-contained) claims the queue itself (atomic `mv` → `.processing`; merges a stale leftover and re-claims it; exits silently if the claim is lost; heartbeat `touch` at the detection→curation boundary), reads `decisions-log.jsonl`/`decisions.md`/`pitfalls.md`/`.decisions-usage.json` directly, appends/edits observations in the log directly (one JSONL row at a time, never whole-file rewrites), and calls only the ledger ops via its Bash tool: **decision**/**pitfall** detection via `assign-anchor` (internally self-locks `.decisions.lock`; assigns the next ADR-NNN/PF-NNN anchor number into `decisions-ledger.jsonl`, then deterministically renders `decisions.md`/`pitfalls.md`/`index.md` from the ledger — active entries only) and periodic curation via `retire-anchor` (flips `decisions_status`, never deletes) plus `rotate-observations`. Raw observations accumulate in the gitignored `.devflow/learning/decisions-log.jsonl` (rotated to `decisions-log.archive.jsonl`). No deterministic thresholds or confidence formulas — the LLM determines whether an observation warrants a new entry or should be reinforced into an existing one. The agent deletes `.processing` as its final act (consume-then-delete; a crash leaves the batch for the next session's stale-merge recovery) and ends with a 1–3 line summary — native background-task visibility, no status files. Global tuning config: `~/.devflow/learning.json`. Project tuning config: `.devflow/learning/learning.json` (`model` and `debug` only — no daily-run cap or throttle). `devflow learning --disable` flips the config field and drains `.devflow/learning/.pending-turns.jsonl`/`.pending-turns.processing` unconditionally (a mid-run agent whose files vanish aborts without changes — the desired outcome of disabling; mirrors memory.ts's disable-drain). Toggleable via `devflow learning --enable/--disable/--status` or `devflow init --learning/--no-learning`. Management subcommands: `devflow learning --list`, `devflow learning --configure`, `devflow learning --clear/--reset` (both resolve the git root explicitly).

Expand Down
1 change: 1 addition & 0 deletions src/assets/scripts/hooks/assets/orchestrator-charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Stays mainline (judgment work): conversation, decisions, routing, synthesizing a

Operating rules:
- Decompose mainline. Subagents cannot spawn subagents — you own task breakdown, then delegate leaf tasks.
- Subagents see none of this conversation. Make every delegation self-contained: goal, constraints, relevant session decisions and facts, exact paths. A deliverable that draws on the conversation (issue, PR, report) needs the substance in the prompt — not a pointer to it.
- Parallelize independent delegations in one message. Git operations stay sequential.
- Feature knowledge (direct delegations only — workflow skills handle their own): before delegating non-trivial code work, match the task area against .devflow/features/index.md and pass matching KNOWLEDGE.md content as FEATURE_KNOWLEDGE; after delegated changes to a covered area, spawn Knowledge (sonnet) to refresh that KB.
- Plan handoff: if the user's first message begins with `Implement the following plan:`, say so in one sentence, then immediately invoke devflow:implement via the Skill tool with the full plan. Do not pause to ask.