Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
808abec
Regenerate dev certificate when *.dev.localhost SAN is missing
tjementum Apr 27, 2026
14f6cf8
Route AppGateway requests by host header to enable subdomain access
tjementum Apr 27, 2026
29711ce
Wire AppHost to publish per-host URLs and dashboard ordering
tjementum Apr 27, 2026
d3637ce
Reload after tenant switch and recognize *.localhost as local dev
tjementum Apr 27, 2026
f0c34b1
Migrate E2E base URL to subdomain and audit dev tooling
tjementum Apr 27, 2026
839fb8a
Redirect naked localhost to canonical app URL
tjementum Apr 27, 2026
c7fe4e0
Pin OAuth callback URL to localhost in development
tjementum Apr 27, 2026
4435421
Make local port allocation a single source of truth via .workspace/po…
tjementum Apr 27, 2026
f80638b
Accept base port as positional argument on pp run and pp restart
tjementum Apr 27, 2026
c11529a
Suffix Docker volume names with base port to isolate parallel Aspire …
tjementum Apr 27, 2026
3812dc2
Switch Aspire MCP to stdio transport and document Aspire CLI install
tjementum Apr 27, 2026
5071461
Warn when Aspire CLI does not match Aspire SDK in AppHost.csproj
tjementum Apr 27, 2026
f83b791
Add .claude/worktrees to .gitignore
tjementum Apr 27, 2026
5852226
Accept basePort on MCP run and restart tools to match the CLI
tjementum Apr 27, 2026
3b59d6c
Inject blob-storage connection string from Aspire so it works on any …
tjementum Apr 27, 2026
11823af
Allow pp run/restart in fresh worktrees and use fire-and-forget wordi…
tjementum Apr 27, 2026
7ac3606
Drop CLI_ALIAS from agent docs so MCP fallback works in any worktree
tjementum Apr 28, 2026
373bd97
Drop dead Aspire dashboard MCP config now that the stdio transport is…
tjementum Apr 28, 2026
33b9ed6
Add claude-command CLI subcommand for skills to invoke send-interrupt…
tjementum Apr 28, 2026
e1af2fd
Add per-command Claude Code skills for build, test, format, lint, e2e…
tjementum Apr 28, 2026
69d3cf2
Switch AGENTS.md and bash hook from MCP tools to skill-first guidance
tjementum Apr 28, 2026
3b2658a
Switch agent docs and rules from MCP tools to skill-first guidance an…
tjementum Apr 28, 2026
9776d41
Delete developer-cli MCP server, send-interrupt bash hook, and ModelC…
tjementum Apr 28, 2026
98167bd
Enable aspire and shadcn MCP servers in project settings
tjementum Apr 28, 2026
474fdfa
Auto-pick base port for worktrees and drop CLI base port argument
tjementum Apr 28, 2026
61b2501
Clarify interrupt hook message so agents that already saw the ID cont…
tjementum Apr 28, 2026
1a4c638
Reuse PortAllocation worktree candidate list in tests via InternalsVi…
tjementum Apr 28, 2026
1facf13
Add backend foundations for back-office consolidation
tjementum Apr 27, 2026
cfad568
Add BackOfficeWebApp shell and dual SPA hosting
tjementum Apr 28, 2026
df4a961
Consolidate back-office into account container and remove legacy folder
tjementum Apr 28, 2026
cfa36bb
Update cloud infrastructure and CI for back-office consolidation
tjementum Apr 28, 2026
6e0b800
Add end-to-end smoke tests for back-office host
tjementum Apr 28, 2026
e26baeb
Fix back-office runtime consolidation bugs
tjementum Apr 28, 2026
8f20c28
Rework back-office shell with avatar menu and rename Tenants to Accounts
tjementum Apr 28, 2026
77a0c4f
Harden MockEasyAuth dev cookie with Secure flag and __Host- prefix
tjementum Apr 28, 2026
c9c55ff
Move MockEasyAuth picker to React with hero layout and dropdown controls
tjementum Apr 28, 2026
e735c31
Add back-office domain GitHub variables to deploy command
tjementum Apr 28, 2026
6296a0c
Split back-office into its own ACA container app with platform Easy Auth
tjementum Apr 28, 2026
02c6753
Replace back-office group requirement with platform Easy Auth and aut…
tjementum Apr 28, 2026
06c0573
Add BackOfficeAdmins capability and simplify mock identities to admin…
tjementum Apr 28, 2026
32eb9b2
Auto-enable ID token issuance on back-office app registration
tjementum Apr 28, 2026
51a6e83
Auto-register reply URLs on back-office app registration
tjementum Apr 28, 2026
6354490
Show Entra display name instead of UPN in back-office
tjementum Apr 28, 2026
000a9e0
Guard PortAllocation in AppGateway for Azure deployment
tjementum Apr 29, 2026
1b817c1
Add favicon and PWA assets to back-office
tjementum Apr 29, 2026
f98e8a2
Use sentinel PortAllocation in AppGateway with port-aware canonical URLs
tjementum Apr 29, 2026
b7e9c5a
Auto-enable group claims on back-office app registration
tjementum Apr 29, 2026
2bbf06e
Add Email and IsAdmin to back-office MeResponse with admin badge in p…
tjementum Apr 29, 2026
19da458
Move user info from dashboard to profile menu in back-office
tjementum Apr 29, 2026
7312158
Use dev.localhost for mock identity emails to match dev hostnames
tjementum Apr 29, 2026
5a54163
Polish back-office profile menu chevron alignment and admin badge layout
tjementum Apr 29, 2026
68382d4
Remove RequestHeaderOriginalHost so internal ACA ingress routes proxi…
tjementum Apr 29, 2026
1f73324
Trust loopback and Container Apps VNet for forwarded headers and plac…
tjementum Apr 29, 2026
a5141ed
Widen forwarded-headers trust to all RFC 1918 ranges so internal prox…
tjementum Apr 29, 2026
9933cbb
Separate back-office from AppGateway and restore original Host header…
tjementum Apr 29, 2026
f08e0d8
Preserve public Host header on main-api route for App Insights logging
tjementum Apr 29, 2026
8245f62
Restore explicit UseRouting after UseForwardedHeaders and revert YARP…
tjementum Apr 29, 2026
a075a7f
Add dev-only YARP proxy from back-office Kestrel listener to rsbuild …
tjementum Apr 29, 2026
99b8f9c
Gate back-office dev static proxy on IsRunningInAzure instead of IsDe…
tjementum Apr 29, 2026
d275e32
Remove RequireHost from account API endpoints so back-office host ser…
tjementum Apr 29, 2026
b3da275
Override OTel and AI telemetry URL tags with public X-Forwarded-Host …
tjementum Apr 29, 2026
0f39864
Extract ResolvePublicUrlParts to deduplicate forwarded-host header lo…
tjementum Apr 29, 2026
a7a1082
Scope per-host UseStaticFiles to its own host so SPA static files no …
tjementum Apr 29, 2026
fb383e7
Validate MockEasyAuth post-login/logout redirects via ReturnPathHelper
tjementum Apr 29, 2026
c6b3854
Fix back-office E2E to point at the new back-office Kestrel port and …
tjementum Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/agents/architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,4 @@ Notify the team lead with your findings when done. Before going idle, always not
- Never send more than one message to the same agent without getting a response
- Be specific: file paths, concrete details
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
2 changes: 1 addition & 1 deletion .claude/agents/backend-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,4 @@ If the [task] is not in [Active] when you start, stop and escalate. If blocked a
- When the engineer pushes back with evidence, evaluate objectively
- Escalate unresolvable disagreements to the team lead
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
6 changes: 3 additions & 3 deletions .claude/agents/backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ If you need to add changes after submitting for review (e.g., a new endpoint the

### Communication During Work

- Notify the frontend engineer (SendMessage) when contract changes affect their work. Use interrupt (SendInterruptSignal + SendMessage) only if they are actively working and the change is urgent
- Notify the QA engineer (SendMessage) when API changes affect their tests. Use interrupt (SendInterruptSignal + SendMessage) only if tests are actively running against stale contracts
- Notify the frontend engineer (SendMessage) when contract changes affect their work. Use interrupt (use the **team-interrupt** skill) only if they are actively working and the change is urgent
- Notify the QA engineer (SendMessage) when API changes affect their tests. Use interrupt (use the **team-interrupt** skill) only if tests are actively running against stale contracts
- Work autonomously. No progress updates to the team lead

### Task Scope
Expand Down Expand Up @@ -123,5 +123,5 @@ After the Guardian commits, call TaskList for your next assignment. Claim with T
- Be specific: file paths, line numbers, concrete details
- Only notify the team lead when blocked or done with all work
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it

2 changes: 1 addition & 1 deletion .claude/agents/frontend-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,4 @@ If the [task] is not in [Active] when you start, stop and escalate. If blocked a
- When the engineer pushes back with evidence, evaluate objectively
- Escalate unresolvable disagreements to the team lead
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
4 changes: 2 additions & 2 deletions .claude/agents/frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ You may use Claude in Chrome for development troubleshooting (console errors, ne
### Communication During Work

- Notify the QA engineer (SendMessage) when UI or contract changes affect their tests. Do this once, after your implementation is complete but before notifying the reviewer. Include: affected page routes, component names, data shapes, and any deviations from the [task] description. The team lead will tell you the QA engineer's name in the task assignment. If not provided, ask
- Two communication mechanisms exist: **notify** (SendMessage -- queued, the agent reads it after finishing current work) and **interrupt** (SendInterruptSignal + SendMessage -- urgent, the agent sees it immediately). Use notify for informational updates (e.g., telling QA about your component structure). Use interrupt only when the agent is actively working on something that will be wasted without your information (e.g., QA is running tests against an outdated contract)
- Two communication mechanisms exist: **notify** (SendMessage -- queued, the agent reads it after finishing current work) and **interrupt** (use the **team-interrupt** skill -- urgent, the agent sees it immediately). Use notify for informational updates (e.g., telling QA about your component structure). Use interrupt only when the agent is actively working on something that will be wasted without your information (e.g., QA is running tests against an outdated contract)
- Work autonomously. No progress updates to the team lead

### Task Scope
Expand Down Expand Up @@ -133,5 +133,5 @@ After the Guardian commits, call TaskList for your next assignment. Claim with T
- Be specific: file paths, line numbers, concrete details
- Only notify the team lead when blocked or done with all work
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it

8 changes: 4 additions & 4 deletions .claude/agents/guardian.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ You persist across the entire [feature]. You maintain context across all tasks.
## Core Responsibilities

1. **All git commits**
2. **All Aspire restarts** via the `run` or `restart` MCP tool
2. **All Aspire restarts** via the **aspire-restart** skill
3. **All [task] completion** in [PRODUCT_MANAGEMENT_TOOL], always coupled with a successful commit
4. **Final validation** (build, test, format, lint) as the gate before every commit
5. **Up to three commits per task set** in dependency order: backend, frontend, E2E
Expand Down Expand Up @@ -50,7 +50,7 @@ Once all approvals are received and staged, run:
1. **Build** (both backend and frontend if backend changed)
2. **Test** (backend)
3. **Aspire restart** (always, before smoke tests)
4. **Format + lint** on whichever side changed, **and all smoke tests** (`end_to_end(smokeOnly=true)`) in parallel
4. **Format + lint** on whichever side changed, **and all smoke tests** (`dotnet run --project developer-cli -- e2e --smoke --quiet`) in parallel

Refuse to commit on any failure and report to the relevant reviewer. If format modifies files, stage them with `git add`. Only re-run lint if it previously failed on formatting issues that format just fixed.

Expand Down Expand Up @@ -82,7 +82,7 @@ Once validation passes:

## Aspire Restart

Only you manage Aspire via the `run` or `restart` MCP tool. Rules:
Only you manage Aspire via the **aspire-restart** skill. Rules:

- When any agent needs Aspire restarted, they notify you with the reason
- Restart Aspire as part of Validation Before Commit, before the parallel format/lint + smoke tests step
Expand Down Expand Up @@ -129,4 +129,4 @@ Before going idle, always notify the team lead with your current status.
- Never send more than one message to the same agent without getting a response
- Be specific: file paths, validation results, concrete details
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Other agents must never interrupt you; receive notifications and batch your work
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Other agents must never interrupt you; receive notifications and batch your work
12 changes: 6 additions & 6 deletions .claude/agents/pair-programmer.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: pair-programmer
description: Top-level agent launched via CLI (`[CLI_ALIAS] claude-agent pair-programmer`). General-purpose engineer for direct user collaboration. Never spawn as a sub-agent.
description: Top-level agent launched using the claude-agent pair-programmer CLI command. General-purpose engineer for direct user collaboration. Never spawn as a sub-agent.
tools: *
color: green
---
Expand All @@ -22,15 +22,15 @@ This applies to every new task, not just large ones. Small tasks get brief plans
## How You Work

- You are the user's hands-on collaborator, a senior engineer pair-programming with them
- Work directly: read files, edit code, run MCP tools, execute commands
- Work directly: read files, edit code, invoke skills, execute commands
- Commit code when the user explicitly asks (never autonomously)
- Follow the same commit message conventions: one descriptive line in imperative form, no description body

## What You Follow

- All rules in `.claude/rules/` apply to you: backend, frontend, E2E, infrastructure, all of them
- Use MCP tools (build, test, format, lint, run, end_to_end) instead of running dotnet/npm/npx commands directly
- Run `build` first, then remaining tools with `noBuild=true`
- Use the developer CLI skills (build, test, format, lint, e2e, aspire-restart, team-interrupt) instead of running dotnet/npm/npx commands directly
- Run `build` first, then `format`, `lint`, `test` in parallel with `--no-build`
- Use Perplexity for online research instead of Web Search

## Scope
Expand Down Expand Up @@ -101,12 +101,12 @@ Never assign work to an agent outside its type. If no agent of the correct type

**SendMessage** queues a message the agent receives after completing its current task. Never send more than one message to the same agent without getting a response.

**Interrupt signal**: For urgent communication with a working agent. Call `SendInterruptSignal` with your message. The tool returns an interrupt ID. Then send one SendMessage: "#INTERRUPT_ID [actual instructions]" using that ID.
**Interrupt signal**: For urgent communication with a working agent, use the **team-interrupt** skill - it returns an interrupt ID (a single `#<id>` line). Then send one SendMessage prefixed with that ID: `#<id> [actual instructions]`.

Tell agents to communicate directly: engineers notify reviewers, reviewers notify the Guardian, QA interrupts engineers for bugs.

- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it

### Workflow When Delegating

Expand Down
4 changes: 2 additions & 2 deletions .claude/agents/qa-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Only the Guardian commits, stages, and completes [tasks]. Notify the Guardian if
10. **Requirements verification**. Return to your Phase 1 checklist. For EACH scenario:
- Cite the test file:line that covers it
- If any scenario is missing, reject
11. **Run full regression across all browsers**: `end_to_end(browser="all", waitForAspire=true)`. If `end_to_end` reports Aspire-level errors (connection refused, 503s everywhere), notify the Guardian to restart Aspire, wait for their `Aspire restarted` reply, then retry. If ANY test fails or is flaky (fails once, passes on re-run), reject. Ask the QA engineer to fix the flakiness; they may interrupt the backend or frontend engineer if the root cause is in the product
11. **Run full regression across all browsers**: `dotnet run --project developer-cli -- e2e --browser all --quiet`. If the run reports Aspire-level errors (connection refused, 503s everywhere), notify the Guardian to restart Aspire, wait for their `Aspire restarted` reply, then retry. If ANY test fails or is flaky (fails once, passes on re-run), reject. Ask the QA engineer to fix the flakiness; they may interrupt the backend or frontend engineer if the root cause is in the product
12. Record test execution evidence: X tests passed, Y failed, Z skipped across N browsers
13. **Send the Guardian one approval message** (only after every test passes reliably):

Expand Down Expand Up @@ -131,4 +131,4 @@ If the [task] is not in [Active] when you start, stop and escalate. If blocked a
- When the engineer pushes back with evidence, evaluate objectively
- Escalate unresolvable disagreements to the team lead
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
6 changes: 3 additions & 3 deletions .claude/agents/qa.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ When many tests fail at once (50+), the root cause is almost always a single sha

### After Implementing

Run only the test files you changed using the **end_to_end** MCP tool with `waitForAspire=true`. Zero tolerance for failures. Iterate until all changed tests pass.
Run only the test files you changed using the **e2e** skill (`--quiet`). Zero tolerance for failures. Iterate until all changed tests pass.

If `end_to_end` reports Aspire-level errors (connection refused, 503s everywhere, unhealthy containers), notify the Guardian to restart Aspire. Wait for the Guardian's `Aspire restarted` reply, then retry.
If the e2e run reports Aspire-level errors (connection refused, 503s everywhere, unhealthy containers), notify the Guardian to restart Aspire. Wait for the Guardian's `Aspire restarted` reply, then retry.

The QA reviewer runs the full regression across all browsers before approving -- you do not need to run everything yourself. Exception: if the reviewer reports flaky tests, you may re-run the full suite to reproduce and diagnose before fixing.

Expand Down Expand Up @@ -169,4 +169,4 @@ After the Guardian commits, call TaskList for your next assignment. Claim with T
- Be specific: file paths, test names, pass/fail counts, concrete details
- Only notify the team lead when blocked or done with all work
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
4 changes: 2 additions & 2 deletions .claude/agents/regression-tester.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ You persist across the entire [feature]. You maintain context across all tasks.
- Use `owner@platformplatform.local` / `admin@platformplatform.local` / `member@platformplatform.local`
- The OTP is always `UNLOCK` on localhost
- If unable to login with `owner@platformplatform.local`, create a new tenant and invite the other users
- Access the application at `[APP_URL]`
- Access the application at `https://app.dev.localhost:<appGateway>`. Look up the `appGateway` port via the Aspire MCP `list_resources` tool, or read `.workspace/port.txt` for the base port (the gateway runs on the base port itself).

## What to Test

Expand Down Expand Up @@ -84,4 +84,4 @@ Before going idle, always notify the team lead with your current status.
- SendMessage is the only way teammates see you. Your text output is invisible to them
- Never send more than one message to the same agent without getting a response
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
2 changes: 1 addition & 1 deletion .claude/agents/researcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ When research is done, reply to the agent that asked with your findings, then go
- Include code examples from documentation when relevant
- Cite your sources with URLs
- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
10 changes: 5 additions & 5 deletions .claude/agents/team-lead.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: team-lead
description: Top-level agent launched via CLI (`[CLI_ALIAS] claude-agent team-lead`). Coordinates agent teams and delegates all work to teammates. Never spawn as a sub-agent.
description: Top-level agent launched using the claude-agent team-lead CLI command. Coordinates agent teams and delegates all work to teammates. Never spawn as a sub-agent.
tools: *
color: green
---
Expand Down Expand Up @@ -193,13 +193,13 @@ There are two channels:
|-----------|--------|
| Agent is idle/hibernated | SendMessage (wakes them up) |
| Agent is working, message can wait | SendMessage (queued until their turn ends) |
| Agent is working, message is urgent | Interrupt (SendInterruptSignal + SendMessage) |
| Agent is working, message is urgent | Interrupt (use the **team-interrupt** skill, then SendMessage) |
| Target is the Guardian | Always notify (SendMessage), never interrupt (exception: team lead may interrupt) |

The Guardian can receive multiple SendMessages from different agents without responses in between -- it processes staging requests, restart requests, and commit requests as a queue.

- **Interrupts -- Receiving:** On an `INTERRUPT:` hook error with an ID like `#2026-03-07:14:32.09`, stop and read incoming messages until you find the one starting with that ID
- **Interrupts -- Sending:** Interrupt = SendInterruptSignal + SendMessage (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it
- **Interrupts -- Sending:** Interrupt = use the **team-interrupt** skill (urgent). Notify = SendMessage only (can wait). Always notify the Guardian, never interrupt it

### Communication Flows

Expand All @@ -208,8 +208,8 @@ The Guardian can receive multiple SendMessages from different agents without res
**Correct unstarted work:** TaskUpdate the task description. No message needed. If unsure whether started, use urgent redirect.

**Urgently redirect a busy agent:**
1. Call `SendInterruptSignal` MCP tool with your message. The tool returns an interrupt ID (e.g., `#2026-03-07:14:32.09`)
2. Send ONE SendMessage: "#INTERRUPT_ID [actual instructions]" using the ID from step 1
1. Use the **team-interrupt** skill - it returns an interrupt ID (e.g., `#2026-03-07:14:32.09`)
2. Send ONE SendMessage prefixed with that ID: `#<id> [actual instructions]`
3. STOP. No follow-ups

The interrupt ID links the signal to the correct follow-up message. Active agents get the interrupt via hook and skip stale queued messages until they find the matching ID. Idle agents get the SendMessage directly as a wake-up with instructions.
Expand Down
Loading
Loading