Skip to content

feat(ambient)!: replace keyword/plan detection with orchestrator charter + plan handoff#251

Merged
dean0x merged 13 commits into
mainfrom
feat/ambient-orchestrator-charter
Jul 5, 2026
Merged

feat(ambient)!: replace keyword/plan detection with orchestrator charter + plan handoff#251
dean0x merged 13 commits into
mainfrom
feat/ambient-orchestrator-charter

Conversation

@dean0x

@dean0x dean0x commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • Removes both old ambient detection paths: first-word keyword dispatch (implement, explore, research, debug, plan) and 3-marker plan detection (## Goal / ## Steps / ## Files). These added overhead and duplicated slash commands.
  • Adds session-start-orchestrator — a SessionStart hook that injects a static ~200-token orchestrator charter as additionalContext at every session start, establishing the main model as a pure delegator and grading sub-agents by complexity (haiku → sonnet → opus → full workflows).
  • Rewrites preamble to three clean behaviors: plan-handoff fast-path (Implement the following plan: prefix → devflow:implement), slash skip (no output), and a 2-line orchestrator reminder for all other prompts. Both hooks are git-repo-gated via a new sourced git-marker helper (pure bash, 64-level bounded walk, no subprocess).
  • Both hooks share the same devflow ambient --enable/--disable toggle. Partial state (preamble present, orchestrator missing) is detected and reported by devflow ambient --status with a repair note.

Changes

  • scripts/hooks/orchestrator-charter.md — static charter asset (≤4096 chars, enforced)
  • scripts/hooks/session-start-orchestrator — new SessionStart hook; DEVFLOW_BG_UPDATER re-entrancy guard; fail-open
  • scripts/hooks/preamble — rewritten; old keyword case statement and 3-marker detection removed
  • scripts/hooks/git-marker — sourced helper: df_has_git_marker; bash 3.2 compatible
  • src/cli/commands/ambient.ts — ORCHESTRATOR_HOOK_MARKER, partial-state detection/repair, updated messaging
  • src/cli/commands/init.ts / uninstall.ts — updated descriptions
  • Tests: 1881 passing; new describe('session-start-orchestrator', ...) block + full preamble — orchestrator charter mode rewrite; tests/integration/ambient-activation.test.ts updated

Breaking Changes

Both old detection paths are removed. Sessions that relied on keyword-prefixed prompts auto-routing workflows will no longer get that behavior — the orchestrator charter approach delegates routing to the model's judgment based on context, not string matching.

Reviewer Focus Areas

  • scripts/hooks/session-start-orchestrator: verify it mirrors session-start-context structure (no set -e, fail-open, re-entrancy guard)
  • scripts/hooks/preamble: confirm clean removal of shopt -s nocasematch, keyword case, and 3-marker grep — no residue
  • scripts/hooks/git-marker: check the 64-level walk handles /, empty string, and .git-as-file correctly
  • src/cli/commands/ambient.ts: hasAmbientHook (preamble-authoritative), hasOrchestratorHook, partial-state detection, idempotent addAmbientHook
  • orchestrator-charter.md: content correctness — model tier routing, plan-handoff fallback bullet, ≤4096 char budget

Upgrade Note

After upgrading, run devflow init to register the new session-start-orchestrator hook. Existing installs with only the preamble hook are in partial state — devflow ambient --enable repairs it.

T-5 empirical outcome: pending live verification post-merge deploy.

Prefix re-validation (2026-07-04, pre-merge): The handoff prefix was re-confirmed live — this feature's own implementation session was a native "execute plan in new session" handoff at v2.1.198, and its first user prompt begins with the literal Implement the following plan:. Local transcript survey shows the prefix stable across v2.1.167→v2.1.198 with no alternative phrasing in any project; changelog/docs through v2.1.201 show no handoff-format change. Schema note: transcripts now carry the plan body in a top-level planContent field with origin: {"kind":"auto-continuation"}message.content holds only the prefix. This is harmless to the fast-path (the match is prefix-anchored and the model still receives the full plan in context), but the origin tag is a plausible discriminator Claude Code could use to skip UserPromptSubmit for injected prompts — T-5 remains the definitive post-deploy test.

dean0x and others added 6 commits July 4, 2026 16:25
…ter + plan handoff

Removes both old ambient detection paths (first-word keyword dispatch and
3-marker plan detection) and replaces them with a two-hook orchestrator system:

- scripts/hooks/orchestrator-charter.md: static ~200-token charter injected at
  every SessionStart as additionalContext, establishing the main model as a pure
  orchestrator and grading sub-agents by complexity (haiku/sonnet/opus)
- scripts/hooks/session-start-orchestrator: new SessionStart hook that reads the
  charter and emits it via json_session_output; silent outside git repos, guards
  against DEVFLOW_BG_UPDATER re-entrancy
- scripts/hooks/preamble: rewritten to three behaviors — plan-handoff fast-path
  (prompts beginning "Implement the following plan:" invoke devflow:implement),
  slash skip (no output), and 2-line orchestrator reminder for all other prompts
- scripts/hooks/git-marker: sourced helper providing df_has_git_marker, a pure
  bash bounded upward walk (64 levels, no subprocess) for git repo detection

ambient.ts gains ORCHESTRATOR_HOOK_MARKER, partial-state detection and repair,
and updated enable/disable/status messaging. Tests: 1881 passing.

Upgrade: run `devflow init` to register the session-start-orchestrator hook.
Existing installs with only the preamble hook are in partial state — run
`devflow ambient --enable` to repair.
…ring

preamble: remove `set -e` — aligns with the session-start-orchestrator
pattern and the stated design invariant (fail-open via guard clauses,
no set -e). Guard clauses already ensure exit 0 on every path; omitting
set -e makes the hook strictly more fail-safe.

session-start-orchestrator: move json_session_output before the
"=== HOOK COMPLETE ===" debug log so the trace accurately marks
completion after all work is done, consistent with preamble.
- Sync devflow-ambient description across plugins.ts + marketplace.json
  with plugin.json (removed stale 'Keyword + plan auto-detection' /
  'classifies intent' wording that described the pre-ADR-004 behavior)
- Realign marketplace.json ambient keywords with plugin.json
- Fix stale integration-test title/comment claiming a normal prompt
  produces no hook output; now injects the orchestrator reminder and
  asserts it does not trigger a spurious skill invocation
The background memory worker runs claude -p in the project git root with
DEVFLOW_BG_UPDATER=1 and fires UserPromptSubmit. The redesigned preamble
emits the orchestrator reminder on every non-slash/non-empty prompt, so
every background memory refresh would otherwise be injected with a
delegate-to-agents directive a haiku one-shot cannot act on. Add the
canonical re-entrancy guard (mirrors capture-prompt and
session-start-orchestrator) + F13 regression test.
Relocates scripts/hooks/orchestrator-charter.md to
scripts/hooks/assets/orchestrator-charter.md, establishing an
assets/ subdirectory for static prose assets shipped with hooks.

Updates:
- session-start-orchestrator: CHARTER_FILE path → assets/ subdir
- tests/shell-hooks.test.ts: CHARTER_FILE const + oversize-charter
  fixture (creates assets/ dir before writing the test file)
- tests/skill-references.test.ts: Format 5 scan extended to also
  cover scripts/hooks/assets/*.md (flat readdirSync was hook-only)
- CLAUDE.md + docs/reference/file-organization.md: structure docs
- .devflow/features/ambient-orchestrator/KNOWLEDGE.md: path refs

Content of the charter itself is byte-identical (only location moved).

Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x

dean0x commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

Review Summary: PR #251 Code Comments

Review findings consolidated and deduplicated across 10 reports. Posting inline comments for ≥80% confidence blocking/should-fix issues.

Comment Strategy

  • Inline comments: Blocking and should-fix findings at ≥80% confidence
  • This summary: Lower-confidence suggestions and summary recommendations
  • Deduplication: Performance + Reliability + TypeScript double-parse consolidated into one point

Key Blocking Issues (≥80% confidence)

  1. README.md Lines 19 & 44 (CRITICAL, 97%) — Stale keyword/structured-plan prose
  2. ambient.ts:226-238 (MEDIUM, 80%, Architecture) — Status observability gap for orchestrator-only state
  3. ambient.ts:112-130 (MEDIUM, 80%, Complexity) — Duplicated hook-registration block
  4. ambient.ts:227 (MEDIUM, 80%, Reliability) — Unguarded JSON.parse crashes on corrupt settings
  5. KNOWLEDGE.md:33 (MEDIUM, 88%, Documentation) — Dispatch table contradicts code for empty prompts
  6. shell-hooks.test.ts:637 (MEDIUM, 90%, Testing) — AC-F12 test mislabeled, doesn't verify claimed window
  7. git-marker testing (MEDIUM, 88%, Testing) — No direct test for subprocess-purity invariant

Should-Fix Issues (≥80% confidence)

  1. ambient.ts:88-137 (LOW, 80%, Regression) — addAmbientHook asymmetry: doesn't sweep classification hook
  2. ambient.ts:113 (LOW, 80%, TypeScript) — Inline hasOrchestratorHook shadows module-level function
  3. shell-hooks.test.ts:947 (LOW, 80%, Testing) — 4096-byte charter boundary (exactly 4096) untested

Lower-Confidence Suggestions (60-79%)

  • Double JSON.parse optimization (65-88%) — Lines 227-229: parse once, pass object to both functions
  • Three near-identical predicates (65%) — isAmbient, hasPreamble, hasAmbientHook each re-encode "is preamble present"
  • Model-tier routing taxonomy duplication (60%) — haiku/sonnet/opus mapping in charter and preamble reminder
  • Integration test coupled to hook output (70%) — systemPrompt hardcoded; should reference shell-hooks templates
  • Non-git tests environmental dependency (65%) — F6a-F6b rely on TMPDIR having no .git ancestor

Recommendation: APPROVED_WITH_CONDITIONS
Address the README documentation and KNOWLEDGE.md dispatch-table contradictions (CRITICAL/MEDIUM) before merge. All other findings are fixable and improve robustness.

Generated by Claude Code devflow:comment-pr operation

Comment thread src/cli/commands/ambient.ts Outdated
p.log.info(`Ambient mode: ${color.green('enabled')}`);
}
} else {
p.log.info(`Ambient mode: ${color.dim('disabled')}`);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Status observability gap: Orchestrator-only state reports as disabled (MEDIUM, 80%)

When hasAmbientHook returns false (no preamble) but the orchestrator SessionStart hook exists, this line prints plain disabled with no hint about the stray hook.

The orchestrator hook fires every session and injects the charter, so the reported state contradicts observable behavior. The mirror partial-state case (preamble without orchestrator) correctly gets a partial hint on line 231.

Fix: Check for the orchestrator-only case in the else branch:

} else {
  if (hasOrchestratorHook(settingsContent)) {
    p.log.info(`Ambient mode: ${color.dim('disabled')} ${color.dim('(partial — stray orchestrator hook; run devflow ambient --disable to clean up)')}`);  
  } else {
    p.log.info(`Ambient mode: ${color.dim('disabled')}`);
  }
}

Comment thread src/cli/commands/ambient.ts Outdated
],
});
changed = true;
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Duplicated hook-registration block: SessionStart mirrors UserPromptSubmit (MEDIUM, 80%)

The SessionStart orchestrator add-block (lines 112-130) is structurally identical to the UserPromptSubmit preamble add-block (lines 92-110). Both perform the same some(... includes(MARKER)) check, then idempotent add.

This duplication creates a future maintenance burden. The feature KB warns: "Adding a third presence-gate separately… must be added to both functions [and] the partial-state detection logic." This duplication is exactly what makes that fragile.

Fix: Extract a helper to avoid keeping two copies in sync:

function ensureHook(
  settings: Settings, event: 'UserPromptSubmit' | 'SessionStart',
  marker: string, hookName: string, timeout: number, devflowDir: string,
): boolean {
  const present = settings.hooks?.[event]?.some((m) =>
    m.hooks.some((h) => h.command.includes(marker)));
  if (present) return false;
  settings.hooks ??= {};
  settings.hooks[event] ??= [];
  settings.hooks[event]!.push({
    hooks: [{ type: 'command', command: path.join(devflowDir, 'scripts', 'hooks', 'run-hook') + ` ${hookName}`, timeout }],
  });
  return true;
}
// Then:
if (ensureHook(settings, 'UserPromptSubmit', PREAMBLE_HOOK_MARKER, 'preamble', 5, devflowDir)) changed = true;
if (ensureHook(settings, 'SessionStart', ORCHESTRATOR_HOOK_MARKER, 'session-start-orchestrator', 10, devflowDir)) changed = true;

Comment thread src/cli/commands/ambient.ts Outdated
@@ -187,7 +225,16 @@ export const ambientCommand = new Command('ambient')

if (options.status) {
const enabled = hasAmbientHook(settingsContent);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Unguarded JSON.parse crashes on corrupt settings.json (MEDIUM, 80%)

This path calls hasAmbientHook(settingsContent)JSON.parse(input) with no surrounding try/catch. If ~/.claude/settings.json is corrupt (trailing comma, etc.), this throws an uncaught exception and the CLI aborts with a raw stack trace.

The same function guards another parse 15 lines away (line 247-260) with a try/catch and graceful degradation. The primary paths (status/enable/disable) should do the same.

Fix: Parse once upfront and degrade gracefully:

let settingsContent: string;
try {
  settingsContent = await fs.readFile(settingsPath, 'utf-8');
} catch (err) {
  if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;
  // ... handle ENOENT
}

let settings: Settings;
try {
  settings = JSON.parse(settingsContent);
} catch (err) {
  p.log.error(`~/.claude/settings.json is not valid JSON: ${(err as Error).message}`);
  if (options.status) return;
  // ... handle for enable/disable
}

const enabled = hasAmbientHook(settings);
const hasOrchestrator = hasOrchestratorHook(settings);

Both predicates already accept Settings objects, removing the redundant double-parse at lines 227/229 (also addresses the performance optimization concern).

|---|---|
| First word begins `Implement the following plan:` | Fixed devflow:implement handoff directive |
| First word is `/` | Silent exit 0 (slash commands pass through) |
| Anything else (including empty-after-strip) | 2-line orchestrator delegation reminder |

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Dispatch table contradicts code for empty prompts (MEDIUM, 88%)

The KB dispatch table row reads: Anything else (including empty-after-strip) | 2-line orchestrator delegation reminder

But the actual preamble code handles empty-after-strip as its own first branch that emits nothing (silent exit 0):

if [ -z "$HEAD" ]; then
  dbg "EXIT: empty prompt"          # no json_prompt_output — silent
elif [[ "$HEAD" == "Implement the following plan:"* ]]; then ...
elif [[ "$HEAD" == "/"* ]]; then ...
else
  json_prompt_output "..."          # reminder only here
fi

Since this KB is the feature knowledge base that future agents/developers will trust as the model of this hook, the inaccuracy will mislead work.

Fix: Split the table so empty-after-strip is its own row:

| First word begins Implement the following plan: | Fixed devflow:implement handoff directive |
| First char is / | Silent exit 0 (slash commands pass through) |
| Empty after whitespace strip | Silent exit 0 (no output) |
| Anything else | 2-line orchestrator delegation reminder |

Comment thread tests/shell-hooks.test.ts Outdated

// --- 256-window bound ---

it('F12: 300 leading spaces before prefix → no plan handoff (prefix beyond 256-byte window) [AC-F12]', () => {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

AC-F12 test is mislabeled and under-asserts the 256-byte window bound (MEDIUM, 90%)

The test name and comment claim it verifies "prefix beyond 256-byte window", but the input ' '.repeat(300) + 'Implement the following plan: …' doesn't exercise that path.

300 leading spaces make HEAD="${PROMPT:0:256}" all-whitespace, then the leading-whitespace strip collapses HEAD to empty. The hook exits via [ -z "$HEAD" ] (empty-prompt branch) — output is 0 bytes. So the key assertion expect(out).not.toContain('plan handoff') passes only because out === ''; it never tests the actual 256-byte content window.

The genuinely window-bounded case (256+ non-whitespace bytes before the prefix) is unexercised. I verified: 'a'.repeat(260) + 'Implement the following plan: …' fires the reminder (prefix pushed past window), which is the behavior this test claims to verify but doesn't.

Fix: Split into two precise tests:

  1. Whitespace-only head → assert expect(out).toBe('') (this is what AC-F12 actually tests)
  2. New test with non-whitespace padding past byte 256 → assert the reminder template fires, not HANDOFF_TEMPLATE (this is the real window-bound verification)

@dean0x

dean0x commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

Additional Inline Comments Posted

Five high-priority inline comments have been posted on this PR covering the most critical blocking and should-fix findings:

  1. ambient.ts:236 — Status observability gap for orchestrator-only state (MEDIUM, 80%)
  2. ambient.ts:130 — Duplicated hook-registration block needs extraction (MEDIUM, 80%)
  3. ambient.ts:227 — Unguarded JSON.parse crashes on corrupt settings (MEDIUM, 80%)
  4. KNOWLEDGE.md:33 — Dispatch table contradicts code for empty prompts (MEDIUM, 88%)
  5. shell-hooks.test.ts:637 — AC-F12 test mislabeled, under-asserts (MEDIUM, 90%)

Remaining Findings (≥80% confidence, not yet posted as inline)

  • git-marker test coverage (MEDIUM, 88%) — No direct test for subprocess-purity invariant; add suite
  • addAmbientHook asymmetry (LOW, 80%) — Doesn't sweep stale session-start-classification hook on enable/repair
  • ambient.ts:113 inline shadow (LOW, 80%) — Local hasOrchestratorHook shadows module-level function
  • shell-hooks.test.ts:947 (LOW, 80%) — 4096-byte charter boundary (exactly 4096) untested; add boundary case

Summary Assessment

Status: APPROVED_WITH_CONDITIONS

Blockers to address before merge:

  • README.md lines 19 & 44 (CRITICAL, 97%) — stale keyword/structured-plan prose
  • architecture.ts status observability (MEDIUM, 80%) — orchestrator-only state reporting
  • KNOWLEDGE.md dispatch table (MEDIUM, 88%) — empty-prompt contradiction

Should-fix items (safe to defer post-merge):

  • Duplicated hook registration → extract helper
  • Unguarded JSON.parse → parse upfront with try/catch
  • AC-F12 test split → verify actual 256-byte window
  • git-marker test coverage → add direct tests
  • Minor TypeScript/Regression/Testing items

All findings detailed in the corresponding inline comments and initial summary comment.


Review completed by Claude Code devflow:comment-pr

dean0x and others added 7 commits July 5, 2026 00:30
Three stale passages updated to reflect the PR #251 ambient redesign
(applies ADR-004, applies ADR-003):

- README.md line 19: replace "detects when you paste a structured plan"
  with charter-injection description; drop EDD reference, retain TDD.
- README.md line 44: rewrite "Ambient intelligence" bullet — remove
  first-word keyword dispatch prose; describe charter injection,
  delegation reminder, plan-handoff fast-path, and slash pass-through.
- .devflow/features/ambient-orchestrator/KNOWLEDGE.md: fix preamble
  dispatch table — add empty-after-strip row (silent exit 0, matching
  the `[ -z "$HEAD" ]` branch in scripts/hooks/preamble); reorder rows
  to match code dispatch order; remove stale parenthetical from the
  "Anything else" row.
- docs/reference/file-organization.md: update plugin count 21 → 22.
Issue 1 (git-marker): replace `||`/`&&` chain at the loop-termination guard
with an explicit `if` — semantics are unchanged (left-associative precedence
was already correct) but the explicit form removes the readability footgun.

Issue 2 (session-start-orchestrator): add hook-log-init sourcing and a
`log "Injecting charter (N chars)"` call to match the observability pattern
both sibling SessionStart hooks (session-start-context, session-start-memory)
already follow. Applies ADR-004.

Issue 3 (preamble): add a cross-reference comment beside the model-tier
taxonomy in the orchestrator reminder string, pointing to orchestrator-
charter.md as the authoritative full definition. The charter already carries
the reciprocal cross-reference; this closes the asymmetry. Avoids PF-001.

All 132 shell-hook tests pass.
…classification sweep

Issue 1 — parse settings.json once with try/catch before any branch that
needs it; pass the already-parsed Settings object to hasAmbientHook /
hasOrchestratorHook in --status, eliminating double-parse and crash risk
on a corrupt settings.json.

Issue 2 — extend --status else-branch to check hasOrchestratorHook; shows
"(partial — run devflow ambient --enable to repair)" when the orchestrator
SessionStart hook is present but preamble is absent, matching the hint
surfaced for the mirror partial state.

Issue 3 — extract ensureHook() helper, collapsing the structurally-identical
UserPromptSubmit and SessionStart add-blocks; eliminates the const
hasOrchestratorHook local variable that shadowed the module-level function.

Issue 4 — add symmetric filterHookEntries(…, isClassification) sweep to
addAmbientHook, matching removeAmbientHook behaviour; enables --enable to
repair installs left with a stale session-start-classification hook.

Two regression tests cover the new classification sweep in addAmbientHook.

Co-Authored-By: Claude <noreply@anthropic.com>
…-byte boundary

Batch-3 test fixes for shell-hooks.test.ts.

- Issue 1 (F12 mislabeled/vacuous): split into F12a (300 spaces → HEAD
  collapses to empty → silent exit, asserting output is exactly '') and F12b
  ('a'.repeat(260) + prefix → prefix past byte 256 → reminder, not handoff).
  The original test passed vacuously on empty output; F12b now pins the actual
  256-byte window-bound behavior.

- Issue 2 (git-marker no direct test): add describe('git-marker helper')
  with 7 behavioral tests (repo root, nested subdir, .git-as-file worktree
  style, non-git dir, empty string, '/', >64-level bound). Also add P1b
  source scan to catch a reintroduced git subprocess in git-marker itself
  (previously only preamble source was scanned). Regex uses `\bgit\s+\w`
  to detect git-as-command without false-matching the `.git` path literal.

- Issue 3 (charter boundary): add AC-F10 exact-4096-byte-accept test. The
  hook guard is `-gt 4096`, so exactly 4096 bytes must be injected; only the
  4097-reject case was previously tested.

- Issue 4 (template triplication): extract HANDOFF_TEMPLATE and
  REMINDER_TEMPLATE to tests/fixtures/ambient-templates.ts and import in
  both shell-hooks.test.ts and tests/integration/ambient-activation.test.ts.
  Eliminates drift risk between shell-hook unit assertions and integration
  systemPrompt simulation.

- Issue 5 (noGitDir guard): add beforeAll that probes os.tmpdir() via
  df_has_git_marker; throws with a clear message if tmpdir has a .git
  ancestor, making the assumption explicit and failing fast instead of
  producing confusing assertion failures.

applies ADR-003 (end-state only: no tombstone residue in test rewrites)
Co-Authored-By: Claude <noreply@anthropic.com>
…lay + predicate style

- Convert 4 arrow-function predicates (isLegacy, isAmbient, isClassification,
  isOrchestrator) to named function declarations with explicit return types,
  following the project's function-keyword standard.
- Replace `let changed = ... || changed` accumulation in addAmbientHook with
  named boolean variables (removedLegacy, removedClassification, addedPreamble,
  addedOrchestrator), matching the cleaner pattern already used in removeAmbientHook.
- Collapse the status display from two nested branches (each calling
  hasOrchestratorHook independently) to a single evaluation: extract both
  enabled and hasOrchestrator before branching, derive the shared repairHint
  string once, and apply it in both the enabled and disabled log lines.
Refreshes KB with five targeted changes from the resolve session:
state-machine table now shows exact --status repair hint text; ensureHook
helper + symmetric classification sweep + up-front settings parsing captured;
session-start-orchestrator hook-log-init sourcing noted; preamble routing-table
cross-reference comment documented; tests/fixtures/ambient-templates.ts added
to Key Files.
Drop the disable-mouse-clicks entry from the flag registry, its test
block, and the CLAUDE.md flags doc (21 -> 20 flags). No migration:
existing installs clean up manually.
@dean0x dean0x merged commit 994d556 into main Jul 5, 2026
2 checks passed
@dean0x dean0x deleted the feat/ambient-orchestrator-charter branch July 5, 2026 14:06
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