Commit graph

77 commits

Author SHA1 Message Date
ACJLabsDev
235a8ce202
Add Star History Chart to README.md (#1229) 2026-04-20 19:43:52 +03:00
Cole Medin
cb44b96f7b
feat(providers/pi): interactive flag binds UIContext for extensions (#1299)
* feat(providers/pi): interactive flag binds UIContext for extensions

Adds `interactive: true` opt-in to Pi provider (in `.archon/config.yaml`
under `assistants.pi`) that binds a minimal `ExtensionUIContext` stub to
each session. Without this, Pi's `ExtensionRunner.hasUI()` reports false,
causing extensions like `@plannotator/pi-extension` to silently auto-approve
every plan instead of opening their browser review UI.

Semantics: clamped to `enableExtensions: true` — no extensions loaded
means nothing would consume `hasUI`, so `interactive` alone is silently
dropped. Stub forwards `notify()` to Archon's event stream; interactive
dialogs (select/confirm/input/editor/custom) resolve to undefined/false;
TUI-only setters (widgets/headers/footers/themes) no-op. Theme access
throws with a clear diagnostic — Pi's theme singleton is coupled to its
own `Symbol.for()` registry which Archon doesn't own.

Trust boundary: only binds when the operator has explicitly enabled
both flags. Extensions gated on `ctx.hasUI` (plannotator and similar)
get a functional UI context; extensions that reach for TUI features
still fail loudly rather than rendering garbage.

Includes smoke-test workflow documenting the integration surface.
End-to-end plannotator UI rendering requires plan-mode activation
(Pi `--plan` CLI flag or `/plannotator` TUI slash command) which is
out of reach for programmatic Archon sessions — manual test only.

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

* fix(providers/pi): end-to-end interactive extension UI

Three fixes that together get plannotator's browser review UI to actually
render from an Archon workflow and reach the reviewer's browser.

1. Call resourceLoader.reload() when enableExtensions is true.
   createAgentSession's internal reload is gated on `!resourceLoader`, so
   caller-supplied loaders must reload themselves. Without this,
   getExtensions() returns the empty default, no ExtensionRunner is built,
   and session.extensionRunner.setFlagValue() silently no-ops.

2. Set PLANNOTATOR_REMOTE=1 in interactive mode.
   plannotator-browser.ts only calls ctx.ui.notify(url) when openBrowser()
   returns { isRemote: true }; otherwise it spawns xdg-open/start on the
   Archon server host — invisible to the user and untestable from bash
   asserts. From the workflow runner's POV every Archon execution IS
   remote; flipping the heuristic routes the URL through notify(), which
   the ExtensionUIContext stub forwards into the event stream. Respect
   explicit operator overrides.

3. notify() emits as assistant chunks, not system chunks.
   The DAG executor's system-chunk filter only forwards warnings/MCP
   prefixes, and only assistant chunks accumulate into $nodeId.output.
   Emitting as assistant makes the URL available both in the user's
   stream and in downstream bash/script nodes via output substitution.

Plus: extensionFlags config pass-through (equivalent to `pi --plan` on the
CLI) applied via ExtensionRunner.setFlagValue() BEFORE bindExtensions
fires session_start, so extensions reading flags in their startup handler
actually see them. Also bind extensions with an empty binding when
enableExtensions is on but interactive is off, so session_start still
fires for flag-driven but UI-less extensions.

Smoke test (.archon/workflows/e2e-plannotator-smoke.yaml) uses
openai-codex/gpt-5.4-mini (ChatGPT Plus OAuth compatible) and bumps
idle_timeout to 600000ms so plannotator's server survives while a human
approves in the browser.

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

* refactor(providers/pi): keep Archon extension-agnostic

Remove the plannotator-specific PLANNOTATOR_REMOTE=1 env var write from
the Pi provider. Archon's provider layer shouldn't know about any
specific extension's internals. Document the env var in the plannotator
smoke test instead — operators who use plannotator set it via their shell
or per-codebase env config.

Workflow smoke test updated with:
- Instructions for setting PLANNOTATOR_REMOTE=1 externally
- Simpler assertion (URL emission only) — validated in a real
  reject-revise-approve run: reviewer annotated, clicked Send Feedback,
  Pi received the feedback as a tool result, revised the plan (added
  aria-label and WCAG contrast per the annotation), resubmitted, and
  reviewer approved. Plannotator's tool result signals approval but
  doesn't return the plan text, so the bash assertion now only checks
  that the review URL reached the stream (not that plan content flowed
  into \$nodeId.output — it can't).
- Known-limitation note documenting the tool-result shape so downstream
  workflow authors know to Write the plan separately if they need it.

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

* chore(providers/pi): keep e2e-plannotator-smoke workflow local-only

The smoke test is plannotator-specific (calls plannotator_submit_plan,
expects PLAN.md on disk, requires PLANNOTATOR_REMOTE=1) and is better
kept out of the PR while the extension-agnostic infra lands.

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

* style(providers/pi): trim verbose inline comments

Collapse multi-paragraph SDK explanations to 1-2 line "why" notes across
provider.ts, types.ts, ui-context-stub.ts, and event-bridge.ts. No
behavior change.

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

* fix(providers/pi): wire assistants.pi.env + theme-proxy identity

Two end-to-end fixes discovered while exercising the combined
plannotator + @pi-agents/loop smoke flow:

- PiProviderDefaults gains an optional `env` map; parsePiConfig picks
  it up and the provider applies it to process.env at session start
  (shell env wins, no override). Needed so extensions like plannotator
  can read PLANNOTATOR_REMOTE=1 from config.yaml without requiring a
  shell export before `archon workflow run`.

- ui-context-stub theme proxy returns identity decorators instead of
  throwing on unknown methods. Styled strings flow into no-op
  setStatus/setWidget sinks anyway, so the throw was blocking
  plannotator_submit_plan after HTTP approval with no benefit.

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

* fix(providers/pi): flush notify() chunks immediately in batch mode

Batch-mode adapters (CLI) accumulate assistant chunks and only flush on
node completion. That broke plannotator's review-URL flow: Pi's notify()
emitted the URL as an assistant chunk, but the user needed the URL to
POST /api/approve — which is what unblocks the node in the first place.

Adds an optional `flush` flag on assistant MessageChunks. notify() sets
it, and the DAG executor drains pending batched content before surfacing
the flushed chunk so ordering is preserved.

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

* docs: mention Pi alongside Claude and Codex in README + top-level docs

The AI assistants docs page already covers Pi in depth, but the README
architecture diagram + docs table, overview "Further Reading" section,
and local-deployment .env comment still listed only Claude/Codex.

Left feature-specific mentions alone where Pi genuinely lacks support
(e.g. structured output — Claude + Codex only).

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

* docs: note Pi structured output (best-effort) in matrix + workflow docs

Pi gained structured output support via prompt augmentation + JSON
extraction (see packages/providers/src/community/pi/capabilities.ts).
Unlike Claude/Codex, which use SDK-enforced JSON mode, Pi appends the
schema to the prompt and parses JSON out of the result text (bare or
fenced). Updates four stale references that still said Claude/Codex-only:

- ai-assistants.md capabilities matrix
- authoring-workflows.md (YAML example + field table)
- workflow-dag.md skill reference
- CLAUDE.md DAG-format node description

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

* feat(providers/pi): default extensions + interactive to on

Extensions (community packages like @plannotator/pi-extension and
user-authored ones) are a core reason users pick Pi. Defaulting
enableExtensions and interactive to false previously silenced installed
extensions with no signal, leading to "did my extension even load?"
confusion.

Opt out in .archon/config.yaml when you want the prior behavior:

  assistants:
    pi:
      enableExtensions: false   # skip extension discovery entirely
      # interactive: false       # load extensions, but no UI bridge

Docs gain a new "Extensions (on by default)" section in
getting-started/ai-assistants.md that documents the three config
surfaces (extensionFlags, env, workflow-level interactive) and uses
plannotator as a concrete walk-through example.

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

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 07:37:40 -05:00
Anjishnu Sengupta
c495175d94
Fix formatting in README.md (#1059) 2026-04-20 09:59:26 +03:00
Cole Medin
d535c832e3
feat(telemetry): anonymous PostHog workflow-invocation tracking (#1262)
* feat(telemetry): add anonymous PostHog workflow-invocation tracking

Emits one `workflow_invoked` event per run with workflow name/description,
platform, and Archon version. Uses a stable random UUID persisted to
`$ARCHON_HOME/telemetry-id` for distinct-install counting, with
`$process_person_profile: false` to stay in PostHog's anonymous tier.

Opt out with `ARCHON_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`. Self-host
via `POSTHOG_API_KEY` / `POSTHOG_HOST`.

Closes #1261

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

* test(telemetry): stop leaking test events to production PostHog

The `telemetry-id preservation` test exercised the real capture path with
the embedded production key, so every `bun run validate` published a
tombstone `workflow_name: "w"` event. Redirect POSTHOG_HOST to loopback
so the flush fails silently; bump test timeout to accommodate the
retry-then-give-up window.

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

* fix(telemetry): silence posthog-node stderr leak on network failure

The PostHog SDK's internal logFlushError() writes 'Error while flushing
PostHog' directly to stderr via console.error on any network or HTTP
error, bypassing logger config. For a fire-and-forget telemetry path
this leaked stack traces to users' terminals whenever PostHog was
unreachable (offline, firewalled, DNS broken, rate-limited).

Pass a silentFetch wrapper to the PostHog client that masks failures as
fake 200 responses. The SDK never sees an error, so it never logs.
Original failure is still recorded at debug level for diagnostics.

Side benefit: shutdown is now fast on network failure (no retry loop),
so offline CLI commands no longer hang ~10s on exit.

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

* test(telemetry): make id-preservation test deterministic

Replace the fire-and-forget capture + setTimeout + POSTHOG_HOST-loopback
dance with a direct synchronous call to getOrCreateTelemetryId(). Export
the function with an @internal marker so tests can exercise the id path
without spinning up the PostHog client. No network, no timer, no flake.

Addresses CodeRabbit feedback on #1262.

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

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-16 13:45:55 -05:00
Rasmus Widing
81859d6842
fix(providers): replace Claude SDK embed with explicit binary-path resolver (#1217)
* feat(providers): replace Claude SDK embed with explicit binary-path resolver

Drop `@anthropic-ai/claude-agent-sdk/embed` and resolve Claude Code via
CLAUDE_BIN_PATH env → assistants.claude.claudeBinaryPath config → throw
with install instructions. The embed's silent failure modes on macOS
(#1210) and Windows (#1087) become actionable errors with a documented
recovery path.

Dev mode (bun run) remains auto-resolved via node_modules. The setup
wizard auto-detects Claude Code by probing the native installer path
(~/.local/bin/claude), npm global cli.js, and PATH, then writes
CLAUDE_BIN_PATH to ~/.archon/.env. Dockerfile pre-sets CLAUDE_BIN_PATH
so extenders using the compiled binary keep working. Release workflow
gets negative and positive resolver smoke tests.

Docs, CHANGELOG, README, .env.example, CLAUDE.md, test-release and
archon skills all updated to reflect the curl-first install story.

Retires #1210, #1087, #1091 (never merged, now obsolete).
Implements #1176.

* fix(providers): only pass --no-env-file when spawning Claude via Bun/Node

`--no-env-file` is a Bun flag that prevents Bun from auto-loading
`.env` from the subprocess cwd. It is only meaningful when the Claude
Code executable is a `cli.js` file — in which case the SDK spawns it
via `bun`/`node` and the flag reaches the runtime.

When `CLAUDE_BIN_PATH` points at a native compiled Claude binary (e.g.
`~/.local/bin/claude` from the curl installer, which is Anthropic's
recommended default), the SDK executes the binary directly. Passing
`--no-env-file` then goes straight to the native binary, which
rejects it with `error: unknown option '--no-env-file'` and the
subprocess exits code 1.

Emit `executableArgs` only when the target is a `.js` file (dev mode
or explicit cli.js path). Caught by end-to-end smoke testing against
the curl-installed native Claude binary.

* docs: record env-leak validation result in provider comment

Verified end-to-end with sentinel `.env` and `.env.local` files in a
workflow CWD that the native Claude binary (curl installer) does not
auto-load `.env` files. With Archon's full spawn pathway and parent
env stripped, the subprocess saw both sentinels as UNSET. The
first-layer protection in `@archon/paths` (#1067) handles the
inheritance leak; `--no-env-file` only matters for the Bun-spawned
cli.js path, where it is still emitted.

* chore(providers): cleanup pass — exports, docs, troubleshooting

Final-sweep cleanup tied to the binary-resolver PR:

- Mirror Codex's package surface for the new Claude resolver: add
  `./claude/binary-resolver` subpath export and re-export
  `resolveClaudeBinaryPath` + `claudeFileExists` from the package
  index. Renames the previously single `fileExists` re-export to
  `codexFileExists` for symmetry; nothing outside the providers
  package was importing it.
- Add a "Claude Code not found" entry to the troubleshooting reference
  doc with platform-specific install snippets and pointers to the
  AI Assistants binary-path section.
- Reframe the example claudeBinaryPath in reference/configuration.md
  away from cli.js-only language; it accepts either the native binary
  or cli.js.

* test+refactor(providers, cli): address PR review feedback

Two test gaps and one doc nit from the PR review (#1217):

- Extract the `--no-env-file` decision into a pure exported helper
  `shouldPassNoEnvFile(cliPath)` so the native-binary branch is unit
  testable without mocking `BUNDLED_IS_BINARY` or running the full
  sendQuery pathway. Six new tests cover undefined, cli.js, native
  binary (Linux + Windows), Homebrew symlink, and suffix-only matching.
  Also adds a `claude.subprocess_env_file_flag` debug log so the
  security-adjacent decision is auditable.

- Extract the three install-location probes in setup.ts into exported
  wrappers (`probeFileExists`, `probeNpmRoot`, `probeWhichClaude`) and
  export `detectClaudeExecutablePath` itself, so the probe order can be
  spied on. Six new tests cover each tier winning, fall-through
  ordering, npm-tier skip when not installed, and the
  which-resolved-but-stale-path edge case.

- CLAUDE.md `claudeBinaryPath` placeholder updated to reflect that the
  field accepts either the native binary or cli.js (the example value
  was previously `/absolute/path/to/cli.js`, slightly misleading now
  that the curl-installer native binary is the default).

Skipped from the review by deliberate scope decision:

- `resolveClaudeBinaryPath` async-with-no-await: matches Codex's
  resolver signature exactly. Changing only Claude breaks symmetry;
  if pursued, do both providers in a separate cleanup PR.
- `isAbsolute()` validation in parseClaudeConfig: Codex doesn't do it
  either. Resolver throws on non-existence already.
- Atomic `.env` writes in setup wizard: pre-existing pattern this PR
  touched only adjacently. File as separate issue if needed.
- classifyError branch in dag-executor for setup errors: scope creep.
- `.env.example` "missing #" claim: false positive (verified all
  CLAUDE_BIN_PATH lines have proper comment prefixes).

* fix(test): use path.join in Windows-compatible probe-order test

The "tier 2 wins (npm cli.js)" test hardcoded forward-slash path
comparisons, but `path.join` produces backslashes on Windows. Caused
the Windows CI leg of the test suite to fail while macOS and Linux
passed. Use `path.join` for both the mock return value and the
expectation so the separator matches whatever the platform produces.
2026-04-14 17:56:37 +03:00
Rasmus Widing
36bd9cff8f
feat: add archon serve command for one-command web UI install (#1011)
* Investigate issue #978: one-command web UI install via archon serve

* feat: add `archon serve` command for one-command web UI install (#978)

Extract `startServer(opts)` from server's monolithic `main()` into an
exported function with `ServerOptions` (webDistPath, port,
skipPlatformAdapters). Add `import.meta.main` guard so the file still
works as a standalone script for `bun dev`.

Create `archon serve` CLI command that lazily downloads a pre-built
web UI tarball from GitHub releases on first run, verifies SHA-256
checksum, extracts atomically, then starts the full server. Cached
per version in `~/.archon/web-dist/<version>/`.

Update release CI to build the web UI, package it as
`archon-web.tar.gz`, and include in release checksums.

* fix: address review findings for archon serve command

- Validate --port range (1-65535) and reject NaN before any other checks
- Capture tar stderr for actionable extraction error messages
- Add structured logging (download_started/download_failed/server_start_failed)
- Post-extraction sanity check for index.html
- Wrap renameSync with error context and tmpDir cleanup
- Wrap fetch() calls to preserve URL context on network errors
- Validate parseChecksum returns 64 hex chars
- Set skipPlatformAdapters: true for standalone web UI mode
- Improve ServerOptions/ServeOptions JSDoc
- Move consoleErrorSpy cleanup to afterEach in tests
- Add tests for port validation and malformed hash rejection
- Update CLAUDE.md: CLI section, directory tree, package descriptions
- Update README.md: mention archon serve for binary installs
- Update docs-web: CLI reference, archon-directories

* refactor: simplify serve command implementation

- Use BUNDLED_IS_BINARY directly instead of version === 'dev' sentinel
- Extract toError() helper for repeated error normalization
- Use dirname() instead of manual substring/lastIndexOf
- Extract cleanupAndThrow() for repeated rmSync + throw pattern
- Add missing assertion on port 0 test for consistency
2026-04-10 13:33:47 +03:00
Cole Medin
bcd84598b7 docs: unify getting started flow and improve What It Looks Like intro
- Shared "Start Using Archon" section after both setup paths
- Remove duplicated usage instructions from each path
- Full Setup ends at the wizard, Quick Install ends at the binary
- Both converge to "go to your project, open Claude Code, start working"
- Better intro line for the workflow example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:30:51 -05:00
Cole Medin
029807097a docs: rework README - better workflow example, clearer getting started
What It Looks Like: Replace flat command-list workflow with one that
shows all differentiators - AI loops, deterministic bash nodes, human
approval gates, fresh context. Show usage as a Claude Code conversation
instead of a CLI command, since that's how most people will use Archon.

Getting Started: Lead with Full Setup (guided wizard) as the recommended
path. Move Quick Install (CLI binary) below as the power-user shortcut.
Add decision-helper callout so users know which path to take.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:26:31 -05:00
Cole Medin
3cd1f7a9d9 docs: restructure README with two clear quickstart paths
Reorganize README flow: intro → why → what it looks like → previous
version → quickstart with two options.

Option A: CLI binary install (30 seconds, for terminal-first users).
Option B: Full setup with guided wizard (5 min, for web UI and
platform integrations).

Removes the separate Install section that overlapped with Quickstart.
Moves Web UI, workflows, architecture, and platform sections after
the quickstart so users get running before reading reference material.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:18:25 -05:00
Cole Medin
8bf26e1380 docs: add GitHub trending badge to README
Archon was #1 trending repo on GitHub. Add the Trendshift badge
between the tagline and the status badges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:02:05 -05:00
Cole Medin
f80d187d24 docs: add Archon logo and polish README header
Add logo to assets/ and update README with centered header,
tagline, and badges for a professional open-source presentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:01:25 -05:00
Cole Medin
32d4787e96 docs: replace em dashes and move previous version section higher
Replace all em dashes with regular dashes in README. Move the
"Previous Version" section to right before Quickstart so existing
users find it immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:20:17 -05:00
Cole Medin
41067c475d docs: add link to archived previous version of Archon
Points users to the archive/v1-task-management-rag branch for
the original Python-based Archon (task management + RAG tool).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:16:16 -05:00
Cole Medin
c291f6f97a chore: fix remaining references and update README for open-source launch
- Update Dockerfile.user.example image refs (dynamous → coleam00/archon)
- Update docker-compose.yml image name (remote-coding-agent → archon)
- Fix clone URL and dir name in Book of Archon first-five-minutes
- Update prompt-builder example project name
- Add elevator pitch to README intro
- Fix all README doc links to point to archon.diy (old docs/ dir was deleted)
- Add install scripts to docs-web public dir for GitHub Pages serving

Relates to #980

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:03:13 -05:00
Cole Medin
ae346c2a67 feat: prepare for open-source migration to coleam00/Archon
- Replace all dynamous-community/remote-coding-agent references with coleam00/Archon
- Replace all ghcr.io/dynamous-community/remote-coding-agent with ghcr.io/coleam00/archon
- Change license from proprietary Dynamous to MIT
- Fix cd directory name in docs (remote-coding-agent → Archon)
- Remove hardcoded local paths from skills and docs
- Add Windows x64 binary to release pipeline (cross-compiled from Linux)
- Add --minify --bytecode flags to binary compilation
- Create PowerShell install script (scripts/install.ps1)
- Fix isBinaryBuild() detection for Bun 1.3.5+ (use import.meta.dir virtual FS check)
- Scaffold Astro Starlight docs site at website/ (Astro 6 + Starlight 0.38)
- Add deploy-docs.yml workflow for GitHub Pages
- Update test.yml branch triggers (develop → dev)
- Add install section with curl/PowerShell/Homebrew/Docker to README
- Add badges and archon.diy docs link to README
- Create SECURITY.md with vulnerability disclosure policy
- Update CONTRIBUTING.md for public audience
- Add website/ and eslint ignores for Astro-generated files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 10:47:22 -05:00
Cole Medin
51a2702699 fix: address PR #938 review findings — interactive loop correctness and coverage
Fixed:
- H1: Return 'completed' (not 'failed') from interactive loop gate to prevent
  false "Some DAG nodes failed" warnings in multi-node workflows
- H2: Check safeSendMessage return value before pausing — fail the node with a
  clear error if the gate message failed to deliver, preventing orphaned paused runs
- H3: Extend isApprovalTransition guard in updateWorkflowRun to cover loop_user_input
  metadata key, preventing completed_at from being stamped on resumable loop runs
- M1: Add isApprovalContext() type guard in workflow-run.ts; replace unsafe casts
  in dag-executor.ts and command-handler.ts
- M4/L3: Update comments to accurately reflect completed-return semantics and
  metadata merge requirement
- L1: Pass '' instead of undefined for $LOOP_USER_INPUT on iterations after first
- L4: Update $LOOP_USER_INPUT docstring to clarify first-iteration-only scoping
- Gap6: Add archon-piv-loop to bundled-defaults.ts so it's available in binary builds

Tests added:
- H4: /workflow approve interactive_loop branch tests in command-handler.test.ts
  (routing, approval_received event, no node_completed, error cases)
- M2: superRefine validation tests in loader.test.ts (reject interactive without
  gate_message; accept valid interactive loop)
- M3: loader warning test for interactive loop in non-interactive workflow

Docs updated:
- H5: docs/loop-nodes.md — add interactive/gate_message fields, $LOOP_USER_INPUT
  variable, and interactive loop pattern section
- M5: docs/authoring-workflows.md — note interactive loops require workflow-level
  interactive: true
- L5: README.md — add archon-piv-loop row, update count 16→17
- L6: docs/authoring-workflows.md — update count 16→17
- L7: CLAUDE.md — add $LOOP_USER_INPUT to variable substitution table

Bundled defaults test updated: count 10→11 to reflect archon-piv-loop addition

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 11:17:56 -05:00
Cole Medin
d5976802fd
docs: consolidate QUICKSTART.md and getting-started-cli.md into single guide (#878)
* docs: consolidate QUICKSTART.md and getting-started-cli.md into single guide (#806)

Two overlapping getting-started docs (QUICKSTART.md for Web UI, getting-started-cli.md
for CLI) created confusion for new users. Neither was complete alone.

Changes:
- Merged both docs into docs/getting-started.md with "Choose Your Path" (Web UI vs CLI)
- Deleted QUICKSTART.md (content preserved in unified guide)
- Renamed docs/getting-started-cli.md to docs/getting-started.md
- Updated all references in README.md, adapter docs, and new-developer-guide.md
- Added troubleshooting section from QUICKSTART.md (previously missing from CLI guide)
- Added .env setup section with note about CLI-only vs server usage

Fixes #806

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

* fix: format files and fix test imports from validation

- Auto-format workflows.test.ts and api.ts (Prettier)
- Fix api.conversations.test.ts: Hono() → OpenAPIHono({ defaultHook: validationErrorHook })

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

* fix: restore removed dependencies and scripts in @archon/web

Restores zustand, react-resizable-panels, openapi-typescript, and
generate:types script that were accidentally removed. Removes
@archon/workflows dep that violates CLAUDE.md architectural boundary.
Restores src/stores/ test batch in test script.

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

* chore: remove spurious non-docs changes from PR

Revert bun.lock, packages/web/package.json, packages/core/src/db/workflows.test.ts,
packages/server/src/routes/api.conversations.test.ts, and packages/server/src/routes/api.ts
to match dev. This docs-only PR should contain no code or dependency changes.

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

* chore: restore formatting of non-docs files to exactly match dev

These files were reformatted by the pre-commit prettier hook in the previous commit.
Restore them byte-for-byte from dev so this docs-only PR has zero code changes.

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

* fix(docs): correct broken anchor links in getting-started guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:25:58 -07:00
Cole Medin
9244fd80df
docs: document agent-browser as optional dependency for E2E workflows (#876)
* docs: document agent-browser as optional dependency for E2E workflows (#787)

agent-browser is used by archon-validate-pr, validate-ui skill, and replicate-issue
skill but installation requirements were not documented. Users hitting these workflows
got confusing errors.

Changes:
- Added installation section to .claude/skills/agent-browser/SKILL.md
- Created docs/e2e-testing.md general cross-platform setup guide
- Added agent-browser as optional dependency in README.md prerequisites
- Added E2E troubleshooting section to docs/troubleshooting.md
- Added cross-reference from docs/e2e-testing-wsl.md to general guide

Fixes #787

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

* fix: format + fix test references for OpenAPIHono migration

Prettier auto-formatted two files and fixed 5 test cases that referenced
`Hono` instead of `OpenAPIHono` after the OpenAPI route refactor.

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

* fix(docs): accurately describe agent-browser fallback as prompt instruction

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 16:24:46 -05:00
Cole Medin
dafa0f9082
docs: restructure setup flow, fix workflow tables, rename getting-started (#820)
* docs: update README, getting-started, and authoring-workflows for default workflows (#789)

Documentation was stale: workflow count was wrong (16→17), several workflows
were missing from tables, router auto-selection was undocumented, and examples
used deprecated sequential/loop syntax instead of DAG nodes.

Changes:
- README.md: Fix workflow count to 17, update table with all key workflows,
  add defaults-as-templates guidance, mention router auto-selection
- docs/getting-started.md: Complete workflow table (all 17), add auto-selection
  explanation, convert custom workflow example to DAG syntax
- docs/authoring-workflows.md: Remove sequential (steps:) and standalone loop
  sections, convert all examples to DAG nodes: syntax, add deprecation notice,
  add "Using defaults as templates" guidance, update summary

Fixes #789

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

* fix(docs): address review findings — complete workflow table and fix stale step refs

- Add 6 missing workflows to README table (now lists all 17)
- Replace stale "step" references with "node" terminology in authoring-workflows.md
- Update retry notification example to match DAG executor output
- Fix artifact chain table to reference node name instead of "step 1"

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

* docs(readme): remove Option A (run from Archon repo) — only target repo usage

* docs: restructure setup flow — wizard-first, rename getting-started

- README: Make the setup wizard the primary path (clone → claude → "set up archon")
- README: Add clear "Start Using Archon" section with exit/cd/claude steps
- README: Add note to always run from target repo, not Archon repo
- README: Link to CLI and Web UI guides as alternative paths
- Rename docs/getting-started.md → docs/getting-started-cli.md
- Update all cross-references (7 files) to new filename

* docs: fix workflow count (17 → 16) in authoring-workflows.md

* docs: fix loop node YAML nesting and add fresh_context in authoring-workflows

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Rasmus Widing <rasmus.widing@gmail.com>
2026-03-26 12:54:04 +02:00
Rasmus Widing
ef04321eef
refactor(workflows)!: remove sequential execution mode, DAG becomes sole format (#805)
* refactor(workflows)!: remove sequential execution mode, DAG becomes sole format

Remove the steps-based (sequential) workflow execution mode entirely.
All workflows now use the nodes-based (DAG) format exclusively.

- Convert 8 sequential default workflows to DAG format
- Delete archon-fix-github-issue sequential (DAG version absorbs triggers)
- Remove SingleStep, ParallelBlock, StepWorkflow types and guards
- Gut executor.ts from ~2200 to ~730 lines (remove sequential loop)
- Remove step_started/completed/failed and parallel_agent_* events
- Remove logStepStart/Complete and logParallelBlockStart/Complete
- Delete SequentialEditor, StepProgress, ParallelBlockView components
- Remove sequential mode from workflow builder and execution views
- Delete executor.test.ts (4395 lines), update ~45 test fixtures
- Update CLAUDE.md and docs to reflect DAG-only format

BREAKING CHANGE: Workflows using `steps:` format are no longer supported.
Convert to `nodes:` (DAG) format. The loader provides a clear error message
directing users to the migration guide.

* fix: address review findings — guard errors, remove dead code, add tests

- Guard logNodeSkip/logWorkflowError against filesystem errors in dag-executor
- Move mkdir(artifactsDir) inside try-catch with user-friendly error
- Remove startFromStep dead parameter from executeWorkflow signature
- Remove isDagWorkflow() tautology and all callers (20+ sites)
- Remove dead BuilderMode/mode state from frontend components
- Remove vestigial isLoop, selectedStep, stepIndex, step_index fields
- Remove "DAG" prefix from user-facing resume/error messages
- Fix 5 stale docs (README, getting-started, authoring-commands, web adapter)
- Update event-emitter tests to use node events instead of removed step events
- Add executor-shared.test.ts (12 tests) for substituteWorkflowVariables
- Add executor.test.ts (11 tests) for concurrent-run, model resolution, resume

* fix(workflows): add migration guide, port preamble tests, improve error message

- Add docs/sequential-dag-migration-guide.md with 3 conversion patterns
  (single step, chain with clearContext, parallel block) and a Claude Code
  migration command for automated conversion
- Update loader error message to point to migration guide and include
  ready-to-run claude command
- Port 8 preamble tests from deleted executor.test.ts to new
  executor-preamble.test.ts: staleness detection (3), concurrent-run
  guard (3), DAG resume (2)

Addresses review feedback from #805.

* fix(workflows): update loader test to match new error message wording

* fix: address review findings — fail stuck runs, remove dead code, fix docs

- Mark workflow run as failed when artifacts mkdir fails (prevents
  15-min concurrent-run guard block)
- Remove vestigial totalSteps from WorkflowStartedEvent and executor
- Delete dead WorkflowToolbar.tsx (369 lines, no importers)
- Remove stepIndex prop from StepLogs (always 0, label now "Node logs")
- Restore cn() in StatusBar for consistent conditional classes
- Promote resume-check log to error, add errorType to failure logs
- Remove ghost $PLAN/$IMPLEMENTATION_SUMMARY from docs (never implemented)
- Update workflows.md rules to DAG-only format
- Fix migration guide trigger_rule example
- Clean up blank-line residues and stale comments

* fix: resolve rebase conflicts with #729 (forkSession) and #730 (dashboard)

- Remove sequential forkSession/persistSession code from #729 (dead after
  sequential removal)
- Fix loader type narrowing for DagNode context field
- Update dashboard components from #730 to use dagNodes instead of steps
- Remove WorkflowStepEvent/ParallelAgentEvent from dashboard SSE hook
2026-03-26 11:27:34 +02:00
Cole Medin
671004528b docs: add prerequisites section to README quickstart
Add collapsible prerequisites with install commands for Node.js,
GitHub CLI, and Claude Code above the quickstart section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 08:49:05 -05:00
Cole Medin
f6680248bc docs: add "Using Archon on Your Project" and "Web UI" sections to README
- Add section bridging installation to usage: two paths (from Archon repo
  or copy skill to your repo), auto-registration, agent-first philosophy
- Add standalone Web UI section with key pages (Chat, Dashboard, Workflow
  Builder, Execution) and monitoring hub callout (all-platform visibility)
- Add workflow count note (16 total) to "What Can You Automate?" table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:13:22 -05:00
Rasmus Widing
392a13ab90 fix(docs): address review findings from PR #734
- Fix stale port 3000 → 3090 in ngrok/Cloudflare tunnel commands
- Fix workflow names to use actual archon- prefixed names throughout README
- Split ralph into ralph-fresh and ralph-stateful variants
- Fix "Future: workflow definitions" → actual shipped feature label
- Fix directory structure to show project-centric layout (not legacy)
- Add missing TELEGRAM_ALLOWED_USER_IDS documentation
- Add docs/adapters/slack.md for consistent adapter doc pattern
- Update README platform table to link to new slack adapter doc
2026-03-19 09:02:42 +01:00
Rasmus Widing
f8661677e8 refactor(docs): restructure README and extract content to /docs
Slim README from 1576 to 200 lines. Focus on value prop (deterministic
AI coding workflows), quickstart paths (AI-assisted, CLI, Web UI), and
bundled workflow showcase.

All reference content moved to dedicated docs:
- docs/adapters/ — per-platform setup guides
- docs/ai-assistants.md — Claude/Codex auth details
- docs/database.md — SQLite/PostgreSQL guide + schema
- docs/deployment.md — Docker + local dev setup
- docs/commands-reference.md — all slash commands
- docs/troubleshooting.md — common issues and fixes
- docs/windows.md — Windows/WSL2 guide
- docs/configuration.md — added streaming, concurrency, health endpoints
2026-03-19 09:02:42 +01:00
Rasmus Widing
845c816226
feat: default worktree isolation for CLI + auto-detect base branch (#692)
* feat: default worktree isolation for CLI + auto-detect base branch

- CLI now creates a worktree by default (matching all other adapters)
- Branch names auto-generated as {workflowName}-{timestamp}
- --no-worktree opts out of isolation (standalone flag, no longer requires --branch)
- All generated branch names prefixed with archon/ for clear namespace
- Base branch auto-detected from git (symbolic-ref → origin/main → origin/master)
- Config worktree.baseBranch still overrides auto-detection
- $BASE_BRANCH in workflow prompts auto-resolves without config
- Ignore .claude/skills/ from ESLint

* fix: address PR review findings — error handling, tests, docs

- Add warn log for silent getDefaultBranch catch in executor.ts
- Fix branchToSync bug: don't pass fromBranch as sync target
  (fromBranch is the worktree start-point, not the base to sync)
- Add user-facing warning when isolation is silently skipped
- Add errorType to codebase_auto_registration_failed log
- Consolidate all validation guards in workflowRunCommand
  (cli.ts keeps them for UX fast-path, workflowRunCommand is
  the authoritative boundary for programmatic callers)
- Add tests: validation guards, default isolation, --no-worktree
  skip, isolation-skipped warning, auto-detect $BASE_BRANCH success
- Add loadRepoConfig to @archon/core mock in workflow tests
- Update docs: CLAUDE.md, cli-user-guide, configuration,
  authoring-workflows, worktree-orchestration, README, cli.md rule
  — all updated for default isolation, archon/ prefix, optional
  baseBranch with auto-detection

* refactor: simplify isolation branch logic and fix log naming

- Split shouldIsolate into wantsIsolation + codebase check to
  eliminate redundant double-check of codebase
- Simplify else-if chain: use wantsIsolation instead of re-testing
  already-false conditions
- Deduplicate isolation-skipped warning messages
- Fix log event: base_branch.auto_detect_failed →
  workflow.base_branch_auto_detect_failed (project naming convention)

* fix: fail fast when isolation cannot be created instead of silent fallback

When the user hasn't opted out with --no-worktree, failing to create
a worktree (DB error or not in a git repo) now throws instead of
silently running in the live checkout. This prevents AI from making
unprotected changes to the working tree.

* chore: Auto-commit workflow artifacts (archon-assist)
2026-03-17 13:39:41 +02:00
Rasmus Widing
5901defc93
feat: add per-node skills for DAG workflows (#446) (#689)
* feat: add per-node skills for DAG workflows (#446)

Add `skills: [name, ...]` field to DAG workflow nodes. When a node has
skills, the executor wraps it in an AgentDefinition that preloads those
skills into the subagent context. 'Skill' is auto-added to allowedTools.

- Add skills field to DagNodeBase type and loader validation
- Add agents + agent fields to WorkflowAssistantOptions and
  AssistantRequestOptions for AgentDefinition wrapping
- Pass agents/agent through ClaudeClient to SDK Options
- Build AgentDefinition with preloaded skills in dag-executor
- Add Codex warning (per-node skills not supported)
- Add skills comma-separated input in Web UI NodeInspector
- Add skills to WorkflowCanvas reactFlowToDagNodes conversion
- Add 5 unit tests for skills parsing validation

* feat: add Remotion video generation workflow and skills/MCP docs

Add archon-remotion-generate as a bundled default workflow that uses
per-node skills (remotion-best-practices) to generate Remotion video
compositions with AI, then renders preview stills and full video via
deterministic bash nodes.

- Add archon-remotion-generate.yaml to defaults
- Add docs/remotion-workflow.md with setup guide and examples
- Add docs/skills.md documenting per-node skills feature (#446)
- Register workflow in bundled-defaults.ts for binary builds

* chore: gitignore skills-lock.json

* fix: address review feedback for per-node skills (#446)

- Always pass ['Skill'] in AgentDefinition.tools instead of undefined
- Surface buildPromptWithContext errors to user via safeSendMessage
- Use AgentDefinition from SDK in AssistantRequestOptions (remove cast)
- Warn and skip non-object MCP server configs instead of silent passthrough
- Include JSON parse error detail in loadMcpConfig error messages
- Add 3 executor-level tests for skills options construction
- Update bundled-defaults test count for remotion workflow
- Add skills to CLAUDE.md, authoring-workflows.md, README.md, hooks.md
- Clean up loader skills validation with type predicate
2026-03-17 09:21:47 +02:00
Rasmus Widing
7af8745ddb
feat: add per-node MCP servers for DAG workflows (#445) (#688)
* feat: add per-node MCP servers for DAG workflows (#445)

Add `mcp: path/to/config.json` field to DAG workflow nodes. At execution
time, the executor reads the MCP config JSON, expands $VAR_NAME env
references in env/headers values, and passes the loaded servers to the
Claude Agent SDK via Options.mcpServers. MCP tool wildcards are auto-
added to allowedTools.

- Add mcp field to DagNodeBase type and loader validation
- Add mcpServers + allowedTools to WorkflowAssistantOptions and
  AssistantRequestOptions
- Pass mcpServers/allowedTools through ClaudeClient to SDK Options
- Handle system/init message to detect MCP connection failures
- Add Codex warning (per-node MCP not supported)
- Add Haiku warning (tool search not supported)
- Add MCP config path input in Web UI NodeInspector
- Add mcp to WorkflowCanvas reactFlowToDagNodes conversion
- Add 12 unit tests for loadMcpConfig and env var expansion

* fix: address review findings for per-node MCP servers

Type safety:
- Use SDK McpServerConfig type in AssistantRequestOptions (eliminates unsafe cast)
- Update WorkflowAssistantOptions.mcpServers to proper discriminated union
- Remove redundant cast in claude.ts

Error handling:
- Warn users when MCP config references undefined env vars
- Check safeSendMessage return value for MCP connection failures
- Check safeSendMessage return value for Haiku MCP warning
- Log unhandled system messages at debug level in both claude.ts and dag-executor.ts
- Coerce non-string env/header values with warning instead of silent passthrough

Code quality:
- Fix log event naming: dag_node_mcp_* → dag.mcp_* (domain.action_state format)
- Replace IIFE in loader mcp validation with plain if/else
- Extract duplicated env expansion logic into expandEnvVarsInRecord helper
- Merge split import from ./deps into single statement
- Return missingVars from loadMcpConfig/expandEnvVars for caller awareness

Documentation:
- Add mcp field to Node Fields table in docs/authoring-workflows.md
- Add mcp to DAG schema example, allowed_tools section, and summary list
- Add mcp to CLAUDE.md DAG feature list
- Add per-node MCP servers paragraph to README.md tool restrictions section

* docs: add MCP servers guide (docs/mcp-servers.md)

Comprehensive guide covering config file format (stdio/HTTP/SSE), env var
expansion, automatic tool wildcards, MCP-only nodes, connection failure
handling, workflow examples, troubleshooting, and popular server list.
Cross-referenced from authoring-workflows.md and CLAUDE.md.

* feat: add optional ntfy push notification to smart PR review

Add conditional notify node to archon-smart-pr-review workflow that sends
a push notification when the review completes. Gated behind a bash node
that checks for .archon/mcp/ntfy.json — silently skipped if not configured.

- Add check-ntfy bash node + notify MCP node to smart PR review workflow
- Add .archon/mcp/ to .gitignore (per-user MCP configs may contain secrets)
- Add "Push Notifications" setup guide to docs/mcp-servers.md
2026-03-16 20:24:45 +02:00
Rasmus Widing
4054ff18c5
fix: require explicit base branch config for worktree creation (#686)
* fix: require explicit base branch config for worktree creation

When no `worktree.baseBranch` is configured in .archon/config.yaml,
the system silently fell back to `getDefaultBranch()` which always
resolved to `main`. This caused worktrees to branch from main instead
of the intended branch (e.g., dev), producing merge conflicts.

Now errors with actionable message when no base branch is set:
"Set worktree.baseBranch in .archon/config.yaml or use --from flag"

The --from flag continues to work as an override for one-off cases.
Cleanup service still uses getDefaultBranch for merge checks.

Also adds .archon/config.yaml with baseBranch: dev for this project.

* fix: scope $BASE_BRANCH validation and improve error handling

- Make $BASE_BRANCH resolution lazy: only fail when a workflow step
  actually references the variable, not on every workflow execution
- Surface config load errors distinctly from missing-value errors in
  worktree provider (was masking real cause behind generic message)
- Add 'no base branch configured' to known isolation error patterns
  so the error is classified and shown to users properly
- Add tests for baseBranch/fromBranch precedence and non-task
  workflowType behavior
- Update stale docs referencing removed auto-detection fallback
  across CLAUDE.md, README.md, and docs/

* fix: configure isolation loader in CLI workflow command

The CLI was calling getIsolationProvider() without first calling
configureIsolation(), so the worktree provider had no way to load
.archon/config.yaml — all worktree creation failed with "No base
branch configured" even when config existed.
2026-03-16 15:05:16 +02:00
Rasmus Widing
33c329f6db
feat: visual workflow builder with React Flow (#471)
* feat: add visual workflow builder with React Flow

Replace the "Coming Soon" stub at /workflows/builder with a full visual
workflow editor supporting all three modes:

- DAG mode: React Flow canvas with drag-and-drop from command palette,
  edge drawing between nodes, Dagre auto-layout, and full node inspector
- Sequential mode: sortable step list with parallel block grouping
- Loop mode: config panel for prompt/until/max_iterations/fresh_context

Toolbar provides validate, save, and run actions using existing backend
APIs. Existing workflows can be loaded for editing via dropdown or
?edit= URL param. Mode switching with unsaved changes shows confirmation.

Also exports DagNode types from @archon/core, adds 5 new API client
functions (getWorkflow, saveWorkflow, deleteWorkflow, validateWorkflow,
listCommands), and fixes WorkflowDefinitionResponse to use the real
WorkflowDefinition type.

* docs: update docs for visual workflow builder

- Fix directory structure: pages/ → routes/, add workflows to components
- Add visual workflow builder to Web UI features in README

* fix: address review findings in workflow builder

- Move auto-load from render-time side effect to useEffect
- Add fallthrough handling for unrecognized workflow types
- Add promptText as explicit property on DagNodeData, remove double casts
- Consolidate DagFlowNode type alias to single export
- Replace Date.now() node IDs with crypto.randomUUID()
- Use node.id instead of node.data.id in reactFlowToDagNodes
- Remove as WorkflowDefinition casts, inline properties for union safety
- Add try-catch around dagre.layout() and guard undefined pos
- Surface useQuery errors in NodePalette and WorkflowToolbar
- Separate JSON.parse from onUpdate in catch block, show parse details
- Add separate runError state, clear stale errors, handle orphaned conversations

* feat: add parallel block inspector, editing, and ungrouping

- Add ParallelBlockInspector component with sub-step editing
  (command, clearContext, allowed/denied tools)
- Add/remove sub-steps within a parallel block
- Auto-ungroup when fewer than 2 sub-steps remain
- Ungroup button in both inspector panel and step row
- Delete block action in inspector

* fix: address PR review findings in workflow builder

- Fix prompt text data loss: map prompt → promptText in dagNodesToReactFlow
- Add key prop to NodeInspector to prevent stale state on node switch
- Log dagre layout errors instead of silently swallowing
- Surface listCommands query errors with visible banner
- Block run when unsaved changes; don't navigate on failure
- Validate before save to avoid raw server error messages
- Add console.error to loadWorkflow and validation catch blocks
- Surface workflow list load error in feedback row
- Differentiate network errors from validation errors
- Add readonly to SequentialEditor steps prop
- Add JSDoc on DagNodeData, ParallelBlockInspectorProps, WorkflowCanvasProps

* feat: add Beta badge to Workflow Builder nav link

* feat: add bash node type and smart PR review DAG workflow

Add a `bash` node type for DAG workflows that runs shell scripts without
AI, capturing stdout as node output. This enables free/deterministic
operations like gathering stats or running git commands within DAG
workflows.

- BashNode type with `bash` script field and optional `timeout`
- Three-way mutual exclusivity in parser (command/prompt/bash)
- executeBashNode with variable substitution, stderr logging, timeout
- Web UI: BASH badge, script editor, timeout input, draggable palette item

Also add archon-smart-pr-review DAG workflow that classifies PR complexity
first (via haiku), then routes to only the relevant review agents based
on the classification. Saves AI calls on trivial/small PRs.

* docs: document bash node type in DAG workflow section

The bash: node type added in this PR was missing from the workflow
documentation. Users writing DAG workflows need to know the three
available node types: command:, prompt:, and bash:.

* fix: address review findings in workflow builder

- Add console.error to handleSave/handleRun catch blocks (was silently swallowing errors)
- Fix allowed_tools/denied_tools using || instead of ?? (empty array [] was converted to undefined, changing semantics)
- Remove unnecessary type assertions in resolveNodeDisplay that bypass TS narrowing
- Add justification comments to as DagNode casts (required by project guidelines)
- Add error details to NodePalette failed commands message
- Use exhaustive switch in buildDefinition with never check
- Fix NodeInspector comments: "AI-only fields" was incomplete, "Output Format" guard was misleading
- Separate serialize/parse try-catch in validate endpoint for clearer error messages
- Classify ENOENT/EACCES errors in executeBashNode for user-friendly messages
- Document intentional Dagre layout fallback per project guidelines
2026-02-25 14:09:53 +02:00
Rasmus Widing
9def2a5ebd
feat: per-node and per-step tool restrictions (allowed_tools, denied_tools) (#454)
* feat: add per-node and per-step tool restrictions (allowed_tools, denied_tools)

Add `allowed_tools` (whitelist) and `denied_tools` (blacklist) fields to DAG
nodes and sequential steps, enforced at the Claude SDK level via Options.tools
and Options.disallowedTools.

- Extend AssistantRequestOptions with disallowedTools field
- Add allowed_tools/denied_tools to DagNodeBase and SingleStep types
- Parse and validate the arrays in parseDagNode and parseSingleStep
- Spread disallowedTools into Claude SDK Options in claude.ts
- Apply per-node restrictions in resolveNodeProviderAndModel (dag-executor)
- Merge per-step restrictions in executeStepInternal (executor)
- Emit Codex warning when these fields are set (unsupported per-call)
- Preserve empty allowed_tools: [] distinct from absent (disables all tools)

* docs: document allowed_tools and denied_tools for workflow tool restrictions

Add allowed_tools/denied_tools to the Step Options and Node Fields tables
in authoring-workflows.md, add a dedicated section with examples, update
the Summary list, and add a brief mention in README.md and CLAUDE.md.

* refactor: extract parseToolList helper, simplify tool restriction parsing

Extract duplicated allowed_tools/denied_tools parsing logic from
parseSingleStep and parseDagNode into a shared parseToolList helper.
Replaces nested ternaries and IIFE patterns with straightforward
conditionals. Simplify stepOptions construction in executor.ts to
use explicit if-statements instead of nested spreads.

* fix: address PR review issues in tool restriction validation and delivery

- parseSingleStep: add error propagation for non-array allowed_tools/denied_tools (return null on failure)
- parseDagNode: return null when tool field validation adds errors (errorsBeforeToolFields guard)
- parseToolList: warn on non-string entries for steps (id always passed now)
- Add warning when denied_tools is set alongside allowed_tools: []
- executor.ts: make Codex and Claude paths mutually exclusive (no dead tool fields built for Codex)
- dag-executor.ts: check safeSendMessage return for both output_format and tool restriction warnings, log error on delivery failure
- Add tests: denied_tools-only Codex warning, both tools on same step, merged options with model, DAG execution-level tool restriction tests
2026-02-19 14:48:27 +02:00
Rasmus Widing
a315617b73
feat: DAG workflow engine with parallel execution and conditional branching (#450)
* feat: add DAG workflow engine with parallel execution and conditional branching

Adds a third workflow execution mode (`nodes:`) alongside `steps:` and `loop:`.
DAG workflows support explicit dependency edges, parallel layer execution via
Promise.allSettled, conditional branching with `when:` expressions, join semantics
via `trigger_rule`, structured JSON output via Claude SDK `outputFormat`, and
upstream output capture via `$node_id.output` substitution.

- New: `DagNode`, `DagWorkflow`, `TriggerRule`, `NodeOutput`, `NodeState` types
- New: `condition-evaluator.ts` — pure `evaluateCondition` for `when:` expressions
- New: `dag-executor.ts` — topological sort, Promise.allSettled parallel layers,
  output capture, trigger rule evaluation, per-node provider/model resolution
- Updated: `loader.ts` — detect `nodes:` key, validate node graph, Kahn cycle detection
- Updated: `executor.ts` — route DAG workflows to dag-executor before loop dispatch
- Updated: `logger.ts` / `event-emitter.ts` — node_start/complete/skip/error events
- Updated: `workflow-bridge.ts` — SSE events for dag_node state changes
- Updated: `AssistantRequestOptions` — added `outputFormat` for Claude structured output
- Updated: `claude.ts` — thread `outputFormat` into SDK Options
- Tests: 37 new tests (condition-evaluator + dag-executor topological sort, trigger
  rules, loader cycle detection, invalid DAG rejection, valid DAG parsing)

* docs: document DAG workflow mode (nodes:) added in phase 1

Add full documentation for the new `nodes:` execution mode:
- docs/authoring-workflows.md: add third workflow type section,
  full DAG schema reference (node fields, trigger_rule, when:
  conditions, output_format, $nodeId.output substitution), a
  DAG example workflow, and update the variable table and summary
- CLAUDE.md: add nodes:/DAG bullet points to the Workflows section
- README.md: add nodes: example alongside steps: and loop:, update
  key design patterns to mention DAG mode

* fix: address DAG workflow engine review findings

Critical bugs:
- DB workflow status never updated after DAG completion (completeWorkflowRun/failWorkflowRun now called)
- resolveNodeProviderAndModel throws silently swallowed by Promise.allSettled — now caught and returned as failed node outputs
- substituteNodeOutputRefs JSON parse failure was silent — now logged as warn

Important fixes:
- Surface unparseable when: conditions to user via safeSendMessage (fail-open preserved)
- Missing upstream nodes treated as failed in checkTriggerRule instead of silently filtered out
- Config load failure in loadCommandPrompt upgraded from warn to error
- Circular import executor ↔ dag-executor broken via new command-validation.ts module
- Remove defensive "should never happen" else branch in executeNodeInternal (DagNode discriminated union guarantees it)

Type improvements:
- DagNode → CommandNode | PromptNode discriminated union (command/prompt mutually exclusive at type level)
- NodeOutput → discriminated union (error: string required on failed, absent on others)
- TRIGGER_RULES constant and isTriggerRule() added to types.ts, deduplicating loader.ts local definitions
- isDagWorkflow simplified to Array.isArray(workflow.nodes)
- output_format array guard in parseDagNode now rejects arrays and null values

Code quality:
- Replace all void workflowEventDb.createWorkflowEvent() with .catch() error logging
- Fix o.error ?? 'unknown' to o.state === 'failed' ? o.error : 'unknown' (type-safe)
- Export substituteNodeOutputRefs for unit testing

Tests (7 new):
- condition-evaluator: number and boolean JSON field coercion
- dag-executor: none_failed_min_one_success with all-skipped deps, nodes+loop conflict,
  invalid trigger_rule rejection, substituteNodeOutputRefs (3 cases), all-nodes-skipped mechanism

* docs: fix two inaccuracies in DAG workflow documentation

- README: "Nodes without depends_on run in parallel" was misleading —
  root nodes run concurrently with each other in the same layer, but a
  single root node doesn't run "in parallel" with anything. Reworded to
  "are in the first layer and run concurrently with each other".

- authoring-workflows.md: Variable Substitution section intro said
  "Loop prompts and DAG node prompts/commands support these variables"
  but step-based workflows also support the same variables via
  substituteWorkflowVariables in executor.ts. Updated to say all
  workflow types.

* fix: address PR #450 review findings in DAG workflow engine

Correctness:
- Remove throw from !anyCompleted path to prevent double workflow_failed
  emission; add safeSendMessage and return instead
- Guard lastSequentialSessionId assignment against undefined overwrite

Type safety:
- Narrow workflowProvider from string to 'claude' | 'codex' in
  resolveNodeProviderAndModel and executeDagWorkflow signatures
- Remove unsafe 'as claude | codex' cast
- Add compile-time assertion that NodeOutput covers all NodeState values

Silent failure surfacing:
- Pre-execution node failure now notifies user via safeSendMessage
- Unexpected Promise.allSettled rejection notifies user and logs layerIdx
- completeWorkflowRun DB failure notifies user of potential inconsistency
- Codex node with output_format now warns user (not just server log)
- Make resolveNodeProviderAndModel async to support the above

Dead code:
- Remove unused 'export type { MergedConfig }' re-export

Comments:
- Update safeSendMessage/substituteWorkflowVariables/loadCommandPrompt
  TODOs to reflect Rule of Three is now met
- Fix executeNodeInternal docstring to mention context:'fresh' nodes
- Fix evaluateCondition @param: "settled" not "completed" upstreams
- Fix NodeOutput doc: "JSON-encoded string from the SDK"

Tests (7 new):
- substituteNodeOutputRefs: unknown node ref resolves to empty string
- checkTriggerRule: absent upstream synthesised as failed (x2)
- buildTopologicalLayers: two independent chains share layers correctly
- evaluateCondition: valid expression returns parsed: true
2026-02-18 15:13:22 +02:00
Rasmus Widing
d7a6335fa6
fix: prevent router bypass when AI uses tools instead of /invoke-workflow (#449)
* fix: prevent router bypass when AI uses tools instead of /invoke-workflow (#291)

When routing natural language messages to workflows, Claude sometimes used
tools directly instead of outputting `/invoke-workflow {name}`. This left
no fallback — the raw AI response (often with tool output) was sent to the
platform and the expected workflow never ran.

- Pass `tools: []` to the Claude SDK for routing calls (hard SDK constraint,
  not just a prompt instruction) so tools are unavailable during routing
- Add tool-avoidance instruction to the router prompt as belt-and-suspenders
- Detect Codex tool bypass in the stream/batch loop and suppress tool events
  from the platform during routing
- Fall back to `archon-assist` in `tryWorkflowRouting` when no
  `/invoke-workflow` is found — covers both Claude prompt misses and Codex
  tool bypass (where no assistant text is produced at all)
- Log distinct events: `router.tool_bypass_detected`,
  `router.codex_tool_bypass_fallback`, `router.fallback_to_assist`,
  `router.assist_workflow_not_found`

Tests: tools:[] assertion, archon-assist fallback, raw response fallback,
Codex all-tool path

* docs: document router fallback behavior and tool restriction

Update CLAUDE.md and README.md to reflect the new routing behavior:
- Router falls back to archon-assist when no /invoke-workflow is produced
- Claude routing calls pass tools: [] to prevent tool use at the API level
- Codex tool bypass is detected and triggers the same archon-assist fallback

* fix: address review findings from PR #449

- Fix silent failure: send error message when Codex uses tools during
  routing but no archon-assist fallback exists (both stream and batch mode)
- Remove mutable hadTool field from WorkflowRoutingContext; pass as
  explicit parameter to tryWorkflowRouting instead
- Downgrade router.assist_workflow_not_found from warn to debug since
  it fires on every normal routing response without archon-assist
- Add conversationId to router.tool_bypass_detected log for correlation
- Add JSDoc to AssistantRequestOptions.tools documenting undefined vs []
  semantics and Codex no-op behavior
- Add batch-mode Codex tool-bypass test (hadToolBatch path was untested)
- Add test for Codex not receiving tools: [] (documents SDK contract)
- Add test for silent failure case when no archon-assist and tool bypass
2026-02-18 13:16:14 +02:00
Cole Medin
f2a0d029e7 SQLite-first docs, fix Postgres workflow_runs default, rebuild combined schema
- Fix workflow_runs.status DEFAULT from 'running' to 'pending' in Postgres
  (migration 018) to match SQLite and actual code flow
- Rebuild 000_combined.sql as clean final schema (7 tables, no stale columns,
  correct defaults, all indexes)
- Update all docs to present SQLite as the default, zero-setup option
- Mark PostgreSQL as optional/advanced in README, CLAUDE.md, and guides

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:23:59 -06:00
Rasmus Widing
7dc2e444f9
Deprecate database command templates (#425)
* Fix: Deprecate database command templates (#231)

Database command templates still influenced routing and /command-invoke, preventing file-based commands from fully replacing them.

Changes:
- Remove template routing, handlers, and DB module
- Add .archon/commands fallback for /command-invoke
- Drop template table from schema/migrations and update docs/tests

Fixes #231

* docs: update CLAUDE.md and README.md for template deprecation

Remove all references to deprecated database command templates:
- Update table count from 8 to 7 tables
- Remove command_templates table from database schema sections
- Remove "Command Templates (Global)" section from README
- Remove /template-add, /template-delete, /templates command docs
- Update "Custom command templates" to "Custom commands"
- Remove references to global templates stored in database

* Fix review findings: error handling, tests, migration guidance

- Fix commandFileExists to only catch ENOENT, throw on unexpected
  errors (permissions, I/O) instead of silently returning false
- Add test for file read failure after successful existence check
- Add test for path traversal rejection via isValidCommandName
- Add test for registered command taking precedence over fallback
- Add migration guidance comments for users with existing templates
2026-02-17 16:55:17 +02:00
Rasmus Widing
7c9e14e533
Fix documentation gaps and stale code examples (#246, #367) (#403)
* Fix documentation gaps and stale code examples (#246, #367)

README assumed psql on host for Docker setups (schema auto-inits via
docker-entrypoint-initdb.d). CLAUDE.md had an empty Git Operation Errors
section. architecture.md showed old inline-concatenation pattern for
context injection. executor.ts had an orphaned JSDoc block.

Changes:
- Remove misleading psql command from README, add auto-init note
- Fill Git Operation Errors section with classifyIsolationError pattern
- Update Context Injection docs to match current contextToAppend approach
- Remove duplicate JSDoc on executeStepInternal

Fixes #246
Fixes #367

* Address self-review findings

- Remove broken #database-migrations anchor link from README note
- Use generic comment placeholder instead of fictional worktreeProvider API in CLAUDE.md
2026-02-17 13:04:19 +02:00
DIY Smart Code
2c378b9f14
Fix: Remove misleading psql command from Docker setup (#246) (#405)
README.md instructs users to run `psql $DATABASE_URL < migrations/000_combined.sql`
for Docker-based PostgreSQL setup, but this requires a locally-installed psql client
that Docker-only users don't have. The migration is already auto-executed on first
container startup via the init.d mount in docker-compose.yml.

Changes:
- Removed unnecessary psql command from README Optional PostgreSQL section
- Added note clarifying that schema is created automatically for Docker installs

Fixes #246

Co-authored-by: leex279 <leex279@users.noreply.github.com>
2026-02-17 13:03:08 +02:00
Rasmus Widing
bc581ff2a8
Fix PRs targeting wrong base branch instead of configured one (#387)
* Investigate issue #377: PRs hardcoded to main instead of configured base branch

* Fix PRs targeting wrong base branch instead of configured one (#377)

Workflow command templates hardcoded `main` as the base branch for PR creation,
git diffs, rebases, and output display. The `baseBranch` config from
`.archon/config.yaml` was correctly used for worktree creation but never
passed through to these workflow command templates.

Changes:
- Add base branch detection (config -> repo default fallback) to archon-finalize-pr, archon-create-pr, and archon-plan-setup
- Add --base flag to gh pr create in archon-finalize-pr
- Replace hardcoded origin/main references with $BASE_BRANCH variable
- Fix output templates to show actual base branch instead of hardcoded "main"
- Fix conflict resolution instructions in archon-pr-review-scope to use {base} variable

Fixes #377

* Fix remaining hardcoded main references caught in self-review

- archon-create-pr.md: Fix alternative gh pr create --fill to use $BASE_BRANCH
- archon-create-pr.md: Fix error handling rebase instruction to use $BASE_BRANCH
- archon-plan-setup.md: Fix error handling merge conflict message to use $BASE_BRANCH

* Fix hardcoded main references in remaining command templates

Extends the base branch fix to all command templates:
- archon-implement.md: Add base branch detection, fix rebase and decision table
- archon-implement-issue.md: Add base branch detection, fix rebase and checkpoint
- archon-implement-review-fixes.md: Fix branch check text
- archon-plan-setup.md: Fix decision table and error message text
- archon-pr-review-scope.md: Fix "Behind Main" labels and comments

* Add $BASE_BRANCH as a system variable for workflow commands

Resolve base branch in TypeScript (from config or git auto-detection)
and substitute $BASE_BRANCH in command templates, replacing the
duplicated 7-line shell detection snippet across 5 templates.

- Add baseBranch field to MergedConfig, propagate from repo config
- Resolve baseBranch once per workflow in executor via
  config.baseBranch ?? getDefaultBranch(cwd)
- Thread baseBranch through substituteWorkflowVariables and all
  execution paths (step, parallel, loop)
- Remove shell detection blocks from archon-finalize-pr,
  archon-create-pr, archon-plan-setup, archon-implement, and
  archon-implement-issue templates
- Add test for $BASE_BRANCH substitution following $ARTIFACTS_DIR
  test pattern

* docs: Add $BASE_BRANCH variable to documentation

* Fix $BASE_BRANCH shell variable collision and add error handling

- Rename shell variables BASE_BRANCH→PR_BASE in 3 templates
  (pr-review-scope, resolve-merge-conflicts, sync-pr-with-main)
  to avoid collision with Archon-level $BASE_BRANCH substitution
- Wrap getDefaultBranch() in try-catch with user notification
- Add baseBranch resolution logging matching provider pattern
- Restore user override capability in archon-create-pr
- Add .trim() validation for whitespace-only baseBranch config
- Improve MergedConfig.baseBranch docstring with fallback info
- Add tests for config-driven baseBranch precedence
- Add config-loader tests for baseBranch extraction and trimming
2026-02-16 14:41:09 +02:00
Cole Medin
352171474b
Archon Web UI: React frontend, web adapter, API routes, workflow events
* Archon UI PRD and phase 1 plan

* Initial Archon UI

* Workflow tracking

* UI improvements (with a couple schema changes)

* Message history for web adapter and UI adjustments

* Chat/Project/Tasks in Archon UI

* UI fixes

* UI fixes

* UI improvements

* Fix PR review issues: type safety, error handling, cleanup, docs

- Convert MessageChunk to discriminated union with workflow_dispatch variant
- Add IWebPlatformAdapter interface and isWebAdapter() type guard
- Replace unsafe 'in' type guards with proper type narrowing in orchestrator
- Add logging to silent catch blocks in api.ts, web.ts
- Add WebAdapter buffer cleanup with 60s delayed cleanup on disconnect
- Wrap SQLite migration ALTER TABLE groups in try/catch
- Log SSE parse errors in useSSE.ts
- Truncate API error bodies to 200 chars, include URL path
- Surface background workflow errors to parent conversation
- Fix getWorkflowRunByWorker to only swallow 404s, re-throw 500s
- Add documentation comments to ChatMessage and SSEEvent types
- Update table counts from 3/5/6 to 8 across all docs

* Remove agent plan files from PR, gitignore .agents/plans/

These are local development artifacts that shouldn't be in the repo.

* Gitignore .claude/PRPs/

* Fix PR review issues: error handling, type safety, silent failures

- Fix acquireLock error swallowing: wrap handler in try/catch/finally to
  always release UI lock and surface errors to SSE stream
- Restrict CORS to configurable origin (WEB_UI_ORIGIN env var)
- Validate status query param instead of unsafe `as` cast
- Add per-codebase JSON.parse error isolation for corrupted commands
- Type request body in POST /api/conversations
- Return 404 for missing conversation instead of empty array
- Add warning log when flushAssistantMessage has no DB ID mapping
- Add debug logging to 6 SSE catch blocks (was silently swallowing)
- Replace 17x .catch(() => undefined) with void on fire-and-forget calls
- Make workflow status='running' update a blocking error
- Split MessageChunk into proper per-type discriminated union
- Add hidden field to Conversation interface
- Add guard in addMessage for undefined row
- Extract WorkflowRunStatus/WorkflowStepStatus type aliases
- Fix WorkflowArtifact.type to use literal union
- Separate SSE parse errors from handler errors in useSSE hook
- Gitignore e2e testing session artifact

* Wire up dead endpoints: workflow run UI, health display, worker→run link

- Extract dispatchToOrchestrator() helper to deduplicate lock/dispatch
  logic between message send and workflow run endpoints
- Fix workflow run endpoint to construct /workflow run <name> <msg>
  from URL param + body, with name validation
- Add run panel to WorkflowList with message input, error display,
  and navigation to chat on success
- Add System Health section to SettingsPage with independent query
  and actionable error messages
- Add worker→run navigation link in WorkflowExecution header
- Regenerate 000_combined.sql to include migrations 001-015
- Fix silent .catch() patterns: log errors instead of swallowing
- Wrap emitSSE in catch block, log full error objects

* Fix routing for conversation IDs with special characters

GitHub issue conversation IDs like "user/repo#42" contain / and #
which break React Router's :param matching. Fix by:
- Use /chat/* splat route instead of /chat/:conversationId
- encodeURIComponent() all platform_conversation_id values in URLs
- decodeURIComponent() in ChatPage when reading the splat param

* Restructure sidebar: project selector nav, remove dead components

Replace multi-view sidebar (ChatView, ProjectView, TaskView, ViewSwitcher)
with a simpler project-scoped navigation. Add ProjectSelector component
for switching between codebases. Remove unused ConversationsList,
useNotifications hook, and related dead code.

* Add project CRUD: clone/register from UI, delete with cleanup

Extract clone logic from command-handler into standalone clone.ts module
with cloneRepository() and registerRepository() entry points. Add REST
endpoints POST /api/codebases (clone URL or register local path) and
DELETE /api/codebases/:id (destroy worktrees, unlink DB, remove workspace).

Update sidebar with "+" button for inline project add input that auto-detects
URL vs local path, and hover-to-delete with AlertDialog confirmation on each
project in ProjectSelector.

* Harden backend guard rails, polish UX, remove dead project pages

Backend:
- Guard output callback and cleanup timer with try-catch
- Add zombie stream reaper (5min interval) with proper cleanup
- Force-flush assistant buffer at 50 segments to prevent unbounded growth
- Log warning on message buffer overflow
- Emit SSE warning when user message persistence fails

Frontend:
- Show spinner on send button while processing
- Add native tooltip on truncated conversation titles
- Make sidebar resize handle visible with subtle background

Dead code:
- Delete orphaned ProjectDetail, ProjectsList, ProjectsPage
- Remove /projects/:id route from App.tsx

* Dashboard landing page, chat empty state, API error quality, SQLite indexes

- Replace DashboardPage redirect with landing page showing recent
  conversations and workflow runs in a two-column grid
- Fix /chat empty state to render ChatInterface in new-chat mode
  instead of a static placeholder
- Add proper HTTP status codes to API: 404 for missing conversations,
  400 for invalid codebase IDs, empty array for failed workflow discovery
- Add 3 missing indexes to SQLite schema from PG migrations 009/010
  (workflow run staleness, session parent, session conversation lookup)

* Scope workflow runs to selected project

Pass the selected project's codebaseId when creating a conversation
for workflow execution. Show which project the workflow will target,
and disable the run controls when no project is selected.

* Inline project selector in workflow invocation panel

Replace static "Running on {project}" text with a <select> dropdown
so users can pick a project without leaving the workflow view.

* Fix chat header showing "No project" and new chat missing project

Header now resolves project name from codebase_id when cwd is absent.
Dashboard "New Chat" creates conversation with selected project instead
of navigating to an orphaned /chat route. Buttons disabled when no
project is selected.

* Sidebar nav, workflow builder route, workflow invoker in project detail

Add Workflows and Workflow Builder nav links to sidebar, extract
navLinkClass helper. Wire WorkflowInvoker into ProjectDetail. Add
WorkflowBuilderPage route. Remove dead redirect routes and unused
Header from pages that don't need it.

* Fix review issues: guard rm-rf, error handling, Error Boundary, dedup utility

- Guard DELETE /api/codebases/:id to only rm-rf paths under ~/.archon/workspaces/
  (externally registered repos only get DB record deleted)
- Remove accidental e2e-testing-findings-session2.md
- Replace 3x .catch(() => undefined) with proper error logging
- Add React Error Boundary at app root to prevent white-screen crashes
- Wrap JSON.parse(metadata) in try-catch in ChatInterface and WorkflowLogs
- Upgrade SSE write failure logging from debug to warn, add missing logging
- Fix bare catch in SSE heartbeat to only swallow disconnect errors
- Remove unused _createErrorHandler parameter from registerApiRoutes
- Extract shared findMarkdownFilesRecursive to packages/core/src/utils/commands.ts
- Convert boolean to integer explicitly for SQLite hidden column
- Surface workflow discovery errors as warning in API response

* Address PR review: error handling, SSE resilience, test coverage

- Fix path traversal in codebase deletion (use normalizedCwd)
- Buffer SSE write failures for reconnect delivery (3 catch blocks)
- Extract flushBufferedMessages helper with partial-failure recovery
- Add defensive outer catch to background workflow dispatch
- Surface API/load errors to users (history, metadata, React Query)
- Add SSE parse validation and handler error surfacing
- Show stale indicator when workflow polling loses connection
- Add delete error handling to ConversationItem dialog
- Import shared types from @archon/core instead of duplicating
- Lower activity update failure threshold from 5 to 3
- Add test coverage for messages.ts and workflow-events.ts (100%)

* docs: Update documentation for Web UI, workflow events, and message persistence

- Update database schema description (workflow_events detail, messages metadata)
- Add Web UI platform adapter to architecture docs
- Document REST API endpoints for Web UI
- Add SSE streaming pattern documentation
- Update conversation schema (title, deleted_at columns)
- Expand Web UI feature list (workflow invocation, message persistence)

* Address PR review: error handling, type safety, SSE resilience

- Add null check on createWorkflowRun INSERT return
- Narrow catch in registerRepoAtPath to not swallow command loading errors
- Add SSE onerror logging and user notification on permanent close
- Add WarningEvent to SSE union and surface warnings in ChatInterface
- Fix WorkflowEventRow.data SQLite type mismatch (parse JSON string)
- Separate conversation lookup from auto-titling error handling
- Fix log levels for data loss scenarios (warn/debug → error)
- Emit SSE warning to user on flushAssistantMessage failure
- Set workflow run parent link regardless of success/failure
- Cap total buffered conversations at 200
- Define ArtifactType once in core, use everywhere
- Use imported status types in SSE event interfaces
- Add exhaustiveness checks in switch statements
- Preserve original git error in registerRepository
- Remove unused recoverable field from ErrorEvent

---------

Co-authored-by: Rasmus Widing <rasmus.widing@gmail.com>
2026-02-16 09:03:44 +02:00
Rasmus Widing
d5c03a29b7 fix: Address review findings (HIGH + MEDIUM)
- Use native SQLite RETURNING (.all()) instead of lastInsertRowid
  emulation, which returned wrong row on ON CONFLICT DO UPDATE
- Remove unused extractInsertTableName method (dead code after fix)
- Fix trailing comma in SQLite schema causing syntax error on fresh init
- Update create() JSDoc to reflect upsert behavior
- Add migration 011 to README upgrade instructions (3 locations)
- Add SQLite adapter tests for INSERT RETURNING + ON CONFLICT

Review artifacts: .archon/artifacts/runs/14ad0f4c-daa1-4fa2-babb-92822620ac7b/review/
2026-01-30 17:29:53 +02:00
Rasmus Widing
9634167911 docs: Document how commands/workflows are loaded (CLI vs server)
Commands and workflows are loaded at runtime from the working directory.
The CLI reads from disk (sees uncommitted changes), while the server reads
from the workspace clone which only syncs from origin before worktree
creation. Added notes to README, getting-started, authoring guides, and
CLI user guide so users understand they need to push changes for the
server to pick them up.
2026-01-30 12:14:17 +02:00
Rasmus Widing
133a3ccc69 feat: Add interactive setup wizard and config editor to Archon skill
Add a complete setup wizard that guides users through first-time Archon
installation on a target repository. The wizard covers CLI installation,
platform selection (GitHub, Telegram, Slack, Discord), .env configuration,
and copying default commands/workflows to the target repo.

Key additions:
- Setup wizard with quick/guided modes (guides/setup.md)
- Interactive config editor for global and repo config (guides/config.md)
- Platform-specific setup guides (GitHub, Telegram, Slack, Discord)
- Config routing in SKILL.md for "change my config" intent
- Freeform input guidelines to prevent double-question UX issues
- .env detection to skip already-configured values
- Move commands/workflows to defaults/ subdirectory
- Clean up old artifacts and SDLC examples
- Add docs/running-on-a-target-repo.md
2026-01-30 10:41:21 +02:00
Rasmus Widing
c142dbbc54
feat(cli): Add git repository safety check (#328)
* feat(cli): Add git repository safety check

Add validation to ensure CLI workflows only run from within a git
repository. If the user runs from a subdirectory, the CLI resolves
to the repo root. Running from a non-git directory produces a clear
error message with guidance.

- Add git.findRepoRoot() check before workflow commands
- Bypass check for version/help commands
- Add tests for git repo validation behavior

* docs: Update CLI documentation for git repository requirement

* fix(cli): Improve error handling and tests for git repo check

- Move git.findRepoRoot() inside try-catch block to ensure proper error
  handling and database cleanup on unexpected errors
- Add path existence validation before git check for clearer error messages
- Improve tests: test real git.findRepoRoot behavior instead of mocks
- Add tests for path validation and command categorization logic
2026-01-22 10:00:12 +02:00
Rasmus Widing
2c5cb65619
docs: Add CLI user guide and developer guide (#326)
* docs: Add CLI user guide and developer guide

- Add docs/cli-user-guide.md with command reference, flags, and examples
- Add docs/cli-developer-guide.md with architecture and ASCII flow diagrams
- Update README CLI section with proper setup order (install → auth → run)
- Link README to user guide, user guide to developer guide

* docs: Update CLI docs to reflect source-based usage

Binary distribution not yet available. Update all docs to use
`bun run cli` from cloned repo instead of `archon` binary.

* docs: Add bun link for global CLI availability

- Add step to run `bun link` from packages/cli for global `archon` command
- Update all examples to use `archon` instead of `bun run cli`
- Update Windows WSL2 section with bun link step
2026-01-22 09:03:12 +02:00
Rasmus Widing
0e57b2f788 fix: Update all repo URLs from raswonders to dynamous-community 2026-01-22 00:20:27 +02:00
Rasmus Widing
68e7db0466
feat: Phase 5 - CLI binary distribution (#325)
* docs: Add Phase 5 CLI binary distribution plan

- Create detailed implementation plan for binary distribution
- Add Phase 5.0: Bundle defaults for binary (depends on #322)
- Add Phase 5.1-5.7: Build scripts, GitHub Actions, curl install,
  Homebrew formula, Windows docs, version command, release guide
- Update research doc with Phase 6 (auto-update command)
- Renumber dashboard to Phase 7, workflow builder to Phase 8
- Mark Phases 1-4 as complete in research doc

* feat: Phase 5 - CLI binary distribution

Implement standalone binary distribution for Archon CLI:

- Bundle default commands and workflows into binaries at compile time
- Add build scripts for cross-platform compilation (macOS/Linux, ARM64/x64)
- Create GitHub Actions release workflow triggered on version tags
- Add curl install script with checksum verification
- Create Homebrew formula for macOS/Linux installation
- Update version command to show platform, build type, and database info
- Add developer release guide documentation
- Update README with CLI installation instructions

Binary compilation uses Bun's --compile flag to create standalone
executables that include the Bun runtime and all dependencies.
Default workflows and commands are imported as text at compile time
and embedded directly into the binary.

* fix: Pin Dockerfile to Bun 1.3.4 to match lockfile version

The Docker build was failing because oven/bun:1-slim resolved to 1.3.6
while the lockfile was created with 1.3.4, causing --frozen-lockfile to fail.

* docs: Clarify binary vs source builds for default commands/workflows

* fix: Address PR review issues for CLI binary distribution

Security fixes:
- install.sh: Require SKIP_CHECKSUM=true to bypass checksum verification
  instead of silently skipping (addresses security vulnerability)
- install.sh: Show actual error output when version check fails instead
  of falsely reporting success

Validation improvements:
- checksums.sh: Validate all 4 expected binaries exist before generating
  checksums to prevent releasing incomplete builds
- build-binaries.sh: Verify binary exists and has reasonable size (>1MB)
  after each build step
- update-homebrew.sh: Validate extracted checksums are non-empty and
  look like valid SHA256 hashes (64 hex chars)
- update-homebrew.sh: Fix sed patterns to use URL context for updating
  checksums on subsequent runs

Bug fixes:
- homebrew/archon.rb: Fix test to expect exit code 0 (success) instead
  of 1 for `archon version`
- loader.ts: Log error when bundled workflow fails to parse (indicates
  build-time corruption)

Test coverage:
- Add bundled-defaults.test.ts for isBinaryBuild() and content validation
- Add connection.test.ts for getDatabaseType() function
- Add binary build bundled workflow tests to loader.test.ts
- Add binary build bundled command tests to executor.test.ts

All 959 tests pass.
2026-01-21 23:51:51 +02:00
Rasmus Widing
090e5fd812
feat: Runtime loading of default commands/workflows (#324)
* feat: Runtime loading of default commands/workflows

Instead of copying default commands and workflows to target repos on
clone, load them at runtime from the app's bundled defaults directory.

Changes:
- Fix getAppArchonBasePath() to resolve to repo root (not packages/core)
- Add loadDefaultCommands and loadDefaultWorkflows config options
- Update workflow loader to search app defaults then repo (repo wins)
- Update command executor to search app defaults after repo paths
- Remove copyDefaultsToRepo() calls from /clone and GitHub adapter
- Fix lint-staged to not warn on ignored test files

Benefits:
- Defaults always up-to-date (no sync issues)
- Clean repos (no 24+ files copied per clone)
- User's local clone stays in sync with what Archon uses

Closes #322

* docs: Update documentation for runtime loading of defaults

- Update CLAUDE.md to explain runtime loading behavior
- Fix README.md example output and note about defaults
- Update docs/configuration.md with new config options
- Mark copyDefaults as deprecated in favor of loadDefaultCommands/loadDefaultWorkflows

* fix: Address PR review findings for runtime loading

- Fix silent error swallowing in loadConfig catch blocks (loader.ts, executor.ts)
  - Now logs warning with context before falling back to defaults
  - Users will know when their config has syntax errors

- Fix config merging bug in mergeRepoConfig
  - Now includes loadDefaultCommands and loadDefaultWorkflows in merge
  - Repo config opt-out now works correctly

- Add consistent empty file handling for app defaults
  - Returns explicit empty_file error instead of falling through

- Add debug logging for ENOENT cases
  - Helps troubleshoot when app defaults aren't found

- Add startup validation for app defaults paths
  - validateAppDefaultsPaths() checks and logs verification status
  - Called during server startup after logArchonPaths()

- Add comprehensive tests for app defaults command loading
  - Test loading from app defaults when not in repo
  - Test repo commands override app defaults
  - Test loadDefaultCommands: false opt-out
  - Test empty file handling
  - Test graceful handling of missing paths
  - Test config error fallback behavior

* fix: Use namespace imports for archonPaths to fix test mocking in CI

The loader.ts used destructured imports for getDefaultWorkflowsPath and
getWorkflowFolderSearchPaths, but the tests use spyOn which only works
with namespace imports (import * as). This caused the mocks to not work
in CI where tests run in parallel, causing 48 test failures.

* fix: Restore spyOn approach with namespace imports for loader tests

The key fix is that loader.ts uses namespace imports (import * as archonPaths)
which shares the same module instance with the test file. This allows spyOn
to work correctly without using mock.module() which pollutes other tests.

* fix: Use loadDefaultWorkflows: false to avoid app defaults in tests

Instead of mocking archon-paths (which pollutes other tests), we:
1. Only mock config-loader with loadDefaultWorkflows: false by default
2. This prevents app defaults from being loaded during tests
3. For multi-source loading tests, enable loadDefaultWorkflows: true
   and use spyOn to set the path to a temp directory

* fix: Use namespace imports and spyOn for all loader dependencies

Key changes:
1. loader.ts now uses namespace imports for both archonPaths and configLoader
2. loader.test.ts uses spyOn instead of mock.module
3. This avoids polluting other test files (archon-paths.test.ts, config-loader.test.ts)

The spyOn approach works because:
- Both loader.ts and loader.test.ts import the modules as namespaces
- They share the same module instance in Bun's module cache
- spyOn modifies the shared namespace object

* fix: Use namespace imports in executor.ts for test mocking

Change executor.ts to use namespace imports for archon-paths and
config-loader, matching the fix already applied to loader.ts.

The previous fix commits (491fa94, c3a68dd) only updated loader.ts
but missed executor.ts, which has the same pattern of tests using
spyOn() that requires namespace imports to work correctly.

Changes:
- import * as archonPaths from '../utils/archon-paths'
- import * as configLoader from '../config/config-loader'
- Update all usage sites to use namespace prefix

* refactor: Prefix app defaults with archon-* and simplify override logic

Changes:
- Rename all default workflow files to archon-*.yaml
- Rename all default command files to archon-*.md
- Update workflow name: fields to match filenames
- Update command references in workflows to use archon-* names
- Simplify loader.ts to use exact filename match for overrides (not workflow name)
- Remove path mocking from tests - use real app defaults instead
- Simplify tests to be more reliable in CI

Benefits:
- No accidental collisions with user workflows/commands
- Clear intent when users override (must use exact filename)
- Simpler deduplication logic (filename-based)
- More reliable tests (no spyOn issues in CI parallel execution)

* feat: Add deprecation warning for old defaults and update docs

- Add warning in loader.ts when old non-prefixed defaults found in repo
- Update CLAUDE.md with migration instructions for old repos
- Document the archon-* prefix naming convention
- Document exact filename match override behavior

* docs: Move migration docs to docs/migration-guide.md

- Revert CLAUDE.md changes (keep it focused on development)
- Create dedicated migration guide for version upgrades
- Document runtime loading defaults migration steps
- Add commands for full fresh start cleanup

* docs: Add getting started section after cleanup

* docs: Fix stale references to command loading behavior

- Update CLAUDE.md to say 'auto-detected' instead of 'loaded via /clone (auto)'
- Clarify in architecture.md that defaults are loaded at runtime, not copied
- Update GitHub webhook flow to say 'detect and register' instead of 'load commands'

* refactor: Use early return in validateAppDefaultsPaths for cleaner flow

* fix: Improve error handling for silent failure cases

- Add ENOENT check to empty catch block in loader.ts (critical)
- Distinguish between 'not found' and other errors in validateAppDefaultsPaths
- Add errorType to config load fallback logging in loader.ts and executor.ts
2026-01-21 23:08:23 +02:00
Rasmus Widing
7fc0e2e837 docs: Add guide for adding webhooks to additional GitHub repos 2026-01-21 14:23:53 +02:00
Rasmus Widing
3b6b7ab69f
feat: Phase 4 - Express to Hono migration (#318)
* feat: Phase 4 - Express to Hono migration

Replace Express with Hono in @archon/server for improved performance
and better Bun integration. This is a focused HTTP layer migration
that preserves all existing API functionality.

Changes:
- Replace express with hono dependency
- Migrate all endpoints to Hono context-based handlers
- Use Bun.serve() for native Bun server integration
- Update optional parameter syntax from Express 5 to Hono style
- Remove express.json()/express.raw() middleware (Hono handles natively)
- Change default port from 3000 to 3090
- Update log prefixes from [Express] to [Hono]
- Update CLAUDE.md documentation references

All endpoints verified working:
- GET /health, /health/db, /health/concurrency
- POST /test/message, GET /test/messages/:id
- DELETE /test/messages/:id?, PUT /test/mode
- POST /webhooks/github (signature verification)

* refactor: Simplify Hono endpoint handlers

- Remove unnecessary try/catch from /health/concurrency endpoint
  (getStats() is a simple sync operation that doesn't need error handling)
- Remove outer try/catch from /test/message endpoint
  (validation returns early, processing is fire-and-forget with its own error handler)
- Consolidate validation checks with clearer error messages
- Reduce nesting depth for improved readability

Total: 12 lines removed while maintaining identical functionality

* docs: Update port references from 3000 to 3090 after Hono migration

* fix: Improve error handling in Hono endpoints

- Add global app.onError() handler for consistent unhandled exception responses
- Add explicit JSON parsing error handling to /test/message endpoint (returns 400 instead of 500)
- Add explicit JSON parsing error handling to /test/mode endpoint (was completely unhandled)
- Fix CLAUDE.md worktree port example to use correct port (3637 with base 3090)
2026-01-21 13:23:34 +02:00
Rasmus Widing
a28e695aee
feat: Phase 3 - Database abstraction layer and CLI isolation (#314)
* feat: Phase 3 - Database abstraction layer and CLI isolation

Part A: Database Abstraction Layer
- Add IDatabase interface supporting PostgreSQL and SQLite
- Create PostgresAdapter wrapping pg Pool with same interface
- Create SqliteAdapter using bun:sqlite with auto-schema init
- Add SqlDialect helpers for database-specific SQL generation
- Update connection.ts with auto-detection (DATABASE_URL → Postgres, else SQLite)
- Update isolation-environments.ts to use dialect helpers
- CLI now works without DATABASE_URL (uses ~/.archon/archon.db)

Part B: CLI Isolation Integration
- Add --branch/-b flag to create/reuse worktrees for workflows
- Add --no-worktree flag to run on branch directly without isolation
- Add isolation list command to show all active worktrees
- Add isolation cleanup command to remove stale environments
- Auto-register codebase when using --branch from git repo

New git utilities:
- findRepoRoot: Find git repository root from any path
- getRemoteUrl: Get origin remote URL
- checkout: Checkout branch (creating if needed)

* docs: Update documentation for Phase 3 - SQLite support and CLI isolation

* fix: Address all PR review issues for database abstraction

Critical fixes:
- Use dialect helpers (now(), jsonMerge, jsonArrayContains) in all DB operations
- Replace hardcoded PostgreSQL NOW(), ::jsonb, and JSON operators
- Add rowCount validation to updateStatus() and updateMetadata()
- Improve PostgreSQL pool error logging with structured context

Important fixes:
- Add explicit null check in getDialect() instead of non-null assertion
- Add warning for unsupported UPDATE/DELETE RETURNING in SQLite
- Throw error in extractTableName() on parse failure instead of empty string
- Track codebaseLookupError to provide clearer errors when --branch fails
- Couple IDatabase with SqlDialect via readonly sql property

Code simplifications:
- Extract loadWorkflows() helper to DRY duplicate error handling
- Fix N+1 query in getCodebases() by including repository_url in JOIN
- Cache sql.toUpperCase() to avoid redundant calls

All changes verified with:
- Type-check passes
- All 1082 tests pass
- CLI commands tested with both SQLite and PostgreSQL

* docs: Add SQLite support to getting-started, configuration, and architecture guides

* refactor: Simplify Phase 3 code for clarity and maintainability

- sqlite.ts: Remove unused UPDATE branch from extractTableName, consolidate
  RETURNING clause handling into single condition
- isolation.ts: Extract CodebaseInfo interface to reduce type duplication
- workflow.ts: Extract actualBranchName variable for clearer intent
- isolation-environments.ts: Rename variables for semantic clarity
  (staleActivityThreshold/staleCreationThreshold vs nowMinusDays1/2)

* fix: Address all remaining PR review issues

- SQLite: Throw error for UPDATE/DELETE RETURNING instead of warning
- SQLite: Replace deprecated db.exec() with db.run()
- Worktree: Throw for fatal errors (permission denied, not a git repo)
- Types: Add import type for type-only imports in 4 db modules
- Codebases: Add null check validation to createCodebase return
- WorkflowRunOptions: Add JSDoc documenting constraint behavior
- QueryResult: Add comment noting fields should be treated as readonly
- Connection: Improve getDialect() error message with actionable details

* fix: Complete type safety improvements for Phase 3

- QueryResult: Make rows and rowCount readonly to prevent mutation
- WorkflowRunOptions: Use discriminated union to prevent invalid states
  (noWorktree can only be set when branchName is provided)
- Update all database functions to return readonly arrays
- Fix CLI call site to properly construct options object

* fix: Add getDialect mock to database tests

Tests were failing because they expected hardcoded PostgreSQL SQL
(NOW(), metadata || $1::jsonb) but the code now uses dialect helpers.

- Add mockPostgresDialect to test/mocks/database.ts
- Update all db test files to mock getDialect() returning PostgreSQL dialect
- Tests now properly verify the SQL generated by dialect helpers
2026-01-21 10:38:57 +02:00
Rasmus Widing
cf06128e14
feat: Add workflow status visibility (#233) (#256)
* Investigate issue #233: Workflow state management visibility

* feat: Add workflow status visibility to /status and /workflow status (#233)

Users had no visibility into running workflows - they could only see "already running"
errors when attempting to start new workflows. This made it impossible to know what
was running, how long it had been active, or whether it was stuck.

Changes:
- Add workflow info to /status command (name, step, duration, activity)
- Add /workflow status subcommand for detailed workflow state
- Show staleness warnings (>5 min) and stale indicators (>15 min)
- Update help text to document new command

Fixes #233

* Archive investigation for issue #233

* docs: Add /workflow status command to documentation

* refactor: Improve workflow status error handling and code quality

- Extract calculateWorkflowTiming() helper to eliminate code duplication
- Add try-catch around workflow DB queries for graceful degradation
- Define WORKFLOW_SLOW_THRESHOLD_MS and WORKFLOW_STALE_THRESHOLD_MS constants
- Handle invalid date data gracefully (shows "timing unavailable")
- Prevent negative durations with Math.max(0, ...)
- Remove unnecessary String() wrappers in template literals
- Add tests for database error handling and invalid date scenarios
- Add test for /workflow help text including status subcommand
2026-01-19 16:06:58 +02:00