@cluesmith/codev 2.1.0-rc.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dashboard/dist/assets/index-CUjY8HZv.css +32 -0
  2. package/dashboard/dist/assets/{index-PDBY4L6b.js → index-HdzAypSC.js} +42 -45
  3. package/dashboard/dist/assets/index-HdzAypSC.js.map +1 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/dist/agent-farm/cli.js +1 -1
  6. package/dist/agent-farm/cli.js.map +1 -1
  7. package/dist/agent-farm/commands/open.d.ts.map +1 -1
  8. package/dist/agent-farm/commands/open.js +7 -5
  9. package/dist/agent-farm/commands/open.js.map +1 -1
  10. package/dist/agent-farm/db/index.d.ts.map +1 -1
  11. package/dist/agent-farm/db/index.js +12 -0
  12. package/dist/agent-farm/db/index.js.map +1 -1
  13. package/dist/agent-farm/db/schema.d.ts +1 -1
  14. package/dist/agent-farm/db/schema.d.ts.map +1 -1
  15. package/dist/agent-farm/db/schema.js +1 -0
  16. package/dist/agent-farm/db/schema.js.map +1 -1
  17. package/dist/agent-farm/servers/send-buffer.d.ts.map +1 -1
  18. package/dist/agent-farm/servers/send-buffer.js +4 -3
  19. package/dist/agent-farm/servers/send-buffer.js.map +1 -1
  20. package/dist/agent-farm/servers/tower-cron.js +4 -2
  21. package/dist/agent-farm/servers/tower-cron.js.map +1 -1
  22. package/dist/agent-farm/servers/tower-instances.d.ts +1 -1
  23. package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
  24. package/dist/agent-farm/servers/tower-instances.js +2 -2
  25. package/dist/agent-farm/servers/tower-instances.js.map +1 -1
  26. package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
  27. package/dist/agent-farm/servers/tower-routes.js +27 -49
  28. package/dist/agent-farm/servers/tower-routes.js.map +1 -1
  29. package/dist/agent-farm/servers/tower-terminals.d.ts +1 -1
  30. package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
  31. package/dist/agent-farm/servers/tower-terminals.js +11 -8
  32. package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
  33. package/dist/agent-farm/servers/tower-types.d.ts +1 -0
  34. package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
  35. package/dist/agent-farm/utils/config.d.ts +1 -1
  36. package/dist/agent-farm/utils/config.d.ts.map +1 -1
  37. package/dist/agent-farm/utils/config.js +2 -2
  38. package/dist/agent-farm/utils/config.js.map +1 -1
  39. package/dist/cli.js +1 -1
  40. package/dist/cli.js.map +1 -1
  41. package/dist/commands/consult/index.d.ts +21 -1
  42. package/dist/commands/consult/index.d.ts.map +1 -1
  43. package/dist/commands/consult/index.js +49 -7
  44. package/dist/commands/consult/index.js.map +1 -1
  45. package/dist/terminal/pty-session.d.ts +3 -0
  46. package/dist/terminal/pty-session.d.ts.map +1 -1
  47. package/dist/terminal/pty-session.js +7 -0
  48. package/dist/terminal/pty-session.js.map +1 -1
  49. package/package.json +1 -1
  50. package/skeleton/protocols/air/builder-prompt.md +69 -0
  51. package/skeleton/protocols/air/consult-types/impl-review.md +58 -0
  52. package/skeleton/protocols/air/consult-types/pr-review.md +58 -0
  53. package/skeleton/protocols/air/prompts/implement.md +89 -0
  54. package/skeleton/protocols/air/prompts/pr.md +98 -0
  55. package/skeleton/protocols/air/protocol.json +109 -0
  56. package/skeleton/protocols/air/protocol.md +88 -0
  57. package/skeleton/resources/risk-triage.md +111 -0
  58. package/skeleton/resources/workflow-reference.md +14 -6
  59. package/skeleton/roles/architect.md +62 -12
  60. package/dashboard/dist/assets/index-D7YYtcVQ.css +0 -32
  61. package/dashboard/dist/assets/index-PDBY4L6b.js.map +0 -1
