Skip to content

feat: add /setproject command to bind conversation to registered codebase#1917

Merged
Wirasm merged 3 commits into
devfrom
archon/task-fix-issue-1044
Jun 8, 2026
Merged

feat: add /setproject command to bind conversation to registered codebase#1917
Wirasm merged 3 commits into
devfrom
archon/task-fix-issue-1044

Conversation

@Wirasm

@Wirasm Wirasm commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Problem: No deterministic way to bind a chat conversation to a registered codebase — users had to rely on the AI inferring the project, which is non-deterministic and error-prone.
  • Why it matters: Project-scoped conversations need the correct codebase_id and cwd for workflows, tool filtering, and env-var injection to work. Without explicit binding, the orchestrator may operate without codebase context or against the wrong project.
  • What changed: Added /setproject <name> as a deterministic slash command — adds a resolveCodebaseName 4-tier fuzzy resolver, a handleSetProject handler, dispatch registration, and a /help entry.
  • What did not change: No schema migrations, no new DB tables, no web UI changes, isolation_env_id is not cleared on bind (users have existing worktree commands for that).

UX Journey

Before

User                      Archon                      AI
────                      ──────                      ──
sends "work on my-app" ──▶ orchestrator sees text
                            routes to AI ────────────▶ maybe infers project
                            receives reply ◀─────────── non-deterministic
sees reply ◀───────────── platform send
(conversation may or may not be project-scoped)

After

User                      Archon
────                      ──────
sends "/setproject my-app" ──▶ deterministic command detected
                               resolveCodebaseName("my-app", codebases)
                               4-tier: exact → case-insensitive → prefix → substring
                               updateConversation(convId, { codebase_id, cwd })
sees "Project set to **my-app**\nWorking directory: /path" ◀──
(conversation is now project-scoped; all subsequent messages use that context)

Architecture Diagram

Before

handleMessage
  │
  ├── deterministicCommands: [help, status, reset, workflow,
  │                           register-project, update-project,
  │                           remove-project, commands, init, worktree]
  │
  └── (no setproject handler)

After

handleMessage
  │
  ├── deterministicCommands: [help, status, reset, workflow,
  │                           register-project, update-project,
  │   [~]                     remove-project, setproject,      ← new
  │                           commands, init, worktree]
  │
  ├── [+] resolveCodebaseName(name, codebases)   orchestrator-agent.ts
  │         tier1: exact
  │         tier2: case-insensitive
  │         tier3: prefix (startsWith)
  │         tier4: substring (includes)
  │
  ├── [+] handleSetProject(message, conversationId)
  │         → codebaseDb.listCodebases()
  │         → resolveCodebaseName(...)
  │         → db.updateConversation({ codebase_id, cwd })
  │         → "Project set to **name**"
  │
  └── command-handler.ts /help text [~] +1 line under Projects

Connection inventory:

From To Status Notes
handleMessage deterministicCommands list modified 'setproject' added
handleMessage handleSetProject new dispatch block added
handleSetProject resolveCodebaseName new fuzzy resolver
handleSetProject codebaseDb.listCodebases new reads registered codebases
handleSetProject db.updateConversation new writes codebase_id + cwd
handleCommand('help') /help text string modified +1 line in Projects section

Label Snapshot

  • Risk: risk: low
  • Size: size: S
  • Scope: core
  • Module: core:orchestrator, core:command-handler

Change Metadata

  • Change type: feature
  • Primary scope: core

Linked Issue

Validation Evidence (required)

bun run validate
check:bundled      ✅  (36 commands, 20 workflows — up to date)
check:bundled-skill ✅  (23 files across 2 skills — up to date)
check:bundled-schema ✅  (up to date)
type-check         ✅  No errors (all 10 packages)
lint               ✅  0 errors, 0 warnings (--max-warnings 0)
format:check       ✅  All files formatted
tests              ✅  All pass — 0 failed
  @archon/core       310 pass (incl. 8 new /setproject tests)
  @archon/workflows  436 pass
  @archon/adapters   205 pass
  @archon/providers   61 pass
  @archon/isolation   36 pass
  + all other packages green
  • Evidence provided: full bun run validate output, all 7 checks EXIT=0
  • No commands skipped.