@@ -0,0 +1,98 @@
1
+ # PR Phase Prompt
2
+
3
+ You are executing the **PR** phase of the AIR protocol.
4
+
5
+ ## Your Goal
6
+
7
+ Create a pull request with the review embedded in the PR body, optionally run CMAP, and notify the architect.
8
+
9
+ ## Context
10
+
11
+ - **Issue**: #{{issue.number}} — {{issue.title}}
12
+ - **Current State**: {{current_state}}
13
+
14
+ ## Process
15
+
16
+ ### 1. Create the Pull Request
17
+
18
+ Create a PR that links to the issue. The PR body IS the review — include a summary, key decisions, and test plan:
19
+
20
+ ```bash
21
+ gh pr create --title "[Air #{{issue.number}}] feat: <brief description>" --body "$(cat <<'EOF'
22
+ ## Summary
23
+
24
+ <1-2 sentence description of the feature>
25
+
26
+ Implements #{{issue.number}}
27
+
28
+ ## What Changed
29
+
30
+ <Brief explanation of the implementation approach>
31
+
32
+ ## Key Decisions
33
+
34
+ <Any notable decisions made during implementation, or "None — straightforward implementation">
35
+
36
+ ## Test Plan
37
+
38
+ - [ ] Unit tests added
39
+ - [ ] Build passes
40
+ - [ ] All tests pass
41
+
42
+ ## Review Notes
43
+
44
+ <Anything the reviewer should pay special attention to, or "Standard implementation — no special concerns">
45
+ EOF
46
+ )"
47
+ ```
48
+
49
+ **IMPORTANT**: Do NOT create a review file in `codev/reviews/`. The PR body IS the review for AIR.
50
+
51
+ ### 2. Optional CMAP Review
52
+
53
+ If the implementation is non-trivial, run 3-way consultation:
54
+
55
+ ```bash
56
+ consult -m gemini --protocol air --type pr &
57
+ consult -m codex --protocol air --type pr &
58
+ consult -m claude --protocol air --type pr &
59
+ ```
60
+
61
+ All three should run in the background (`run_in_background: true`).
62
+
63
+ **This is optional** — use your judgement. For simple features (config changes, small UI additions), you may skip consultation. For features touching core logic or multiple modules, run it.
64
+
65
+ ### 3. Address Feedback (if CMAP was run)
66
+
67
+ If you ran CMAP:
68
+ - Wait for all consultations to complete
69
+ - Record each model's verdict
70
+ - Fix any issues identified
71
+ - Push updates to the PR branch
72
+
73
+ ### 4. Notify Architect
74
+
75
+ Send notification with PR link:
76
+
77
+ ```bash
78
+ af send architect "PR #<number> ready for review (implements issue #{{issue.number}})"
79
+ ```
80
+
81
+ If CMAP was run, include verdicts:
82
+ ```bash
83
+ af send architect "PR #<number> ready for review (implements issue #{{issue.number}}). CMAP: gemini=<verdict>, codex=<verdict>, claude=<verdict>"
84
+ ```
85
+
86
+ ## Signals
87
+
88
+ When PR is created and ready for review:
89
+
90
+ ```
91
+ <signal>PHASE_COMPLETE</signal>
92
+ ```
93
+
94
+ If you're blocked:
95
+
96
+ ```
97
+ <signal>BLOCKED:reason goes here</signal>
98
+ ```
@@ -0,0 +1,109 @@
1
+ {
2
+ "$schema": "../../protocol-schema.json",
3
+ "name": "air",
4
+ "version": "1.0.0",
5
+ "description": "AIR: Autonomous Implement & Review — lightweight protocol for small features from GitHub Issues",
6
+ "input": {
7
+ "type": "github-issue",
8
+ "required": false,
9
+ "default_for": ["--issue", "-i"]
10
+ },
11
+ "hooks": {
12
+ "pre-spawn": {
13
+ "collision-check": true,
14
+ "comment-on-issue": "On it! Implementing this feature now."
15
+ }
16
+ },
17
+ "phases": [
18
+ {
19
+ "id": "implement",
20
+ "name": "Implement",
21
+ "description": "Implement the feature and add tests",
22
+ "type": "once",
23
+ "steps": [
24
+ "read_issue",
25
+ "implement_feature",
26
+ "add_tests",
27
+ "verify_build",
28
+ "commit"
29
+ ],
30
+ "checks": {
31
+ "build": {
32
+ "command": "npm run build",
33
+ "on_fail": "retry",
34
+ "max_retries": 2
35
+ },
36
+ "tests": {
37
+ "command": "npm test -- --exclude='**/e2e/**'",
38
+ "description": "Unit tests only - e2e tests run in PR phase",
39
+ "on_fail": "retry",
40
+ "max_retries": 2
41
+ }
42
+ },
43
+ "transition": {
44
+ "on_complete": "pr",
45
+ "on_too_complex": "escalate"
46
+ }
47
+ },
48
+ {
49
+ "id": "pr",
50
+ "name": "Create PR",
51
+ "description": "Create pull request with review in PR body",
52
+ "type": "once",
53
+ "steps": [
54
+ "create_pr",
55
+ "link_issue",
56
+ "optional_consultation",
57
+ "notify_architect"
58
+ ],
59
+ "consultation": {
60
+ "on": "review",
61
+ "models": ["gemini", "codex"],
62
+ "type": "impl",
63
+ "parallel": true,
64
+ "max_rounds": 1
65
+ },
66
+ "checks": {
67
+ "pr_exists": {
68
+ "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'",
69
+ "description": "PR must be created before signaling completion"
70
+ },
71
+ "e2e_tests": {
72
+ "command": "npm run test:e2e 2>&1 || echo 'e2e tests skipped (not configured)'",
73
+ "description": "Full e2e test suite",
74
+ "optional": true
75
+ }
76
+ },
77
+ "gate": "pr",
78
+ "transition": {
79
+ "on_complete": null
80
+ }
81
+ }
82
+ ],
83
+ "signals": {
84
+ "PHASE_COMPLETE": {
85
+ "description": "Signal current phase is complete",
86
+ "transitions_to": "next_phase"
87
+ },
88
+ "TOO_COMPLEX": {
89
+ "description": "Feature is too complex for AIR, escalate to ASPIR",
90
+ "transitions_to": "escalate"
91
+ },
92
+ "BLOCKED": {
93
+ "description": "Signal implementation is blocked",
94
+ "requires": "reason"
95
+ }
96
+ },
97
+ "defaults": {
98
+ "mode": "strict",
99
+ "consultation": {
100
+ "enabled": true,
101
+ "models": ["gemini", "codex"],
102
+ "parallel": true
103
+ },
104
+ "checks": {
105
+ "build": "npm run build",
106
+ "test": "npm test"
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,88 @@
1
+ # AIR Protocol
2
+
3
+ > **AIR** = **A**utonomous **I**mplement & **R**eview
4
+ >
5
+ > A lightweight protocol for small features that are fully specified by their GitHub issue.
6
+ > Two phases: Implement → Review. No spec/plan artifacts.
7
+
8
+ ## What is AIR?
9
+
10
+ AIR is a minimal protocol for implementing small features (< 300 LOC) where the GitHub issue provides all the requirements. It skips the Specify and Plan phases entirely — the builder implements directly from the issue and creates a PR with the review embedded in the PR body.
11
+
12
+ ### How AIR Compares
13
+
14
+ | Aspect | BUGFIX | AIR | ASPIR/SPIR |
15
+ |--------|--------|-----|------------|
16
+ | **Use case** | Bug fixes | Small features | New features |
17
+ | **Input** | GitHub Issue | GitHub Issue | GitHub Issue → Spec |
18
+ | **Phases** | Investigate → Fix → PR | Implement → PR | Specify → Plan → Implement → Review |
19
+ | **Artifacts** | None | None | Spec, plan, review files |
20
+ | **Review location** | PR body | PR body | `codev/reviews/` file |
21
+ | **Consultation** | PR phase only | Optional (builder decides) | Every phase (3-way) |
22
+ | **Human gates** | None (PR gate) | None (PR gate) | Spec + Plan + PR gates (SPIR) |
23
+ | **LOC limit** | < 300 | < 300 | No limit |
24
+
25
+ ### When to Use AIR
26
+
27
+ - Small features (< 300 LOC)
28
+ - Requirements are clear from the GitHub issue
29
+ - No architectural decisions needed
30
+ - No new abstractions or significant refactoring required
31
+ - Would be overkill for full SPIR/ASPIR ceremony
32
+
33
+ ### When NOT to Use AIR
34
+
35
+ - Bug fixes → use **BUGFIX**
36
+ - Features needing spec discussion → use **SPIR** or **ASPIR**
37
+ - Amendments to existing specs → use **TICK**
38
+ - Architectural changes → use **SPIR**
39
+ - Complex features with multiple phases → use **SPIR** or **ASPIR**
40
+
41
+ ## Protocol Phases
42
+
43
+ ### I - Implement
44
+
45
+ The builder reads the GitHub issue and implements the feature:
46
+
47
+ 1. Read and understand the issue requirements
48
+ 2. Implement the feature (< 300 LOC)
49
+ 3. Write tests
50
+ 4. Verify build and tests pass
51
+ 5. Commit with descriptive message
52
+
53
+ If the feature grows beyond 300 LOC or requires architectural decisions, the builder signals `TOO_COMPLEX` to escalate to ASPIR.
54
+
55
+ ### R - Review (PR)
56
+
57
+ The builder creates a PR with the review embedded in the PR body:
58
+
59
+ 1. Create PR linking to the issue
60
+ 2. Include a review section in the PR body (summary, key decisions, test plan)
61
+ 3. Optionally run CMAP consultation if the builder judges the complexity warrants it
62
+ 4. Notify the architect
63
+
64
+ The **PR gate** is preserved — a human reviews all code before merge.
65
+
66
+ ## Usage
67
+
68
+ ```bash
69
+ # Spawn a builder using AIR
70
+ af spawn 42 --protocol air
71
+
72
+ # The builder implements autonomously and stops at the PR gate
73
+ ```
74
+
75
+ ## File Structure
76
+
77
+ ```
78
+ codev-skeleton/protocols/air/
79
+ ├── protocol.json # Protocol definition
80
+ ├── protocol.md # This file
81
+ ├── builder-prompt.md # Builder instructions (Handlebars template)
82
+ ├── prompts/
83
+ │ ├── implement.md # Implement phase prompt
84
+ │ └── pr.md # PR phase prompt
85
+ └── consult-types/
86
+ ├── impl-review.md # Implementation consultation guide
87
+ └── pr-review.md # PR consultation guide
88
+ ```
@@ -0,0 +1,111 @@
1
+ # PR Review Risk Triage Guide
2
+
3
+ Quick reference for the architect's risk-based PR review process. For the full integration review workflow, see `codev/roles/architect.md` Section 4.
4
+
5
+ ## Risk Assessment
6
+
7
+ When a builder PR arrives, assess risk before choosing review depth.
8
+
9
+ ### Step 1: Check Size and Scope
10
+
11
+ ```bash
12
+ gh pr diff --stat <N>
13
+ gh pr view <N> --json files | jq '.files[].path'
14
+ ```
15
+
16
+ ### Step 2: Determine Risk Level
17
+
18
+ **Precedence: highest factor wins.** If any single factor is high, the overall risk is high.
19
+
20
+ | Factor | Low | Medium | High |
21
+ |--------|-----|--------|------|
22
+ | **Lines changed** | < 100 | 100-500 | > 500 |
23
+ | **Files touched** | 1-3 | 4-10 | > 10 |
24
+ | **Subsystem** | Docs, tests, cosmetic | Features, commands, shared libs | Protocol, state mgmt, security |
25
+ | **Cross-cutting** | No shared interfaces | Some shared code | Core interfaces, APIs |
26
+
27
+ ### Step 3: Execute Review
28
+
29
+ | Risk | Action | Cost |
30
+ |------|--------|------|
31
+ | **Low** | Read PR, summarize, tell builder to merge | $0 |
32
+ | **Medium** | `consult -m claude --type integration pr N` | ~$1-2 |
33
+ | **High** | 3-way CMAP (Gemini + Codex + Claude in parallel) | ~$4-5 |
34
+
35
+ ## Subsystem Path Mappings
36
+
37
+ | Path Pattern | Subsystem | Risk |
38
+ |-------------|-----------|------|
39
+ | `packages/codev/src/commands/porch/` | Protocol orchestrator | High |
40
+ | `packages/codev/src/tower/` | Tower architecture | High |
41
+ | `packages/codev/src/state/` | State management | High |
42
+ | `codev/protocols/` | Protocol definitions | High |
43
+ | `codev-skeleton/protocols/` | Protocol templates | High |
44
+ | `packages/codev/src/commands/af/` | Agent Farm commands | Medium |
45
+ | `packages/codev/src/commands/consult/` | Consultation system | Medium |
46
+ | `packages/codev/src/lib/` | Shared libraries | Medium |
47
+ | `packages/codev/src/commands/` (other) | CLI commands | Medium |
48
+ | `codev/roles/` | Role definitions | Medium |
49
+ | `codev-skeleton/roles/` | Role templates | Medium |
50
+ | `codev/resources/` | Documentation | Low |
51
+ | `codev/specs/`, `codev/plans/`, `codev/reviews/` | Project artifacts | Low |
52
+ | `packages/codev/tests/` | Tests only | Low |
53
+ | `*.md` (not in `protocols/`) | Documentation | Low |
54
+
55
+ ## Typical Mappings by Protocol
56
+
57
+ - **Low**: Most bugfixes, ASPIR features, documentation, UI tweaks, config updates
58
+ - **Medium**: SPIR features, new commands, refactors touching 3+ files, new utility modules
59
+ - **High**: Protocol changes, porch state machine, Tower architecture, security model changes
60
+
61
+ **Note:** Protocol type is a heuristic, not the primary signal. An ASPIR PR that changes core state management should still be high-risk. Always check the actual diff.
62
+
63
+ ## Example Workflows
64
+
65
+ ### Low Risk: Bugfix (12 lines, 1 file, tests/)
66
+
67
+ ```bash
68
+ $ gh pr diff --stat 120
69
+ packages/codev/tests/unit/foo.test.ts | 12 ++++++------
70
+ 1 file changed, 6 insertions(+), 6 deletions(-)
71
+
72
+ # Low risk — read and approve
73
+ gh pr comment 120 --body "## Architect Review
74
+
75
+ Low-risk test fix. Corrects assertion in foo.test.ts.
76
+
77
+ ---
78
+ Architect review"
79
+
80
+ af send 0042 "PR approved, please merge"
81
+ ```
82
+
83
+ ### Medium Risk: New Feature (180 lines, 3 files, commands/)
84
+
85
+ ```bash
86
+ $ gh pr diff --stat 121
87
+ packages/codev/src/commands/consult/risk.ts | 120 +++++++++++++
88
+ packages/codev/src/cli.ts | 15 ++
89
+ packages/codev/tests/unit/risk.test.ts | 45 +++++
90
+ 3 files changed, 180 insertions(+)
91
+
92
+ # Medium risk — single-model review
93
+ consult -m claude --type integration pr 121
94
+ ```
95
+
96
+ ### High Risk: Protocol Change (650 lines, 14 files, porch/)
97
+
98
+ ```bash
99
+ $ gh pr diff --stat 122
100
+ packages/codev/src/commands/porch/run.ts | 200 ++++++++++++------
101
+ packages/codev/src/commands/porch/next.ts | 150 ++++++++++----
102
+ packages/codev/src/state/project.ts | 80 +++++---
103
+ ... 11 more files
104
+ 14 files changed, 420 insertions(+), 230 deletions(-)
105
+
106
+ # High risk — full 3-way CMAP
107
+ consult -m gemini --type integration pr 122 &
108
+ consult -m codex --type integration pr 122 &
109
+ consult -m claude --type integration pr 122 &
110
+ wait
111
+ ```
@@ -38,7 +38,8 @@ Quick reference for the 7-stage project workflow. For protocol details, see `cod
38
38
  │ HANDOFF / INTEGRATION │
39
39
  ├─────────────────────────────────────────────────────────────────────────────────────┤
40
40
  │ → 6. COMMITTED │
41
- │ Architect does 3-way integration review
41
+ │ Architect assesses PR risk: gh pr diff --stat N
42
+ │ Low: Read + merge | Medium: 1-model review | High: 3-way CMAP │
42
43
  │ Architect iterates with builder via PR comments │
43
44
  │ Architect tells builder to merge │
44
45
  │ Builder merges PR (NO --delete-branch flag) │
@@ -59,7 +60,7 @@ Quick reference for the 7-stage project workflow. For protocol details, see `cod
59
60
  | 3 | planned | Architect | Commit spec + plan | Committed to main |
60
61
  | 4 | implementing | Builder | IDE loop per phase | All phases complete |
61
62
  | 5 | implemented | Builder | Write review, create PR | PR created |
62
- | 6 | committed | Architect + Builder | Integration review, merge | PR merged |
63
+ | 6 | committed | Architect + Builder | Risk-based integration review, merge | PR merged |
63
64
  | 7 | integrated | Human | Validate production | Human confirms |
64
65
 
65
66
  ## Human Gates
@@ -143,9 +144,15 @@ consult -m codex --protocol spir --type impl
143
144
  consult -m gemini --protocol spir --type pr
144
145
  consult -m codex --protocol spir --type pr
145
146
 
146
- # Integration review (during Stage 6)
147
- consult -m gemini --type integration
148
- consult -m codex --type integration
147
+ # Integration review (during Stage 6 — depth depends on risk)
148
+ # Low risk: no consult needed, architect reads and merges
149
+ # Medium risk: single-model review
150
+ consult -m claude --type integration pr N
151
+ # High risk: full 3-way CMAP
152
+ consult -m gemini --type integration pr N &
153
+ consult -m codex --type integration pr N &
154
+ consult -m claude --type integration pr N &
155
+ wait
149
156
 
150
157
  # Parallel 3-way reviews (run all three concurrently)
151
158
  consult -m gemini --protocol spir --type spec &
@@ -162,7 +169,7 @@ wait
162
169
  | `plan` | Stage 2 | Implementation approach, phase breakdown, risk assessment |
163
170
  | `impl` | Stage 4 | Code quality, test coverage, spec adherence |
164
171
  | `pr` | Stage 5 | Final self-check before PR creation |
165
- | `integration` | Stage 6 | System fit, architectural consistency, side effects |
172
+ | `integration` | Stage 6 | System fit, architectural consistency, side effects (depth varies by risk — see `codev/resources/risk-triage.md`) |
166
173
 
167
174
  ## Builder Lifecycle
168
175
 
@@ -240,3 +247,4 @@ af cleanup -p XXXX --force
240
247
  - Builder role: `codev/roles/builder.md`
241
248
  - Architect role: `codev/roles/architect.md`
242
249
  - Consultant role: `codev/roles/consultant.md`
250
+ - Risk triage guide: `codev/resources/risk-triage.md`
@@ -53,7 +53,10 @@ porch pending # List pending gates
53
53
  ### Consult Tool (for integration reviews)
54
54
 
55
55
  ```bash
56
- # 3-way parallel integration review of builder's PR
56
+ # Single-model review (medium risk)
57
+ consult -m claude --type integration pr 35
58
+
59
+ # 3-way parallel review (high risk)
57
60
  consult -m gemini --type integration pr 35 &
58
61
  consult -m codex --type integration pr 35 &
59
62
  consult -m claude --type integration pr 35 &
@@ -117,12 +120,63 @@ af status # Overview of all builders
117
120
  porch status 0042 # Detailed state for one project (strict mode)
118
121
  ```
119
122
 
120
- ### 4. Integration Review
123
+ ### 4. Integration Review (Risk-Based Triage)
124
+
125
+ When the builder creates a PR, **assess risk first** before deciding review depth.
126
+
127
+ > **Full reference**: See `codev/resources/risk-triage.md` for subsystem mappings and examples.
128
+
129
+ #### Step 1: Assess Risk
130
+
131
+ ```bash
132
+ gh pr diff --stat <N> # See lines changed and files touched
133
+ gh pr view <N> --json files | jq '.files[].path' # See which subsystems
134
+ ```
135
+
136
+ #### Step 2: Triage
137
+
138
+ | Risk | Criteria | Action |
139
+ |------|----------|--------|
140
+ | **Low** | <100 lines, 1-3 files, isolated (docs, tests, cosmetic, bugfixes) | Read PR, summarize root cause + fix, tell builder to merge |
141
+ | **Medium** | 100-500 lines, 4-10 files, touches shared code (features, commands) | Single-model review: `consult -m claude --type integration pr N` |
142
+ | **High** | >500 lines, >10 files, core subsystems (porch, Tower, protocols, security) | Full 3-way CMAP (see below) |
143
+
144
+ **Precedence: highest factor wins.** If any single factor (lines, files, subsystem, or cross-cutting scope) is high-risk, treat the whole PR as high-risk.
145
+
146
+ **Typical mappings:**
147
+ - **Low**: Most bugfixes, ASPIR features, documentation, UI tweaks
148
+ - **Medium**: SPIR features, new commands, refactors touching 3+ files
149
+ - **High**: Protocol changes, porch state machine, Tower architecture, security model
150
+
151
+ #### Step 3: Execute Review
152
+
153
+ **Low risk** — no external models needed:
154
+ ```bash
155
+ # Read the PR yourself, then approve
156
+ gh pr comment 83 --body "## Architect Review
157
+
158
+ Low-risk change. [Summary of what changed and why.]
159
+
160
+ ---
161
+ Architect review"
162
+
163
+ af send 0042 "PR approved, please merge"
164
+ ```
165
+
166
+ **Medium risk** — single-model review:
167
+ ```bash
168
+ consult -m claude --type integration pr 83
169
+
170
+ # Post findings as PR comment
171
+ gh pr comment 83 --body "## Architect Integration Review
172
+ ...
173
+ Architect integration review"
121
174
 
122
- When the builder creates a PR:
175
+ af send 0042 "PR approved, please merge"
176
+ ```
123
177
 
178
+ **High risk** — full 3-way CMAP:
124
179
  ```bash
125
- # Run 3-way integration review
126
180
  consult -m gemini --type integration pr 83 &
127
181
  consult -m codex --type integration pr 83 &
128
182
  consult -m claude --type integration pr 83 &
@@ -130,15 +184,9 @@ wait
130
184
 
131
185
  # Post findings as PR comment
132
186
  gh pr comment 83 --body "## Architect Integration Review
133
-
134
- **Verdict: APPROVE**
135
-
136
- Integration looks good. No conflicts with existing modules.
137
-
138
- ---
187
+ ...
139
188
  Architect integration review"
140
189
 
141
- # Notify builder
142
190
  af send 0042 "PR approved, please merge"
143
191
  ```
144
192
 
@@ -225,6 +273,8 @@ Before approving implementations with UX requirements:
225
273
  | Approve spec | `porch approve <id> spec-approval` |
226
274
  | Approve plan | `porch approve <id> plan-approval` |
227
275
  | See pending gates | `porch pending` |
228
- | Integration review | `consult -m X --type integration pr N` |
276
+ | Assess PR risk | `gh pr diff --stat N` |
277
+ | Integration review (medium) | `consult -m claude --type integration pr N` |
278
+ | Integration review (high) | 3-way CMAP (see Section 4) |
229
279
  | Message builder | `af send <id> "short message"` |
230
280
  | Cleanup builder | `af cleanup -p <id>` |
@@ -1,32 +0,0 @@
1
- /**
2
- * Copyright (c) 2014 The xterm.js authors. All rights reserved.
3
- * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
4
- * https://github.com/chjj/term.js
5
- * @license MIT
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * Originally forked from (with the author's permission):
26
- * Fabrice Bellard's javascript vt100 for jslinux:
27
- * http://bellard.org/jslinux/
28
- * Copyright (c) 2011 Fabrice Bellard
29
- * The original design remains. The terminal itself
30
- * has been extended to include xterm CSI codes, among
31
- * other features.
32
- */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}:root{--bg-primary: #1a1a1a;--bg-secondary: #252525;--bg-tertiary: #2a2a2a;--bg-hover: #333333;--text-primary: #e0e0e0;--text-secondary: #a0a0a0;--text-muted: #666666;--border-color: #333333;--accent: #3b82f6;--accent-hover: #2563eb;--status-active: #22c55e;--status-waiting: #eab308;--status-error: #ef4444;--status-implementing: #f97316}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{height:100%;width:100%;overflow:hidden}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,monospace;background:var(--bg-primary);color:var(--text-primary);font-size:13px}.fullscreen-terminal{height:100vh;width:100vw;overflow:hidden}.fullscreen-terminal>div{height:100%;width:100%}.app{display:flex;flex-direction:column;height:100vh}.app-header{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);height:40px;flex-shrink:0}.app-title{font-size:14px;font-weight:600;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.header-version{font-size:11px;color:var(--text-secondary);font-weight:400}.app-body{flex:1;overflow:hidden}.split-pane{display:flex;height:100%;width:100%}.split-left,.split-right{height:100%;overflow:hidden}.split-handle{width:4px;cursor:col-resize;background:var(--border-color);flex-shrink:0}.split-handle:hover{background:var(--accent)}.right-panel{display:flex;flex-direction:column;height:100%}.tab-bar{display:flex;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);overflow-x:auto;flex-shrink:0;height:34px}.tab{display:flex;align-items:center;gap:6px;padding:6px 12px;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-secondary);font-size:12px;cursor:pointer;white-space:nowrap;font-family:inherit}.tab:hover{background:var(--bg-hover);color:var(--text-primary)}.tab-active{color:var(--text-primary);border-bottom-color:var(--accent)}.tab-icon{flex-shrink:0}.tab-label{max-width:120px;overflow:hidden;text-overflow:ellipsis}.tab-close{font-size:14px;line-height:1;opacity:.5;padding:0 2px;border-radius:3px}.tab-close:hover{opacity:1;background:var(--bg-hover)}.tab-content{flex:1;overflow:hidden}.terminal-tab-pane{width:100%;height:100%}.file-path-decoration{border-bottom:1px dotted rgba(255,255,255,.3)!important;background:transparent!important;pointer-events:none}.file-path-decoration-hover{border-bottom-color:#ffffffb3!important}.terminal-iframe{display:block}.file-tree{padding:8px;overflow-y:auto;height:100%}.file-node{display:flex;align-items:center;gap:6px;padding:3px 0;cursor:pointer;font-size:12px;border-radius:4px}.file-node:hover{background:var(--bg-hover)}.file-icon{font-size:14px;flex-shrink:0}.file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-tree-error,.file-tree-loading{padding:16px;color:var(--text-muted);font-size:12px}.no-architect{display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-muted);font-size:14px}.virtual-keyboard{display:flex;gap:6px;padding:6px 8px;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);flex-shrink:0}.virtual-key{padding:4px 12px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-secondary);font-size:12px;font-family:inherit;cursor:pointer;touch-action:manipulation;user-select:none;-webkit-user-select:none}.virtual-key:active{background:var(--bg-hover);color:var(--text-primary)}.virtual-key-active{background:var(--accent);border-color:var(--accent);color:#fff}.virtual-key-active:active{background:var(--accent-hover)}.terminal-controls{position:absolute;top:8px;right:20px;z-index:20;display:flex;gap:4px}.terminal-control-btn{display:flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;padding:0;background:transparent;border:none;border-radius:4px;color:#e0e0e0;opacity:.4;cursor:pointer;touch-action:manipulation;user-select:none;-webkit-user-select:none}.terminal-control-btn:hover{opacity:.8}.terminal-control-btn:active{opacity:1}.terminal-status-dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0;align-self:center}.terminal-status-reconnecting{background-color:#fc0;animation:terminal-pulse 1.2s ease-in-out infinite}.terminal-status-disconnected{background-color:#f44}@keyframes terminal-pulse{0%,to{opacity:1}50%{opacity:.3}}.mobile-layout{display:flex;flex-direction:column;height:100vh}.mobile-content{flex:1;overflow:hidden;display:flex;flex-direction:column}@media(max-width:768px){.app-header{padding:6px 12px}.tab{padding:4px 8px;font-size:11px}}.file-viewer{display:flex;flex-direction:column;height:100%;background:var(--bg-primary)}.file-loading,.file-error{display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-secondary)}.file-error{color:var(--status-error)}.file-header{display:flex;align-items:center;gap:12px;padding:8px 12px;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);flex-shrink:0}.file-path{font-family:monospace;font-size:12px;color:var(--text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-language{font-size:11px;color:var(--text-muted);text-transform:uppercase}.file-save-btn{padding:4px 12px;font-size:11px;background:var(--accent);color:#fff;border:none;border-radius:4px;cursor:pointer}.file-save-btn:hover{background:var(--accent-hover)}.file-save-btn:disabled{opacity:.5;cursor:not-allowed}.file-content{display:flex;flex:1;overflow:auto;background:var(--bg-primary)}.line-numbers{display:flex;flex-direction:column;padding:12px 8px;background:var(--bg-secondary);color:var(--text-muted);font-family:Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;text-align:right;-webkit-user-select:none;user-select:none;flex-shrink:0;min-width:40px}.line-number{padding-right:8px}.line-number.highlighted-line{background:#3b82f64d}.file-text{flex:1;padding:12px;font-family:Menlo,Monaco,Courier New,monospace;font-size:13px;line-height:1.5;background:var(--bg-primary);color:var(--text-primary);border:none;outline:none;resize:none;white-space:pre;overflow:auto}.file-image-container,.file-video-container{flex:1;display:flex;align-items:center;justify-content:center;overflow:auto;padding:20px}.file-image{max-width:100%;max-height:100%;object-fit:contain}.file-video{max-width:100%;max-height:100%}.file-tree-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.file-search{position:relative;padding:8px;border-bottom:1px solid var(--border-color);flex-shrink:0}.file-search-input{width:100%;padding:6px 10px;font-size:12px;font-family:inherit;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-primary);outline:none}.file-search-input:focus{border-color:var(--accent)}.file-search-input::placeholder{color:var(--text-muted)}.file-search-suggestions{position:absolute;top:100%;left:8px;right:8px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;box-shadow:0 4px 12px #0000004d;z-index:100;max-height:240px;overflow-y:auto}.file-search-suggestion{display:flex;flex-direction:column;padding:8px 10px;cursor:pointer;border-bottom:1px solid var(--border-color)}.file-search-suggestion:last-child{border-bottom:none}.file-search-suggestion:hover{background:var(--bg-hover)}.suggestion-name{font-size:12px;color:var(--text-primary);font-weight:500}.suggestion-path{font-size:10px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-tree-section{display:flex;flex-direction:column;overflow:hidden}.file-tree-section:first-of-type{flex-shrink:0}.file-tree-section:last-of-type{flex:1;overflow:hidden}.file-tree-section-header{padding:8px 12px;font-size:11px;font-weight:600;text-transform:uppercase;color:var(--text-muted);letter-spacing:.5px;border-bottom:1px solid var(--border-color);flex-shrink:0}.recent-file{color:var(--text-secondary)}.recent-file:hover{color:var(--text-primary)}.file-path-hint{font-size:10px;color:var(--text-muted);margin-left:auto;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-indicator{font-family:monospace;font-size:10px;font-weight:700;padding:1px 4px;border-radius:3px;margin-left:auto;flex-shrink:0}.git-modified{color:var(--status-implementing);background:#f9731626}.git-staged{color:var(--status-active);background:#22c55e26}.git-untracked{color:var(--text-muted);background:#66666626}.cloud-status{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-secondary);margin-right:12px}.cloud-status--none{color:var(--text-muted)}.cloud-status--error{color:var(--status-error)}.cloud-dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}.cloud-dot--green{background:var(--status-active)}.cloud-dot--yellow{background:var(--status-waiting);animation:cloud-pulse 1.2s ease-in-out infinite}@keyframes cloud-pulse{0%,to{opacity:1}50%{opacity:.3}}.cloud-dot--red{background:var(--status-error)}.cloud-dot--gray{background:var(--text-muted)}.cloud-uptime{color:var(--text-muted);font-size:11px}.cloud-hint{color:var(--text-muted);font-size:11px;font-style:italic}.cloud-link{color:var(--accent);text-decoration:none;font-size:11px}.cloud-link:hover{text-decoration:underline}.cloud-btn{background:transparent;border:1px solid var(--border-color);color:var(--text-secondary);font-size:11px;padding:1px 6px;border-radius:3px;cursor:pointer}.cloud-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.cloud-btn:disabled{opacity:.5;cursor:default}.mobile-wrapper{display:flex;flex-direction:column;height:100vh}.mobile-header{padding:4px 8px;border-bottom:1px solid var(--border-color);background:var(--bg-primary)}.mobile-wrapper .mobile-layout{flex:1;min-height:0}.work-view{display:flex;flex-direction:column;height:100%;overflow:hidden}.work-content{flex:1;overflow-y:auto;padding:12px 16px}.work-view.file-panel-open .work-content{flex:2}.work-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.work-title{font-size:19px;font-weight:600;color:var(--text-primary)}.work-actions{display:flex;gap:6px}.work-btn{background:var(--accent);color:#fff;border:none;padding:4px 10px;border-radius:4px;font-size:14px;cursor:pointer}.work-btn:hover{background:var(--accent-hover)}.work-btn-secondary{background:transparent;border:1px solid var(--border-color);color:var(--text-secondary)}.work-btn-secondary:hover{background:var(--bg-hover);color:var(--text-primary)}.tip-banner{display:flex;align-items:center;gap:8px;padding:6px 12px;margin-bottom:16px;background:var(--bg-tertiary);border-radius:4px;font-size:14px;color:var(--text-secondary)}.tip-banner-label{font-weight:600;color:var(--text-muted);white-space:nowrap}.tip-banner-text{flex:1;min-width:0}.tip-banner-text code{font-family:var(--font-mono, monospace);background:var(--bg-primary);padding:1px 4px;border-radius:2px;font-size:13px;color:var(--text-primary)}.tip-banner-nav{background:none;border:none;color:var(--text-muted);cursor:pointer;padding:2px 4px;font-size:14px;line-height:1;border-radius:2px}.tip-banner-nav:hover{color:var(--text-primary);background:var(--bg-hover)}.tip-banner-dismiss{background:none;border:none;color:var(--text-muted);cursor:pointer;padding:2px 4px;font-size:14px;line-height:1;border-radius:2px;margin-left:4px}.tip-banner-dismiss:hover{color:var(--text-primary);background:var(--bg-hover)}.work-section{margin-bottom:20px}.work-section-title{font-size:13px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;display:flex;align-items:center;gap:6px}.work-empty{color:var(--text-muted);font-style:italic;font-size:14px;padding:8px 0}.work-unavailable{color:var(--status-waiting);font-size:14px;padding:8px 0}.work-error{color:var(--status-error);font-size:14px;padding:8px;margin-bottom:12px;background:#ef44441a;border-radius:4px}.work-loading{color:var(--text-muted);padding:16px}.builder-table{width:100%;border-collapse:separate;border-spacing:0 4px}.builder-table thead th{font-size:13px;font-weight:500;color:var(--text-secondary);text-align:left;padding:0 10px 4px;white-space:nowrap}.builder-row td{background:var(--bg-secondary);padding:8px 10px;font-size:16px;border-top:1px solid var(--border-color);border-bottom:1px solid var(--border-color)}.builder-row td:first-child{border-left:1px solid var(--border-color);border-radius:8px 0 0 8px}.builder-row td:last-child{border-right:1px solid var(--border-color);border-radius:0 8px 8px 0}.builder-row:hover td{border-color:var(--accent)}.builder-row--blocked td:first-child{border-left:3px solid var(--status-waiting)}.builder-col-id{font-weight:500;color:var(--accent);white-space:nowrap;width:60px}.builder-col-title{color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:0;width:40%}.builder-col-state{white-space:nowrap;width:140px}.builder-state-active{font-size:14px;color:var(--accent)}.builder-state-blocked{font-size:14px;color:var(--status-waiting)}.builder-col-progress{width:120px;white-space:nowrap}.progress-bar{width:80px;height:4px;background:var(--bg-tertiary);border-radius:2px;overflow:hidden;display:inline-block;vertical-align:middle}.progress-fill{height:100%;background:var(--status-active);border-radius:2px;transition:width .3s ease}.progress-fill--blocked{background:var(--status-waiting)}.progress-pct{font-size:13px;color:var(--text-secondary);margin-left:6px;vertical-align:middle}.builder-col-elapsed{font-size:14px;color:var(--text-secondary);white-space:nowrap;width:70px}.builder-col-actions{width:60px;text-align:right}.builder-row-open{font-size:13px;color:var(--accent);background:#3b82f614;border:1px solid rgba(59,130,246,.2);padding:3px 10px;border-radius:5px;cursor:pointer;white-space:nowrap}.builder-row-open:hover{background:#3b82f62e}.pr-rows{display:flex;flex-direction:column;gap:4px}a.pr-row{text-decoration:none;color:inherit;cursor:pointer}.pr-row{display:flex;align-items:center;gap:10px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;padding:10px 14px}.pr-row:hover{border-color:var(--accent)}.pr-row-number{font-size:16px;font-weight:500;color:var(--accent);white-space:nowrap}.pr-row-title{flex:1;font-size:16px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pr-row-status{font-size:13px;white-space:nowrap}.pr-status--approved{color:var(--status-active)}.pr-status--reviewing{color:var(--status-waiting)}.pr-status--changes{color:var(--status-error)}.pr-row-age{font-size:13px;color:var(--text-muted);white-space:nowrap}.attention-rows{display:flex;flex-direction:column;gap:4px}a.attention-row{text-decoration:none;color:inherit;cursor:pointer}.attention-row{display:flex;align-items:center;gap:10px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;padding:10px 14px}.attention-row:hover{border-color:var(--accent)}.attention-row-id{font-size:16px;font-weight:500;color:var(--accent);white-space:nowrap}.attention-row-title{flex:1;font-size:16px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.attention-row-kind{font-size:13px;white-space:nowrap}.attention-kind--pr{color:var(--status-waiting)}.attention-kind--spec,.attention-kind--plan{color:var(--status-error)}.attention-row-age{font-size:13px;color:var(--text-muted);white-space:nowrap}.backlog-rows{display:flex;flex-direction:column;gap:2px}.backlog-row{display:flex;align-items:center;gap:6px;padding:4px 14px;border-radius:6px}.backlog-row:hover{background:var(--bg-secondary)}.backlog-row-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0;text-decoration:none;color:inherit}.backlog-row-main:hover .backlog-row-title{color:var(--accent)}.backlog-artifacts{display:flex;gap:4px;flex-shrink:0}.backlog-artifact-link{font-size:12px;padding:1px 5px;border-radius:3px;border:1px solid var(--border-color);background:transparent;color:var(--text-secondary);cursor:pointer;white-space:nowrap}.backlog-artifact-link:hover{background:var(--bg-hover);color:var(--accent);border-color:var(--accent)}.backlog-priority-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.priority-dot--high{background:var(--status-error)}.priority-dot--med{background:var(--status-waiting)}.priority-dot--low{background:var(--text-muted)}.backlog-row-number{font-size:16px;font-weight:500;color:var(--accent);white-space:nowrap}.backlog-type-tag{font-size:12px;padding:1px 5px;border-radius:3px;font-weight:500;white-space:nowrap}.type-tag--bug{background:#ef444426;color:var(--status-error)}.type-tag--project{background:#a855f71f;color:#a855f7}.type-tag--spike{background:#0ea5e91f;color:#0ea5e9}.backlog-row-title{flex:1;font-size:16px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.backlog-row-age{font-size:13px;color:var(--text-muted);white-space:nowrap}.recently-closed-rows{display:flex;flex-direction:column;gap:2px}.recently-closed-row{display:flex;align-items:center;gap:6px;padding:4px 14px;border-radius:6px;opacity:.7}.recently-closed-row:hover{background:var(--bg-secondary);opacity:1}.recently-closed-row-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0;text-decoration:none;color:inherit}.recently-closed-check{font-size:13px;color:var(--status-active);flex-shrink:0}.work-file-panel{border-top:1px solid var(--border-color);background:var(--bg-secondary)}.work-file-panel.expanded{flex:1;display:flex;flex-direction:column;overflow:hidden}.work-file-panel.collapsed{flex-shrink:0}.work-file-panel-header{display:flex;align-items:center;gap:6px;padding:6px 12px;cursor:pointer;-webkit-user-select:none;user-select:none}.work-file-panel-header:hover{background:var(--bg-hover)}.work-file-panel-toggle{font-size:12px;color:var(--text-muted)}.work-file-panel-label{font-size:14px;font-weight:500;color:var(--text-secondary)}.work-file-panel-search{flex:1;margin-left:8px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;color:var(--text-primary);font-size:14px;padding:3px 8px;outline:none}.work-file-panel-search::placeholder{color:var(--text-muted)}.work-file-panel-search:focus{border-color:var(--accent)}.work-file-panel-content{flex:1;overflow-y:auto;padding:0 12px 12px}@media(max-width:768px){.work-content{padding:8px 12px}.work-header{flex-wrap:wrap;gap:8px}.pr-row,.attention-row{flex-wrap:wrap}.builder-table{font-size:14px}.builder-col-elapsed,.builder-table thead th:nth-child(5){display:none}.pr-row-title,.attention-row-title,.backlog-row-title{min-width:60%}}.analytics-view{display:flex;flex-direction:column;height:100%;overflow:hidden}.analytics-content{flex:1;overflow-y:auto;padding:12px 16px}.analytics-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.analytics-title{font-size:16px;font-weight:600;color:var(--text-primary)}.analytics-actions{display:flex;gap:6px;align-items:center}.analytics-range-selector{display:flex;border:1px solid var(--border-color);border-radius:4px;overflow:hidden}.analytics-range-btn{background:transparent;border:none;border-right:1px solid var(--border-color);padding:3px 8px;font-size:11px;cursor:pointer;color:var(--text-secondary)}.analytics-range-btn:last-child{border-right:none}.analytics-range-btn:hover{background:var(--bg-hover)}.analytics-range-btn.active{background:var(--accent);color:#fff}.analytics-section{margin-bottom:16px}.analytics-section-title{font-size:11px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;display:flex;align-items:center;gap:4px}.analytics-collapse-icon{font-size:10px;width:12px;display:inline-block}.analytics-error{color:var(--status-error);font-size:12px;margin-bottom:8px;padding:6px 8px;background:#ef44441a;border-radius:4px}.analytics-loading{color:var(--text-secondary);font-size:13px;padding:20px 0;text-align:center}.analytics-metric-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:8px}.analytics-metric{display:flex;flex-direction:column;padding:8px 10px;background:var(--bg-secondary, var(--bg-hover));border-radius:4px}.analytics-metric-value{font-size:18px;font-weight:600;color:var(--text-primary);line-height:1.2}.analytics-metric-label{font-size:10px;color:var(--text-secondary);margin-top:2px}.analytics-sub-section{margin-top:10px}.analytics-sub-title{font-size:11px;font-weight:500;color:var(--text-secondary);margin-bottom:4px}.analytics-table{width:100%;border-collapse:collapse;font-size:11px}.analytics-table th{text-align:left;color:var(--text-secondary);font-weight:500;padding:3px 6px;border-bottom:1px solid var(--border-color)}.analytics-table td{padding:3px 6px;color:var(--text-primary);border-bottom:1px solid var(--border-subtle, var(--border-color))}.analytics-list{list-style:none;padding:0;margin:0}.analytics-list li{display:flex;justify-content:space-between;padding:2px 0;font-size:12px}.analytics-list-label{color:var(--text-secondary)}.analytics-list-value{color:var(--text-primary);font-weight:500}.analytics-charts-row{display:flex;gap:8px}.analytics-chart-half{flex:1;min-width:0}