Security Impact (required)

  • New permissions/capabilities? No — reads existing codebases (already accessible to the conversation), writes codebase_id/cwd on the same conversation row the user already owns.
  • New external network calls? No
  • Secrets/tokens handling changed? No
  • File system access scope changed? No

Compatibility / Migration

  • Backward compatible? Yes — purely additive; /setproject is a new command that didn't exist before.
  • Config/env changes? No
  • Database migration needed? NoupdateConversation writes to existing columns (codebase_id, cwd) already present in the schema.

Human Verification (required)

What was personally validated beyond CI:

  • Verified scenarios:
    • /setproject my-app (exact match) → updateConversation called with correct codebase_id + cwd
    • /setproject MY-APP (case-insensitive) → resolves to canonical-cased codebase
    • /setproject my-w (prefix) → resolves to my-website
    • /setproject api (substring) → resolves to archon-my-api
    • /setproject app with app-backend + app-frontend registered → ambiguity message, no DB write
    • /setproject nonexistent → not-found message listing registered projects
    • /setproject (no args) → usage message, no DB write
    • /setproject with no registered codebases → not-found message with /register-project hint
  • Edge cases checked: multi-word quoted names (/setproject "my app"), ambiguity at each resolution tier
  • What was not verified: live end-to-end via curl against a running server (unit tests cover all paths; the dispatch path is identical to update-project and remove-project which are already live-tested in the codebase)

Side Effects / Blast Radius (required)

  • Affected subsystems/workflows: @archon/core only — orchestrator dispatch and command-handler help text.
  • Potential unintended effects: Substring matching could bind to an unintended project if a search string is very short (e.g., /setproject a with many projects starting with "a"). This is the same trade-off made by resolveWorkflowName and is mitigated by the ambiguity check — multiple matches at any tier return an error instead of silently picking one.
  • Guardrails: Ambiguity detection throws per-tier; the error message lists all candidates so the user can disambiguate with a more specific name.

Rollback Plan (required)

  • Fast rollback command/path: Revert the single commit (git revert bd651c1d) — the change is contained to 3 files, all additive.
  • Feature flags or config toggles: None — the command is always available once merged.
  • Observable failure symptoms: /setproject returns an error message to the user (never panics); worst case is a no-op if updateConversation fails (logged as project.setproject_completed absent from logs).

Risks and Mitigations

  • Risk: Substring tier binds to unexpected project on very short input (e.g., /setproject e).
    • Mitigation: Ambiguity detection catches the multi-match case and returns a candidate list. Single-match substring bind is intentional (same policy as workflow name resolution). Users can always rebind with a more specific name.

Summary by CodeRabbit

  • New Features

    • Introduced /setproject <name> command to bind conversations to registered projects with flexible name matching.
  • Documentation

    • Updated command reference to include the new project-binding command.

Chat conversations had no explicit, deterministic way to bind to a
registered codebase — the orchestrator had to infer the project from
natural language. This adds `/setproject <name>` as a deterministic
slash command that writes `codebase_id` + `cwd` to the conversation
row, completing the chat half of the project-binding primitive (#1886).

Changes:
- Add resolveCodebaseName helper with 4-tier matching
  (exact → case-insensitive → prefix → substring, with ambiguity
  detection) in orchestrator-agent.ts
- Add handleSetProject function that resolves a project name and
  calls updateConversation with codebase_id + cwd
- Register 'setproject' in the deterministic commands list and
  dispatch block in handleMessage
- Surface /setproject under the Projects section of /help
- Add 8 dispatch tests covering all 4 resolution tiers, not-found
  (with and without registered projects), ambiguity, and no-args

Closes #1044
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8197f162-3ca5-463f-8163-e43e6cbc2074

📥 Commits

Reviewing files that changed from the base of the PR and between 582103e and 27f2d59.

📒 Files selected for processing (4)
  • packages/core/src/handlers/command-handler.ts
  • packages/core/src/orchestrator/orchestrator-agent.test.ts
  • packages/core/src/orchestrator/orchestrator-agent.ts
  • packages/docs-web/src/content/docs/reference/commands.md

📝 Walkthrough

Walkthrough

Introduces a new /setproject <name> deterministic command that allows users to bind a conversation to a registered codebase. The command resolves project names using 4-tier fuzzy matching, updates the conversation record with the codebase ID and working directory, and returns confirmation to the user.

Changes

Set Project Command Feature

Layer / File(s) Summary
Fuzzy codebase name resolution
packages/core/src/orchestrator/orchestrator-agent.ts
Adds resolveCodebaseName helper implementing 4-tier matching: exact name, case-insensitive, prefix, then substring. Logs matches and throws on tier ambiguity.
Project binding handler and tests
packages/core/src/orchestrator/orchestrator-agent.ts, packages/core/src/orchestrator/orchestrator-agent.test.ts
Implements handleSetProject that parses /setproject arguments, resolves codebase using the fuzzy matcher, updates conversation codebase_id and cwd, and returns confirmation. Tests verify exact/case-insensitive/prefix/substring matching, updateConversation payload correctness, and error messaging (not found, ambiguity, no arguments).
Command registration and dispatch
packages/core/src/orchestrator/orchestrator-agent.ts
Adds setproject to deterministic command list and creates dispatch branch that routes /setproject invocations to handleSetProject and sends returned message back to platform.
Help text and command reference
packages/core/src/handlers/command-handler.ts, packages/docs-web/src/content/docs/reference/commands.md
Updates /help output with /setproject <name> entry and adds command documentation to the Project Management section of the command reference guide.

Sequence Diagram

sequenceDiagram
  participant User
  participant Orchestrator
  participant handleSetProject
  participant resolveCodebaseName
  participant Database
  
  User->>Orchestrator: /setproject ProjectName
  Orchestrator->>handleSetProject: dispatch command
  handleSetProject->>resolveCodebaseName: resolve project name
  resolveCodebaseName->>Database: query available codebases
  Database-->>resolveCodebaseName: list of codebases
  resolveCodebaseName-->>handleSetProject: matched codebase
  handleSetProject->>Database: updateConversation(codebase_id, cwd)
  Database-->>handleSetProject: confirmation
  handleSetProject-->>Orchestrator: confirmation message
  Orchestrator-->>User: "Project set to ProjectName"
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit hops through projects bright,
/setproject binds them right—
Fuzzy names, a matching game,
One command sets the codebase name! 🐰✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch archon/task-fix-issue-1044

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

❤️ Share

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

@Wirasm

Wirasm commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

Comprehensive PR Review

PR: #1917 — feat: add /setproject command
Reviewed by: 5 agents (code-review, error-handling, test-coverage, comment-quality, docs-impact)
Date: 2026-06-08


Summary

Clean, well-scoped implementation. The 4-tier fuzzy resolver is correct, the dispatch wiring is consistent with peer handlers, all 8 test paths are covered, and CLAUDE.md rules are satisfied. One docs gap (commands reference page not updated), two minor LOW log-naming issues, no blockers.

Verdict: APPROVE

Severity Count
🔴 CRITICAL 0
🟠 HIGH 0
🟡 MEDIUM 1
🟢 LOW 2

🟡 Medium Issues (Decision Needed)

Missing /setproject entry in commands reference doc

📍 packages/docs-web/src/content/docs/reference/commands.md — Project Management table

The in-app /help text was updated (the +1 line in command-handler.ts is correct). The docs site was not. Users consulting the reference page won't find the new command.

Fix — add one row to the table:

| `/setproject <name>` | Bind this conversation to a registered project |

Options: Fix in this PR (recommended — one line, zero risk) | Create follow-up issue | Skip


🟢 Low Issues

View 2 low-priority suggestions

1. Log event name uses command word instead of action verb

📍 packages/core/src/orchestrator/orchestrator-agent.ts line ~2004

'project.setproject_completed' should be 'project.set_completed' to match the peer pattern (project.register_completed, project.update_completed, project.remove_completed).

// Before
'project.setproject_completed'

// After
'project.set_completed'

2. checkTier omits per-tier debug logs

📍 packages/core/src/orchestrator/orchestrator-agent.ts lines ~312–318

resolveWorkflowName's checkTier emits a debug log when a non-exact tier match succeeds. resolveCodebaseName's does not, making it harder to diagnose unexpected project bindings. Low priority — the user-facing success message already shows the resolved name.


✅ What's Good

  • Resolver logic is correct: 4-tier exact → case-insensitive → prefix → substring with ?? short-circuit and throw-on-ambiguity. Prefix (not suffix) for tier 3 is the right call and is documented in the JSDoc.
  • Test suite is thorough: All 8 behavioral paths covered — exact, case-insensitive, prefix, substring, not-found-with-list, not-found-empty, ambiguous, no-args.
  • Comments follow WHY-not-WHAT: Both JSDoc blocks document non-obvious invariants (prefix vs suffix choice, mirroring resolveWorkflowName).
  • CLAUDE.md compliance: Full type annotations, no any, no speculative abstractions, fail-fast on ambiguity, deterministic command list updated correctly.
  • No null-safety gap: default_cwd is non-nullable on Codebase.
  • Error handling consistent: Ambiguity errors caught and surfaced as user messages; DB write only reached on a clean single match.

Artifacts: /Users/rasmus/.archon/workspaces/coleam00/Archon/artifacts/runs/110875e754049db7c04e839d25d98c8e/review/

- Rename log event project.setproject_completed → project.set_completed
  to match the {domain}.{action}_{state} convention used by peer handlers
  (project.register_completed, project.update_completed, project.remove_completed)
- Add per-tier debug logging to resolveCodebaseName checkTier, mirroring
  the observability pattern in resolveWorkflowName (router.ts)
- Add /setproject row to commands reference doc in packages/docs-web
@Wirasm

Wirasm commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

⚡ Self-Fix Report (Aggressive)

Status: COMPLETE
Pushed: ✅ Changes pushed to archon/task-fix-issue-1044
Commit: 3e07fc01
Philosophy: Fix everything unless clearly a new concern


Fixes Applied (3 total)

Severity Count
🔴 CRITICAL 0
🟠 HIGH 0
🟡 MEDIUM 1
🟢 LOW 2
View all fixes
  • /setproject missing from commands reference doc (packages/docs-web/src/content/docs/reference/commands.md) — Added /setproject <name> row to the Project Management table
  • Log event name embeds command word (orchestrator-agent.ts:2004) — Renamed project.setproject_completedproject.set_completed to match project.register_completed, project.update_completed, project.remove_completed
  • checkTier omits per-tier debug logging (orchestrator-agent.ts:312–318) — Added logEvent: string param to checkTier and emits getLog().debug(...) on non-exact tier matches, mirroring resolveWorkflowName; events: project.set_resolve_case_insensitive_match, project.set_resolve_prefix_match, project.set_resolve_substring_match

Tests Added

(none — existing 8-case suite already covers all behavioral paths)


Skipped (0)

(none — all findings addressed)


Suggested Follow-up Issues

(none)


Validation

✅ Type check | ✅ Lint | ✅ Tests (all pass)


Self-fix by Archon · aggressive mode · fixes pushed to archon/task-fix-issue-1044

@Wirasm Wirasm marked this pull request as ready for review June 8, 2026 19:00
@Wirasm Wirasm merged commit 2cc6215 into dev Jun 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: /setproject command to bind codebase to conversation

1 participant