loki-mode 11.74.2 → 11.75.1
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.
- package/README.md +1 -1
- package/SKILL.md +2 -3
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +10 -10
- package/autonomy/council-v2.sh +4 -4
- package/autonomy/grill.sh +1 -1
- package/autonomy/lib/browser-open.sh +1 -1
- package/autonomy/lib/chat.sh +1 -1
- package/autonomy/lib/cockpit-render.sh +1 -1
- package/autonomy/lib/done-recognition.sh +4 -4
- package/autonomy/lib/efficiency_cost.py +1 -1
- package/autonomy/lib/engine10-push.sh +2 -2
- package/autonomy/lib/prd-enrich.sh +1 -1
- package/autonomy/lib/proof-check.sh +1 -1
- package/autonomy/lib/proof-generator.py +3 -3
- package/autonomy/lib/proof-pr.sh +1 -1
- package/autonomy/lib/skill-link-heal.sh +1 -1
- package/autonomy/lib/voter-agents.sh +1 -1
- package/autonomy/loki +26 -37
- package/autonomy/prd-checklist.sh +1 -1
- package/autonomy/receipt_jwt.py +1 -1
- package/autonomy/run.sh +28 -28
- package/autonomy/trigger-schedule.py +6 -414
- package/autonomy/tui.sh +1 -1
- package/autonomy/verify.sh +4 -4
- package/completions/loki.bash +0 -5
- package/dashboard/__init__.py +1 -1
- package/docs/ARCHITECTURE.md +1 -2
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/COMPONENTS.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/ROUTING-EVIDENCE.md +1 -2
- package/docs/V10-RESEARCH.md +1 -1
- package/docs/dev/architecture-reference.md +3 -7
- package/docs/dev/project-structure.md +1 -4
- package/docs/dev/release-checklist.md +13 -31
- package/docs/research-2026-07/OBSERVABILITY-TOOL-SPEC.md +1 -1
- package/docs/v11/MARKET-SLICES.md +1 -1
- package/docs/v11/REGISTRIES.md +1 -1
- package/docs/v11/ROUTER-1.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/skills/extending.md +2 -3
- package/skills/factory-operations.md +11 -18
- package/skills/release-cadence.md +2 -2
- package/web-app/dist/assets/{AdminPage-jkjilfbl.js → AdminPage-xKgtIhk2.js} +1 -1
- package/web-app/dist/assets/{Avatar-bd5JWkSJ.js → Avatar-Q14AHox9.js} +1 -1
- package/web-app/dist/assets/{Badge-DVRit2Xw.js → Badge-yk5M-lip.js} +1 -1
- package/web-app/dist/assets/{Button-BNAB-pVZ.js → Button-ynznk0At.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-DpG29h_w.js → CockpitPage-C8B765za.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Dasg5V41.js → ComparePage-DqzmWKnf.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-DJojse6b.js → ErrorBoundary-DdBPd_Lq.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-Blxw7_u1.js → EvidenceReceiptPanel-jb4Tp38b.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-BBvSFj80.js → GitHubIssuesPanel-xJQiLcxs.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-BCIKeSBg.js → GitHubPRsPanel-84W3Dhk_.js} +1 -1
- package/web-app/dist/assets/{HomePage-C7d__oNG.js → HomePage-St1Xl2tu.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BXljL3yY.js → LoginPage-jRt0NUHb.js} +1 -1
- package/web-app/dist/assets/{MagicPage-Xjkts_yE.js → MagicPage-CQLFe7LR.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-kQvVp-j2.js → MetricsPage-zzX9eTC5.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-D-4ZlEaO.js → NotFoundPage-DDu023SY.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-DfzR5RXP.js → ProjectPage-D60UURaH.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-DFDsWzkV.js → ProjectsPage-DqVsKxlt.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-CLPIoYT3.js → SettingsPage-G7pPKvo0.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-PZKkyGeY.js → ShowcasePage-CrU_aKgS.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-BsBlcnzo.js → SystemSettingsPage-ClKGQFsB.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-BSjgNhoU.js → TeamsPage-B530vSNe.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-W2KeAzbg.js → TemplatesPage-COmv_Cqd.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-BjroTiCC.js → TerminalOutput-CufG9YzF.js} +1 -1
- package/web-app/dist/assets/{activity-BXZ5YYes.js → activity-Ct1Updr6.js} +1 -1
- package/web-app/dist/assets/{bell-D1urp5pa.js → bell-rcvhQuGr.js} +1 -1
- package/web-app/dist/assets/{bot-Chedf2bF.js → bot-DzeqEI-b.js} +1 -1
- package/web-app/dist/assets/{check-DhaCuOCV.js → check-zacnZHyC.js} +1 -1
- package/web-app/dist/assets/{chevron-left-D7BpQyA6.js → chevron-left-Lxnkl8Qg.js} +1 -1
- package/web-app/dist/assets/{circle-alert-DnGvQ_AQ.js → circle-alert-DoqSdQdB.js} +1 -1
- package/web-app/dist/assets/{clock-CqfxWhHM.js → clock-B7bJcVIC.js} +1 -1
- package/web-app/dist/assets/{cloud-BKxp5AWB.js → cloud-DdA9Bu6q.js} +1 -1
- package/web-app/dist/assets/{code-xml-BDQ6GBtt.js → code-xml-CAZEZ9T8.js} +1 -1
- package/web-app/dist/assets/{database-BmpEx1y_.js → database-Da2GkEIN.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DYNY9R_C.js → dollar-sign-DjDiG-37.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-BJi0IBFd.js → file-code-corner-CSL-Jij-.js} +1 -1
- package/web-app/dist/assets/{file-plus-Dqyb2bcQ.js → file-plus-02DRA8pV.js} +1 -1
- package/web-app/dist/assets/{globe-DPh4RWfM.js → globe-CGyB90kK.js} +1 -1
- package/web-app/dist/assets/{hammer-B3xnuoA1.js → hammer-BaQB96TG.js} +1 -1
- package/web-app/dist/assets/{index-BpX8DcTr.js → index-lcoI1_Kk.js} +3 -3
- package/web-app/dist/assets/{layers-BRCmyCW8.js → layers-BWJBvoeg.js} +1 -1
- package/web-app/dist/assets/{loader-circle-n07Pky0M.js → loader-circle-CdcI0FeS.js} +1 -1
- package/web-app/dist/assets/{lock-BWqOuQmS.js → lock-BBkw5NJx.js} +1 -1
- package/web-app/dist/assets/{package-BJlB_Z-Z.js → package-BpPRO3LM.js} +1 -1
- package/web-app/dist/assets/{plus-oH17BZu2.js → plus-D7XbyK29.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CPQ476LL.js → refresh-cw-DLG3hyAi.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-7hLvOcnS.js → rotate-ccw-Bqau4R_S.js} +1 -1
- package/web-app/dist/assets/{scroll-text-BCmLauQn.js → scroll-text-BtIL3cNk.js} +1 -1
- package/web-app/dist/assets/{server-DfTfvW84.js → server-tZCmZ4yH.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CaeGRq19.js → shield-alert-K5JXzFKg.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-Dz-l2GPC.js → thumbs-up-CHCVyJdw.js} +1 -1
- package/web-app/dist/assets/{trash-2-B-OsDmSo.js → trash-2-DncNxVq0.js} +1 -1
- package/web-app/dist/assets/{trending-down-CXTFOxzq.js → trending-down-D8Bp0azX.js} +1 -1
- package/web-app/dist/assets/{trending-up-FQEdqr3v.js → trending-up-AixETdKR.js} +1 -1
- package/web-app/dist/assets/{upload-CacWSNTg.js → upload-VCbjFn2H.js} +1 -1
- package/web-app/dist/assets/{usePolling-cIjZ9qd2.js → usePolling-CQvKD2Jj.js} +1 -1
- package/web-app/dist/assets/{user-DAouWFHi.js → user-SK-YguQ6.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/autonomy/company-seats.json +0 -82
- package/docs/COMPETITIVE-INTEL-2026-09.md +0 -444
- package/docs/FOUNDER-DECISIONS-TRUST-SEMANTICS-2026-08-01.md +0 -145
- package/docs/FOUNDER-STATUS-AND-DECISIONS-2026-07-01.md +0 -132
- package/docs/LOKI-10-BUILD-PROMPT.md +0 -350
- package/docs/STRATEGY-2026-2028.md +0 -124
- package/docs/V10-VISION.md +0 -161
- package/docs/v10/ADOPTION-PLAN.md +0 -375
- package/docs/v10/ARCHITECT-CUTS.md +0 -744
- package/docs/v10/BACKLOG.md +0 -231
- package/docs/v10/BOARD.md +0 -1403
- package/docs/v10/CONTROL-PLANE.md +0 -120
- package/docs/v10/CONTROL.md +0 -36
- package/docs/v10/CP-ASK-PLAN.md +0 -85
- package/docs/v10/CP-ENTERPRISE-UI.md +0 -537
- package/docs/v10/D51-PHASE-B.md +0 -120
- package/docs/v10/D61-SPEED.md +0 -105
- package/docs/v10/D63-CARDS.md +0 -354
- package/docs/v10/DECISIONS.md +0 -915
- package/docs/v10/E2E-D65.md +0 -123
- package/docs/v10/ENGINE-LAWS.md +0 -163
- package/docs/v10/ENGINE-MEASURE.md +0 -69
- package/docs/v10/ENGINE.md +0 -743
- package/docs/v10/FAILURE-CLASSES.md +0 -2026
- package/docs/v10/FC21B-FC22-PLAN.md +0 -107
- package/docs/v10/FIRST-RUN-GATE.md +0 -39
- package/docs/v10/FOUNDER-QUEUE.md +0 -29
- package/docs/v10/GAP-RESEARCH-1003.md +0 -32
- package/docs/v10/GUARDS.md +0 -883
- package/docs/v10/L0-WAVE1.md +0 -81
- package/docs/v10/LEGACY-REMOVAL.md +0 -408
- package/docs/v10/MEDIUM-ANALYSIS.md +0 -346
- package/docs/v10/METRICS.md +0 -645
- package/docs/v10/MODERNIZE.md +0 -437
- package/docs/v10/OPENCODE-PARITY-PLAN.md +0 -84
- package/docs/v10/OPERATING-MODEL.md +0 -60
- package/docs/v10/PLAN-V12.md +0 -896
- package/docs/v10/PROGRESS.md +0 -2735
- package/docs/v10/RELEASE-11.md +0 -77
- package/docs/v10/RETRO-2026.md +0 -650
- package/docs/v10/ROADMAP-D63.md +0 -35
- package/docs/v10/SCALE.md +0 -140
- package/docs/v10/SCORECARD-PLAN.md +0 -250
- package/docs/v10/SWARM-PROMPT.md +0 -98
- package/docs/v10/SWARM.md +0 -293
- package/docs/v10/cp-redesign/PARITY.md +0 -188
- package/docs/v10/cp-redesign/legacy/INDEX.md +0 -1167
- package/docs/v10/roadmap-10/01-measurement.md +0 -113
- package/docs/v10/roadmap-10/02-cost.md +0 -75
- package/docs/v10/roadmap-10/03-speed.md +0 -65
- package/docs/v10/roadmap-10/04-first-run.md +0 -61
- package/docs/v10/roadmap-10/05-deploy.md +0 -61
- package/docs/v10/roadmap-10/06-stability.md +0 -64
- package/docs/v10/roadmap-10/07-quality.md +0 -57
- package/docs/v10/roadmap-10/08-proof.md +0 -48
- package/docs/v10/roadmap-10/09-safety.md +0 -74
- package/docs/v10/roadmap-10/README.md +0 -1464
- package/skills/sdlc-fleet.md +0 -170
- package/tools/cockpit/SPEC.md +0 -275
- package/tools/cockpit/index.html +0 -146
- package/tools/cockpit/roi-basis.json +0 -33
- package/tools/cockpit/server.py +0 -946
package/skills/sdlc-fleet.md
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# SDLC Fleet Pattern (skill module)
|
|
2
|
-
|
|
3
|
-
<!-- TOC:START (generated by scripts/skill-toc.sh; do not edit) -->
|
|
4
|
-
## Contents
|
|
5
|
-
|
|
6
|
-
- [When to invoke this pattern](#when-to-invoke-this-pattern)
|
|
7
|
-
- [The 6 roles](#the-6-roles)
|
|
8
|
-
- [1. Architect (1 agent, Plan subagent_type, model: opus)](#1-architect-1-agent-plan-subagent_type-model-opus)
|
|
9
|
-
- [2. Product Owner (the integrator, NOT a separate agent)](#2-product-owner-the-integrator-not-a-separate-agent)
|
|
10
|
-
- [3. Dev Fleet (3-5 principal engineers in parallel, model: opus)](#3-dev-fleet-3-5-principal-engineers-in-parallel-model-opus)
|
|
11
|
-
- [4. SDET (1-2 agents, model: opus)](#4-sdet-1-2-agents-model-opus)
|
|
12
|
-
- [5. Council Reviewers (3 agents, parallel, model: 2 opus + 1 sonnet)](#5-council-reviewers-3-agents-parallel-model-2-opus--1-sonnet)
|
|
13
|
-
- [6. Real-User QA (1 agent OR the integrator directly)](#6-real-user-qa-1-agent-or-the-integrator-directly)
|
|
14
|
-
- [Parallel-execution rules](#parallel-execution-rules)
|
|
15
|
-
- [Honest acknowledgements pattern](#honest-acknowledgements-pattern)
|
|
16
|
-
- [Reference run: v7.6.0 LSP integration](#reference-run-v760-lsp-integration)
|
|
17
|
-
- [Per-release checklist (always)](#per-release-checklist-always)
|
|
18
|
-
<!-- TOC:END -->
|
|
19
|
-
|
|
20
|
-
**Established:** v7.7.4 (2026-05-24)
|
|
21
|
-
**Origin:** user mandate "agent teams with senior most developers, Loki architects, sdet team and council of reviewers exist and coordinate and work in parallel"
|
|
22
|
-
**Proven by:** v7.6.0 fleet ship (architect + 3 principal engineers + SDET + 3-reviewer council + real-user QA) demonstrated the pattern works end-to-end.
|
|
23
|
-
|
|
24
|
-
This skill describes the STANDING pattern for shipping any non-trivial change in Loki Mode. The integrator (Claude Code session) is responsible for orchestrating the roles below. Each role is a Loki Agent call.
|
|
25
|
-
|
|
26
|
-
## When to invoke this pattern
|
|
27
|
-
|
|
28
|
-
Apply this pattern when shipping ANY of:
|
|
29
|
-
|
|
30
|
-
- A new feature touching > 3 files
|
|
31
|
-
- A bug fix touching agent runtime, council, memory, or auto-spawn surfaces
|
|
32
|
-
- A MINOR or MAJOR release
|
|
33
|
-
- A change with cross-route parity implications (bash + Bun + TS)
|
|
34
|
-
- A change the user has marked "critical" or "production-blocking"
|
|
35
|
-
|
|
36
|
-
Skip this pattern (acceptable shortcuts) when:
|
|
37
|
-
|
|
38
|
-
- Single-line typo fix in user-facing strings
|
|
39
|
-
- Pure docs edit (no code change)
|
|
40
|
-
- A revert of a previously-shipped change with no new logic
|
|
41
|
-
- An emergency hotfix where waiting on parallel agents would exceed the production-impact window
|
|
42
|
-
|
|
43
|
-
## The 6 roles
|
|
44
|
-
|
|
45
|
-
### 1. Architect (1 agent, Plan subagent_type, model: opus)
|
|
46
|
-
|
|
47
|
-
**Job:** Design the change end-to-end before any code is written. Produces a written plan saved as `docs/<TOPIC>-PLAN.md`.
|
|
48
|
-
|
|
49
|
-
**Inputs:** the original user directive verbatim + relevant source files + any prior council findings.
|
|
50
|
-
|
|
51
|
-
**Outputs:** a markdown plan with: scope, acceptance criteria, implementation steps, file-level diffs sketch, testing plan, risks + mitigations, NOT-tested honest disclosure.
|
|
52
|
-
|
|
53
|
-
**Output is BINDING** for the dev fleet -- don't change scope without re-architecting.
|
|
54
|
-
|
|
55
|
-
### 2. Product Owner (the integrator, NOT a separate agent)
|
|
56
|
-
|
|
57
|
-
**Job:** Lock scope before implementation. Use `AskUserQuestion` to surface ambiguity to the user. NEVER guess at scope.
|
|
58
|
-
|
|
59
|
-
**Output:** explicit user answer that locks the acceptance criteria.
|
|
60
|
-
|
|
61
|
-
### 3. Dev Fleet (3-5 principal engineers in parallel, model: opus)
|
|
62
|
-
|
|
63
|
-
**Job:** Implement independent slices of the architect's plan IN PARALLEL. Each engineer gets a single self-contained task with explicit file references and binding constraints.
|
|
64
|
-
|
|
65
|
-
**Pattern:** spawn N agents via `Agent` tool with `run_in_background: true` in ONE message (parallel). Each agent gets:
|
|
66
|
-
|
|
67
|
-
- The architect's plan section relevant to their slice
|
|
68
|
-
- A SINGLE deliverable (one fix, one feature, one file)
|
|
69
|
-
- Binding constraints (no version bumps, no commits, no emojis, no em dashes, NO destructive operations)
|
|
70
|
-
- Explicit "report back in N words" cap
|
|
71
|
-
|
|
72
|
-
The integrator does NOT delegate synthesis -- they integrate the parallel outputs themselves.
|
|
73
|
-
|
|
74
|
-
### 4. SDET (1-2 agents, model: opus)
|
|
75
|
-
|
|
76
|
-
**Job:** Write tests + capture screenshots. For each shipped feature:
|
|
77
|
-
|
|
78
|
-
- One or more bash / Playwright tests asserting acceptance criteria
|
|
79
|
-
- For UI surfaces: screenshot capture with `chrome --headless --screenshot` or Playwright
|
|
80
|
-
- For backends: curl-based smoke tests
|
|
81
|
-
|
|
82
|
-
**Output:** test files + screenshot artifacts under `artifacts/<release>-screens/`.
|
|
83
|
-
|
|
84
|
-
### 5. Council Reviewers (3 agents, parallel, model: 2 opus + 1 sonnet)
|
|
85
|
-
|
|
86
|
-
**Job:** Independent code review. Binding gate: unanimous APPROVE required to ship.
|
|
87
|
-
|
|
88
|
-
**Pattern:** spawn 3 agents in parallel via `Agent` tool. Each gets:
|
|
89
|
-
|
|
90
|
-
- The full file diff at HEAD
|
|
91
|
-
- Their specialized focus (e.g. "frontend correctness", "backend / integration risk", "release readiness")
|
|
92
|
-
- Strict output format: `VOTE: APPROVE | CONCERN | REJECT` + findings list + reasoning
|
|
93
|
-
|
|
94
|
-
On any CONCERN or REJECT:
|
|
95
|
-
|
|
96
|
-
1. Integrator reads source + validates concern
|
|
97
|
-
2. If valid: dispatch fix agent + RE-RUN entire council on post-fix state
|
|
98
|
-
3. If invalid: refute with evidence + re-spawn ONLY the dissenting reviewer with the refutation
|
|
99
|
-
4. Loop until 3-of-3 APPROVE
|
|
100
|
-
5. "2-of-3 is good enough" is NEVER acceptable
|
|
101
|
-
|
|
102
|
-
### 6. Real-User QA (1 agent OR the integrator directly)
|
|
103
|
-
|
|
104
|
-
**Job:** Install the just-shipped release fresh from npm/bun, run a user-realistic scenario end-to-end, capture screenshots, report any breakage.
|
|
105
|
-
|
|
106
|
-
**Pattern:** after `gh release` confirms, run:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
bun install -g loki-mode@<NEW_VERSION>
|
|
110
|
-
loki --version # confirm new version on PATH
|
|
111
|
-
# Then exercise the new feature in a user-realistic way:
|
|
112
|
-
loki <new-command> ... # the change we just shipped
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Capture:
|
|
116
|
-
- Exit codes
|
|
117
|
-
- Output structure
|
|
118
|
-
- Any unexpected errors / warnings
|
|
119
|
-
- Browser screenshots if UI surface
|
|
120
|
-
|
|
121
|
-
## Parallel-execution rules
|
|
122
|
-
|
|
123
|
-
When spawning multiple agents in the SAME message:
|
|
124
|
-
|
|
125
|
-
- Use `Agent` tool with `run_in_background: true`
|
|
126
|
-
- Send all N tool calls in a SINGLE message (parallel scheduling)
|
|
127
|
-
- Each agent gets a SELF-CONTAINED prompt (no shared context)
|
|
128
|
-
- Each agent gets a SHORT response cap (under 250 words)
|
|
129
|
-
- The integrator INTEGRATES the parallel outputs -- never delegates synthesis
|
|
130
|
-
|
|
131
|
-
Anti-pattern: spawning agents sequentially when work is independent. Always parallel.
|
|
132
|
-
|
|
133
|
-
## Honest acknowledgements pattern
|
|
134
|
-
|
|
135
|
-
Every CHANGELOG entry that ships work via this pattern MUST include:
|
|
136
|
-
|
|
137
|
-
```markdown
|
|
138
|
-
### NOT tested in this release
|
|
139
|
-
|
|
140
|
-
- <each test that was skipped + reason>
|
|
141
|
-
- <any feature shipped without end-to-end real-user repro>
|
|
142
|
-
- <any divergence from architect plan + workaround>
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Failing to disclose is fabrication. CLAUDE.md MEMORY.md "Be real, no fabrication, no lying" applies.
|
|
146
|
-
|
|
147
|
-
## Reference run: v7.6.0 LSP integration
|
|
148
|
-
|
|
149
|
-
Demonstrated this pattern works:
|
|
150
|
-
|
|
151
|
-
1. **Architect** (Plan agent): designed Merge-3 in `docs/MERGE3-PLAN.md`
|
|
152
|
-
2. **Product Owner** (integrator + AskUserQuestion): user chose merge scope
|
|
153
|
-
3. **Dev Fleet** (3 principal engineers in parallel): Engineer A fixed memory PYTHONPATH; Engineer B added USAGE.md auto-gen across bash + TS; Engineer C added Memory drill-down UI
|
|
154
|
-
4. **SDET** (Explore + Playwright): captured 20+ UI screenshots, ran 24-scenario CLI permutation test
|
|
155
|
-
5. **Council** (2 Opus + 1 Sonnet): 2 rounds; round 1 had 2 CONCERN-major; fixes applied; round 2 unanimous APPROVE
|
|
156
|
-
6. **Real-user QA**: fresh `bun install -g loki-mode@7.7.0` + ran on a different stack (Python Flask) than dev test + verified USAGE.md auto-generated + Memory drill-down rendered in a real browser
|
|
157
|
-
|
|
158
|
-
Result: 4 releases shipped that day with all 8 GitHub workflows SUCCESS on each.
|
|
159
|
-
|
|
160
|
-
## Per-release checklist (always)
|
|
161
|
-
|
|
162
|
-
The binding release procedure is the **Release Workflow** section of `CLAUDE.md`,
|
|
163
|
-
which is the authoritative and maintained copy: version bump across every listed
|
|
164
|
-
file, dashboard build, tests, pre-publish validation, commit and push, and
|
|
165
|
-
distribution verification across all channels.
|
|
166
|
-
|
|
167
|
-
This previously pointed at an artifacts/ROADMAP file which has never
|
|
168
|
-
existed in this repository -- so an agent following it for the "binding" steps
|
|
169
|
-
found nothing and had to guess. The steps live in one place now, and that place
|
|
170
|
-
is kept current because every release edits it.
|
package/tools/cockpit/SPEC.md
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
# CEO cockpit: specification
|
|
2
|
-
|
|
3
|
-
Status: spec only (owner: platform-lead to build; chief-of-staff to accept).
|
|
4
|
-
Source of the ask: docs/v10/RETRO-2026.md section 6 item 6 (CEO console) and
|
|
5
|
-
item 7 (ROI ledger).
|
|
6
|
-
|
|
7
|
-
New-file justification (CLAUDE.md "extend, never duplicate"): no existing file
|
|
8
|
-
owns company operations for the founder. `dashboard/server.py` is the
|
|
9
|
-
user-facing per-run product dashboard and must stay free of company state;
|
|
10
|
-
`scripts/v10-pulse.sh`, `tools/cost-history.py` and `scripts/usage-governor.py`
|
|
11
|
-
already own pulse, run cost and usage, so the cockpit only invokes them and
|
|
12
|
-
renders their output. It re-implements none of their logic.
|
|
13
|
-
|
|
14
|
-
## 1. Goals and non-goals
|
|
15
|
-
Goals:
|
|
16
|
-
- One page where the CEO sees, within 5 seconds of opening, what the company
|
|
17
|
-
is doing, what shipped, what is blocked and what it costs against value.
|
|
18
|
-
- One write path: a founder command box that appends a row to
|
|
19
|
-
docs/v10/FOUNDER-QUEUE.md for the chief-of-staff to act on.
|
|
20
|
-
Non-goals:
|
|
21
|
-
- No direct control. Stop-all, dispatch and release actions are queue rows
|
|
22
|
-
("STOP ALL", "pause release") that the chief-of-staff executes by recorded
|
|
23
|
-
PID or through release-reliability-lead. The cockpit never signals a
|
|
24
|
-
process, edits BOARD.md, runs git writes or calls npm publish.
|
|
25
|
-
- No hosted mode, no auth provider, no telemetry.
|
|
26
|
-
|
|
27
|
-
## 2. Hard constraints
|
|
28
|
-
1. Server: Python 3 standard library only (`http.server`,
|
|
29
|
-
`ThreadingHTTPServer`, `json`, `subprocess`, `fcntl`, `secrets`). No pip
|
|
30
|
-
dependency.
|
|
31
|
-
2. Client: one static file `tools/cockpit/index.html` with inline CSS and JS.
|
|
32
|
-
No build step, no CDN, no framework. Works offline.
|
|
33
|
-
3. Bind 127.0.0.1 only. The `--host` flag accepts only `127.0.0.1` or `::1`;
|
|
34
|
-
any other value exits 64 with a message. Never `0.0.0.0`.
|
|
35
|
-
4. Read-only except `POST /api/queue`, which only appends to FOUNDER-QUEUE.md.
|
|
36
|
-
5. Testable headless: `--once --json` prints the full snapshot and exits; no
|
|
37
|
-
browser is ever opened (honour LOKI_NO_BROWSER; no `webbrowser` import).
|
|
38
|
-
6. Every shell-out has a timeout (default 20 s; pulse 60 s) and a cache, so a
|
|
39
|
-
hung `gh` or `npm` never blocks the page. A failed source renders
|
|
40
|
-
UNKNOWN with the error line, never a blank or a 0.
|
|
41
|
-
7. No emojis, no em or en dashes in code, UI text or output.
|
|
42
|
-
|
|
43
|
-
## 3. Files
|
|
44
|
-
- `tools/cockpit/server.py`: server, collectors, snapshot builder, CLI.
|
|
45
|
-
- `tools/cockpit/index.html`: the page.
|
|
46
|
-
- `tools/cockpit/roi-basis.json`: the salary basis and ROI assumptions (section
|
|
47
|
-
5.6). Tracked, edited by hand or by the chief-of-staff, versioned in git.
|
|
48
|
-
- `tests/test-cockpit.sh`: headless test, registered in
|
|
49
|
-
`tests/run-all-tests.sh` and the shard map (retro 3.3.21).
|
|
50
|
-
- Runtime only (untracked, under `.loki/`): `.loki/company/status/<slug>.json`
|
|
51
|
-
(written by each seat), `.loki/cockpit/cache/*.json`, `.loki/cockpit/token`.
|
|
52
|
-
|
|
53
|
-
## 4. CLI
|
|
54
|
-
```
|
|
55
|
-
python3 tools/cockpit/server.py [--port 8787] [--host 127.0.0.1]
|
|
56
|
-
[--repo-root PATH] [--once] [--json]
|
|
57
|
-
[--panel NAME]
|
|
58
|
-
```
|
|
59
|
-
- `--once --json`: build one snapshot, print it, exit 0 (exit 2 if any panel
|
|
60
|
-
is UNKNOWN, mirroring the pulse contract 0 clean, 1 violation, 2 unknown;
|
|
61
|
-
exit 1 if the pulse reports a VIOLATION).
|
|
62
|
-
- `--panel NAME`: restrict `--once` to one panel (pulse, releases, board,
|
|
63
|
-
agents, okrs, roi, queue).
|
|
64
|
-
- Env overrides (for tests and fixtures): `COCKPIT_NPM_CMD`, `COCKPIT_GH_CMD`,
|
|
65
|
-
`COCKPIT_PULSE_CMD`, `BOARD_MD`, `FOUNDER_QUEUE_MD`, `RETRO_MD`,
|
|
66
|
-
`USAGE_READINGS_TSV`, `COST_HISTORY_FILE`, `COCKPIT_STATUS_DIR`,
|
|
67
|
-
`COCKPIT_NOW` (ISO8601 UTC, for deterministic ages).
|
|
68
|
-
- On start the server prints `cockpit: http://127.0.0.1:<port>/` and its PID,
|
|
69
|
-
and writes the PID to `.loki/cockpit/server.pid` so it is stopped by
|
|
70
|
-
recorded PID only.
|
|
71
|
-
|
|
72
|
-
## 5. Panels and data sources
|
|
73
|
-
Each panel in the snapshot has the shape
|
|
74
|
-
`{status: OK|VIOLATION|UNKNOWN|UNMEASURED, as_of, source_cmd, data, error}`.
|
|
75
|
-
`source_cmd` is the exact command or file read, shown on the page under each
|
|
76
|
-
panel (evidence rule, retro 3.1.1).
|
|
77
|
-
|
|
78
|
-
### 5.1 Pulse
|
|
79
|
-
- Source: `bash scripts/v10-pulse.sh` (override `COCKPIT_PULSE_CMD`), run with
|
|
80
|
-
`PULSE_REPO_ROOT` set to the repo root. Cached 90 s; refreshed in a
|
|
81
|
-
background thread so a request never waits on it.
|
|
82
|
-
- Parse: every `Key: value` line into `metrics`; every line under
|
|
83
|
-
`=== VIOLATIONS ===` starting `VIOLATION:` into `violations`; the
|
|
84
|
-
`UNKNOWN metrics:` and `STALE metrics` lines into lists. Exit code 0, 1 or 2
|
|
85
|
-
maps to OK, VIOLATION, UNKNOWN.
|
|
86
|
-
- Render: violations first in a red band, top one largest; then the metric
|
|
87
|
-
table; STALE values shown with their age.
|
|
88
|
-
|
|
89
|
-
### 5.2 Releases
|
|
90
|
-
- npm: `npm view loki-mode time dist-tags --json` (override
|
|
91
|
-
`COCKPIT_NPM_CMD`). Show `dist-tags.latest`, `dist-tags.next`, the last 20
|
|
92
|
-
versions with publish time, releases in the last hour and 24 h, and minutes
|
|
93
|
-
since the last publish.
|
|
94
|
-
- Release runs: `gh run list --workflow release.yml --limit 20 --json
|
|
95
|
-
databaseId,status,conclusion,headSha,createdAt,displayTitle,url` (override
|
|
96
|
-
`COCKPIT_GH_CMD`). Show each run with conclusion and link.
|
|
97
|
-
- Local: `VERSION` file and `git -C <root> describe --tags --abbrev=0`.
|
|
98
|
-
- Derived flags: VERSION vs next vs latest divergence (retro 3.2.27); a
|
|
99
|
-
release run with conclusion failure on the newest VERSION SHA is a
|
|
100
|
-
VIOLATION. A cached packument is not proof: the panel labels npm data
|
|
101
|
-
"registry view" and never claims a tarball is fetchable (retro 3.2.7).
|
|
102
|
-
|
|
103
|
-
### 5.3 BOARD flow
|
|
104
|
-
- Source: `docs/v10/BOARD.md` (override `BOARD_MD`). Parse table rows with
|
|
105
|
-
columns `ID | Owner | Branch @ SHA | File set | Tier | Status | Notes`.
|
|
106
|
-
Status cell is `<token>@YYYY-MM-DDTHH:MMZ`; tokens: ready, building, review,
|
|
107
|
-
review-blocked, approved, merged, released, blocked, rejected, parked.
|
|
108
|
-
- Render: count per token (flow strip ready, building, review, approved,
|
|
109
|
-
merged, released), the active rows (building, review, review-blocked,
|
|
110
|
-
approved, blocked) with age in minutes against their tier budget (LOW 15,
|
|
111
|
-
MEDIUM 30, HIGH 60 per OPERATING-MODEL.md), and an "unparsed rows" list.
|
|
112
|
-
Ready count below 30 is flagged (D91).
|
|
113
|
-
|
|
114
|
-
### 5.4 Agents
|
|
115
|
-
- Source: `.loki/company/status/<slug>.json` for the 10 slugs in
|
|
116
|
-
`.claude/agents/` (list derived from that directory, never hard-coded).
|
|
117
|
-
Schema: `{seat, model, doing, slice, since, next, blocked_on, updated}`.
|
|
118
|
-
- Render one card per seat: model, what it is doing, slice ID linking to the
|
|
119
|
-
BOARD row, minutes since `updated`. A seat with no file is UNKNOWN; a file
|
|
120
|
-
older than 60 min is STALE; `blocked_on` non-empty is highlighted.
|
|
121
|
-
- Also show the seat's owned root causes, parsed from the "Root causes
|
|
122
|
-
owned" section of its agent file.
|
|
123
|
-
|
|
124
|
-
### 5.5 OKRs
|
|
125
|
-
- Source: `docs/v10/RETRO-2026.md` section 6 (override `RETRO_MD`): the 20
|
|
126
|
-
numbered items, each parsed into title (first sentence), owner (text after
|
|
127
|
-
`Owner:` up to the next period) and metric (text after `Metric:`).
|
|
128
|
-
- Current values: `.loki/company/okrs.json`, written by the owning seats,
|
|
129
|
-
shape `{"<item number>": {value, target, status, source_cmd, as_of}}`.
|
|
130
|
-
- Render the 20 rows ranked as in the retro. An item with no current value
|
|
131
|
-
shows UNMEASURED, never 0 and never green. A value without `source_cmd` is
|
|
132
|
-
shown as UNCITED and counts against verification-scientist.
|
|
133
|
-
|
|
134
|
-
### 5.6 ROI
|
|
135
|
-
Two sides, always labelled with their measurement state.
|
|
136
|
-
|
|
137
|
-
Agent cost (left side):
|
|
138
|
-
- Plan cost: `roi-basis.json` field `plan_usd_per_month` (default 200, the
|
|
139
|
-
founder's stated spend, retro RC9 evidence), prorated per day.
|
|
140
|
-
- Usage share: `docs/v10/usage-readings.tsv` (columns `utc_time
|
|
141
|
-
window_percent weekly_percent`) and `python3 scripts/usage-governor.py
|
|
142
|
-
--json`. These are plan-usage percentages, not tokens or dollars; the panel
|
|
143
|
-
says so and shows weekly percent used.
|
|
144
|
-
- Metered run cost: `python3 tools/cost-history.py report --json` (file
|
|
145
|
-
override `COST_HISTORY_FILE`). Shows measured runs, unmeasured runs (usd
|
|
146
|
-
null) as a separate count, and total measured USD. A missing history file
|
|
147
|
-
is UNMEASURED.
|
|
148
|
-
- Budget line: the $50 per day budget from FOUNDER-QUEUE row 3, as a
|
|
149
|
-
configurable `daily_budget_usd`.
|
|
150
|
-
- Cost is labelled ESTIMATE when derived from plan proration, MEASURED only
|
|
151
|
-
when it comes from cost-history measured rows.
|
|
152
|
-
|
|
153
|
-
Human-equivalent value (right side):
|
|
154
|
-
- Salary basis in `roi-basis.json`, versioned, every figure with source URL
|
|
155
|
-
and snapshot date:
|
|
156
|
-
```json
|
|
157
|
-
{
|
|
158
|
-
"source_url": "https://www.levels.fyi/companies/anthropic/salaries/software-engineer",
|
|
159
|
-
"snapshot_date": "2026-09-24",
|
|
160
|
-
"annual_total_comp_usd": {
|
|
161
|
-
"entry": 483000, "senior": 621000, "lead": 865000,
|
|
162
|
-
"staff": 1410000, "median": 883000
|
|
163
|
-
},
|
|
164
|
-
"research_scientist_median_usd": {"value": null, "status": "UNVERIFIED"},
|
|
165
|
-
"research_engineer_usd": {"value": null, "status": "NOT FOUND"},
|
|
166
|
-
"overhead_multiplier": {"value": 1.25, "status": "ASSUMPTION"},
|
|
167
|
-
"work_hours_per_year": {"value": 2000, "status": "ASSUMPTION"},
|
|
168
|
-
"seat_tier": {"chief-of-staff": "lead", "cto": "staff", "...": "..."},
|
|
169
|
-
"hours_per_outcome": {"verified_slice": {"value": null, "status": "ASSUMPTION, unset"}},
|
|
170
|
-
"plan_usd_per_month": 200,
|
|
171
|
-
"daily_budget_usd": 50
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
The figures match RETRO-2026.md 3.8.10 and were re-fetched from the URL on
|
|
175
|
-
2026-10-23. The basis is flagged STALE when `snapshot_date` is older than
|
|
176
|
-
90 days.
|
|
177
|
-
- Value formula, shown on the page: hourly rate = annual total comp x
|
|
178
|
-
overhead multiplier / work hours per year; human-equivalent value = sum over
|
|
179
|
-
released slices (BOARD released tokens in the window) of hours per outcome
|
|
180
|
-
x hourly rate for the owning seat's tier.
|
|
181
|
-
- Value is UNMEASURED while `hours_per_outcome` is unset. The page then shows
|
|
182
|
-
only "standing 10-seat payroll equivalent" (sum of tier comp x overhead for
|
|
183
|
-
10 seats, labelled ASSUMPTION) next to agent cost, and never prints an ROI
|
|
184
|
-
multiple.
|
|
185
|
-
- ROI multiple is shown only when both sides are non-null, with the label of
|
|
186
|
-
the weaker side (ESTIMATE or ASSUMPTION). Per verified outcome cost comes
|
|
187
|
-
from the outcome scoreboard (`.loki/company/scoreboard/*.json`) when it
|
|
188
|
-
exists, else UNMEASURED.
|
|
189
|
-
- Every assumption is editable only in `roi-basis.json`; the page shows its
|
|
190
|
-
path and git SHA, never an inline editor.
|
|
191
|
-
|
|
192
|
-
### 5.7 Founder command box
|
|
193
|
-
- UI: one textarea (max 2000 characters), one "Why only you" optional field,
|
|
194
|
-
one submit button. After submit, the page shows the appended row number
|
|
195
|
-
and the line written.
|
|
196
|
-
- `POST /api/queue`, body JSON `{item, why}`; returns `{row, line}`.
|
|
197
|
-
- Append rules:
|
|
198
|
-
1. Take an exclusive `fcntl.flock` on `FOUNDER-QUEUE.md.lock` (sidecar,
|
|
199
|
-
under `.loki/cockpit/`), with a 5 s timeout returning 503.
|
|
200
|
-
2. Read the file; allocate the next number as max existing `#` + 1.
|
|
201
|
-
3. Sanitize: strip control characters, replace newlines with spaces and
|
|
202
|
-
`|` with `/`, trim, reject empty (400) or over the cap (413).
|
|
203
|
-
4. Write one row in the existing header shape
|
|
204
|
-
`| # | Date | Item | Why only you | Loop does meanwhile |` with Date as
|
|
205
|
-
today UTC `YYYY-MM-DD`, Item prefixed `[cockpit]`, Why from the field or
|
|
206
|
-
`founder command`, Loop cell `chief-of-staff to triage`, plus trailing
|
|
207
|
-
status cell `open`.
|
|
208
|
-
5. Append only (`open(path, "a")`), then fsync, then re-read and verify the
|
|
209
|
-
file did not shrink and the new row is the last line (shrink guard,
|
|
210
|
-
retro 3.3.17). On failure return 500 and leave the file unchanged.
|
|
211
|
-
- The cockpit never commits the change; the chief-of-staff triages and
|
|
212
|
-
commits.
|
|
213
|
-
|
|
214
|
-
## 6. HTTP API
|
|
215
|
-
| Method | Path | Returns |
|
|
216
|
-
|---|---|---|
|
|
217
|
-
| GET | `/` | index.html |
|
|
218
|
-
| GET | `/api/snapshot` | all panels |
|
|
219
|
-
| GET | `/api/panel/<name>` | one panel |
|
|
220
|
-
| GET | `/healthz` | `{"ok": true, "pid": N}` |
|
|
221
|
-
| POST | `/api/queue` | append result |
|
|
222
|
-
Every other method or path returns 405 or 404.
|
|
223
|
-
|
|
224
|
-
Security:
|
|
225
|
-
- Reject any request whose `Host` header is not `127.0.0.1:<port>`,
|
|
226
|
-
`localhost:<port>` or `[::1]:<port>` (DNS rebinding).
|
|
227
|
-
- `POST /api/queue` requires header `X-Cockpit-Token` equal to a per-process
|
|
228
|
-
random token (`secrets.token_urlsafe(32)`), written to
|
|
229
|
-
`.loki/cockpit/token` with mode 600 and injected into the served page; and
|
|
230
|
-
an `Origin` equal to the served origin. Missing or wrong: 403.
|
|
231
|
-
- Request body capped at 8 KB. Responses set `Cache-Control: no-store`,
|
|
232
|
-
`X-Content-Type-Options: nosniff` and a CSP of `default-src 'self';
|
|
233
|
-
script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'`.
|
|
234
|
-
- Subprocesses run with an argument list (never `shell=True`) and an env built
|
|
235
|
-
deny-by-default (PATH, HOME, USER, LOGNAME, LANG, gh and npm config paths
|
|
236
|
-
only), per security-lead rule 3.9.2.
|
|
237
|
-
- No file path from a request is ever opened; all paths come from flags or
|
|
238
|
-
env.
|
|
239
|
-
|
|
240
|
-
## 7. Page behaviour
|
|
241
|
-
- Polls `/api/snapshot` every 15 s; panels update in place without layout
|
|
242
|
-
shift (fixed card heights, skeleton rows); a "last refreshed" time and the
|
|
243
|
-
age of each source are always visible.
|
|
244
|
-
- Order: pulse violations band, agents, BOARD flow, releases, OKRs, ROI,
|
|
245
|
-
command box.
|
|
246
|
-
- Light and dark from `prefers-color-scheme`; readable at 1280 px and 390 px.
|
|
247
|
-
- Every number has a hover or caption with its `source_cmd` and `as_of`.
|
|
248
|
-
|
|
249
|
-
## 8. Headless test (`tests/test-cockpit.sh`)
|
|
250
|
-
Uses `loki_run_tmp_create` and `loki_run_tmp_cleanup`, stops the server by its
|
|
251
|
-
recorded PID only, sets `LOKI_NO_BROWSER=1`. Fixtures under the run tmp dir:
|
|
252
|
-
- A BOARD.md with one row per token plus one unparsed row; assert counts.
|
|
253
|
-
- A FOUNDER-QUEUE.md copy; POST an item containing `|`, a newline and 2001
|
|
254
|
-
characters; assert 413, then a valid item, assert row number = max + 1, the
|
|
255
|
-
pipe replaced, the file only grew, and two concurrent POSTs get distinct
|
|
256
|
-
numbers.
|
|
257
|
-
- Stub `COCKPIT_NPM_CMD` and `COCKPIT_GH_CMD` scripts emitting fixed JSON,
|
|
258
|
-
and one that sleeps past the timeout; assert UNKNOWN, not a hang.
|
|
259
|
-
- Missing cost-history and empty status dir: assert ROI cost UNMEASURED and
|
|
260
|
-
agents UNKNOWN, and that no panel prints `0` for an unmeasured value.
|
|
261
|
-
- `--host 0.0.0.0` exits 64. POST without token: 403. Bad Host: 403.
|
|
262
|
-
- `--once --json` output parses and its exit code matches the pulse stub's
|
|
263
|
-
exit code mapping.
|
|
264
|
-
- Positive control for every absence assertion (retro 3.1.6): the same probe
|
|
265
|
-
run on a fixture that does contain the value must find it.
|
|
266
|
-
|
|
267
|
-
## 9. Acceptance (Wall checks)
|
|
268
|
-
1. `python3 tools/cockpit/server.py --once --json | python3 -m json.tool`
|
|
269
|
-
exits 0 or 2 on a clean checkout, with all 7 panels present.
|
|
270
|
-
2. `bash tests/test-cockpit.sh` passes, and fails when the append sanitizer
|
|
271
|
-
or the Host check is removed (mutation).
|
|
272
|
-
3. `lsof -nP -iTCP:<port> -sTCP:LISTEN` shows 127.0.0.1 only.
|
|
273
|
-
4. No file under the repo changes after an hour of page polling except
|
|
274
|
-
FOUNDER-QUEUE.md on submit (`git status --porcelain` diff).
|
|
275
|
-
5. Screenshot at 1280 px and 390 px reviewed by developer-experience-lead.
|
package/tools/cockpit/index.html
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>Loki Cockpit</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root{--bg:#f4f5f8;--card:#fff;--ink:#14161c;--mute:#5b6270;--line:#d9dde6;--ok:#17653a;--bad:#a4161a;--warn:#8a5a00;--unk:#4a4f6a;--badbg:#fde8e8;--accent:#2b4ed8}
|
|
9
|
-
@media (prefers-color-scheme:dark){:root{--bg:#0f1115;--card:#171a21;--ink:#e8eaf0;--mute:#9aa3b5;--line:#2a2f3a;--ok:#5fd08f;--bad:#ff8083;--warn:#f0b955;--unk:#9fa6c8;--badbg:#3a1618;--accent:#8aa2ff}}
|
|
10
|
-
*{box-sizing:border-box}
|
|
11
|
-
body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.45 system-ui,-apple-system,Segoe UI,sans-serif}
|
|
12
|
-
header{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:baseline;padding:12px 16px;border-bottom:1px solid var(--line)}
|
|
13
|
-
header h1{font-size:16px;margin:0}
|
|
14
|
-
#refreshed{color:var(--mute);font-size:12px}
|
|
15
|
-
main{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));gap:12px;padding:12px 16px}
|
|
16
|
-
section{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:12px;min-height:160px;overflow:hidden}
|
|
17
|
-
section.wide{grid-column:1/-1}
|
|
18
|
-
h2{font-size:13px;margin:0 0 8px;text-transform:uppercase;letter-spacing:.04em;display:flex;gap:8px;align-items:center}
|
|
19
|
-
.badge{font-size:11px;padding:1px 6px;border-radius:10px;border:1px solid currentColor}
|
|
20
|
-
.OK{color:var(--ok)}.VIOLATION{color:var(--bad)}.UNKNOWN,.UNMEASURED,.UNCITED{color:var(--unk)}.STALE{color:var(--warn)}
|
|
21
|
-
.src{margin-top:8px;color:var(--mute);font:11px ui-monospace,Menlo,monospace;word-break:break-all}
|
|
22
|
-
.err{color:var(--warn);font-size:12px;margin:4px 0}
|
|
23
|
-
.band{background:var(--badbg);color:var(--bad);border:1px solid var(--bad);border-radius:6px;padding:8px;margin-bottom:8px}
|
|
24
|
-
.band .top{font-size:16px;font-weight:600}
|
|
25
|
-
table{width:100%;border-collapse:collapse;font-size:12px}
|
|
26
|
-
td,th{text-align:left;padding:3px 6px 3px 0;border-bottom:1px solid var(--line);vertical-align:top;word-break:break-word}
|
|
27
|
-
.flow{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
|
28
|
-
.flow div{border:1px solid var(--line);border-radius:6px;padding:4px 8px;min-width:78px}
|
|
29
|
-
.flow b{display:block;font-size:18px}
|
|
30
|
-
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:8px}
|
|
31
|
-
.card{border:1px solid var(--line);border-radius:6px;padding:8px;font-size:12px}
|
|
32
|
-
.card.blocked{border-color:var(--bad)}
|
|
33
|
-
.mute{color:var(--mute)}
|
|
34
|
-
textarea,input[type=text]{width:100%;background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:8px;font:inherit}
|
|
35
|
-
button{background:var(--accent);color:#fff;border:0;border-radius:6px;padding:8px 14px;font:inherit;cursor:pointer}
|
|
36
|
-
button:disabled{opacity:.5}
|
|
37
|
-
#qres{margin-top:8px;font-size:12px;min-height:18px;word-break:break-word}
|
|
38
|
-
</style>
|
|
39
|
-
</head>
|
|
40
|
-
<body>
|
|
41
|
-
<header><h1>Loki Cockpit</h1><span id="refreshed">loading</span><span class="mute" id="fail"></span></header>
|
|
42
|
-
<main>
|
|
43
|
-
<section class="wide" id="p-pulse"><h2>Pulse</h2><div class="body">loading</div></section>
|
|
44
|
-
<section class="wide" id="p-agents"><h2>Agents</h2><div class="body">loading</div></section>
|
|
45
|
-
<section id="p-board"><h2>BOARD flow</h2><div class="body">loading</div></section>
|
|
46
|
-
<section id="p-releases"><h2>Releases</h2><div class="body">loading</div></section>
|
|
47
|
-
<section class="wide" id="p-okrs"><h2>OKRs</h2><div class="body">loading</div></section>
|
|
48
|
-
<section class="wide" id="p-roi"><h2>ROI</h2><div class="body">loading</div></section>
|
|
49
|
-
<section class="wide" id="p-queue"><h2>Founder command box</h2><div class="body">loading</div>
|
|
50
|
-
<div>
|
|
51
|
-
<textarea id="item" rows="3" maxlength="2000" placeholder="Command or decision for the chief of staff (max 2000 characters)"></textarea>
|
|
52
|
-
<input type="text" id="why" maxlength="500" placeholder="Why only you (optional)">
|
|
53
|
-
<p><button id="send">Append to FOUNDER-QUEUE</button> <span class="mute" id="count">0/2000</span></p>
|
|
54
|
-
<div id="qres"></div>
|
|
55
|
-
</div>
|
|
56
|
-
</section>
|
|
57
|
-
</main>
|
|
58
|
-
<script>
|
|
59
|
-
(function(){
|
|
60
|
-
"use strict";
|
|
61
|
-
var TOKEN="__COCKPIT_TOKEN__";
|
|
62
|
-
function h(tag,attrs){var e=document.createElement(tag);if(attrs){for(var k in attrs){if(k==="class")e.className=attrs[k];else if(k==="title")e.title=attrs[k];else e.setAttribute(k,attrs[k]);}}
|
|
63
|
-
for(var i=2;i<arguments.length;i++){var c=arguments[i];if(c===null||c===undefined)continue;e.appendChild(typeof c==="object"?c:document.createTextNode(String(c)));}return e;}
|
|
64
|
-
function show(v){return v===null||v===undefined?"UNKNOWN":String(v);}
|
|
65
|
-
function badge(s){return h("span",{"class":"badge "+s},s);}
|
|
66
|
-
function src(p){return h("div",{"class":"src",title:"as of "+p.as_of},"source: "+p.source_cmd+" as of "+p.as_of+(p.cache_age_s!==undefined?" cached "+p.cache_age_s+"s":""));}
|
|
67
|
-
function err(p){return p.error?h("div",{"class":"err"},p.error):null;}
|
|
68
|
-
function table(rows,head){var t=h("table");if(head){var tr=h("tr");head.forEach(function(x){tr.appendChild(h("th",null,x));});t.appendChild(tr);}
|
|
69
|
-
rows.forEach(function(r){var tr=h("tr");r.forEach(function(c){tr.appendChild(h("td",null,c));});t.appendChild(tr);});return t;}
|
|
70
|
-
function fill(id,p,build){var s=document.getElementById("p-"+id);var b=s.querySelector(".body");var h2=s.querySelector("h2");
|
|
71
|
-
while(h2.childNodes.length>1)h2.removeChild(h2.lastChild);h2.appendChild(badge(p.status));
|
|
72
|
-
var nb=h("div",{"class":"body"});try{build(nb,p.data||{},p);}catch(e){nb.appendChild(h("div",{"class":"err"},"render error: "+e));}
|
|
73
|
-
nb.appendChild(err(p));nb.appendChild(src(p));s.replaceChild(nb,b);}
|
|
74
|
-
|
|
75
|
-
var R={};
|
|
76
|
-
R.pulse=function(b,d){
|
|
77
|
-
var v=d.violations||[];
|
|
78
|
-
if(v.length){var band=h("div",{"class":"band"});band.appendChild(h("div",{"class":"top"},v[0]));
|
|
79
|
-
v.slice(1).forEach(function(x){band.appendChild(h("div",null,x));});b.appendChild(band);}
|
|
80
|
-
else if(d.exit_code===0)b.appendChild(h("div",{"class":"OK"},"No violations."));
|
|
81
|
-
var m=d.metrics||{};b.appendChild(table(Object.keys(m).map(function(k){return [k,m[k]];})));
|
|
82
|
-
if((d.unknown_metrics||[]).length)b.appendChild(h("p",{"class":"mute"},"UNKNOWN metrics: "+d.unknown_metrics.join(", ")));
|
|
83
|
-
(d.stale||[]).forEach(function(x){b.appendChild(h("p",{"class":"STALE"},x));});};
|
|
84
|
-
R.agents=function(b,d){var c=h("div",{"class":"cards"});
|
|
85
|
-
(d.seats||[]).forEach(function(s){var card=h("div",{"class":"card"+(s.blocked?" blocked":"")});
|
|
86
|
-
card.appendChild(h("div",null,h("b",null,s.slug)," ",badge(s.state)));
|
|
87
|
-
if(s.state==="UNKNOWN"){card.appendChild(h("div",{"class":"mute"},s.error||"no status file"));}
|
|
88
|
-
else{card.appendChild(h("div",null,"model: "+show(s.model)));card.appendChild(h("div",null,"doing: "+show(s.doing)));
|
|
89
|
-
card.appendChild(h("div",null,"slice: "+show(s.slice)));card.appendChild(h("div",null,"updated: "+show(s.updated_min_ago)+" min ago"));
|
|
90
|
-
if(s.blocked_on)card.appendChild(h("div",{"class":"VIOLATION"},"blocked on: "+s.blocked_on));}
|
|
91
|
-
var tk=s.tick||{};card.appendChild(h("div",null,"last tick: "+show(tk.last_tick)+" ("+show(tk.outcome)+")"));
|
|
92
|
-
card.appendChild(h("div",null,"next due: "+show(tk.next_due)+(tk.state==="STALE"?" STALE (no tick in 2x "+tk.interval_min+" min)":"")));
|
|
93
|
-
(s.root_causes||[]).forEach(function(r){card.appendChild(h("div",{"class":"mute"},r));});c.appendChild(card);});
|
|
94
|
-
b.appendChild(c);};
|
|
95
|
-
R.board=function(b,d){var f=h("div",{"class":"flow"});var cs=d.counts||{};
|
|
96
|
-
["ready","building","review","approved","merged","released"].forEach(function(t){f.appendChild(h("div",null,h("b",null,show(cs[t])),t));});b.appendChild(f);
|
|
97
|
-
if(d.ready_below_30)b.appendChild(h("div",{"class":"err"},"ready queue below "+d.ready_target+" (D91)"));
|
|
98
|
-
b.appendChild(table((d.active||[]).map(function(r){return [r.id,r.owner,r.tier,r.token,show(r.age_min)+" / "+show(r.budget_min)+" min"+(r.over_budget?" OVER":"")];}),["ID","Owner","Tier","Status","Age / budget"]));
|
|
99
|
-
if((d.unparsed||[]).length)b.appendChild(h("p",{"class":"mute"},"Unparsed rows: "+d.unparsed.join(", ")));};
|
|
100
|
-
R.releases=function(b,d){
|
|
101
|
-
b.appendChild(table([["npm latest",show(d.latest)],["npm next",show(d.next)],["VERSION",show(d.version_file)],["last tag",show(d.last_tag)],
|
|
102
|
-
["minutes since last publish",show(d.last_publish_minutes_ago)],["releases last hour",show(d.releases_last_hour)],["releases last 24h",show(d.releases_last_24h)]]));
|
|
103
|
-
b.appendChild(h("p",{"class":"mute"},d.npm_label));
|
|
104
|
-
(d.flags||[]).forEach(function(x){b.appendChild(h("div",{"class":"VIOLATION"},x));});
|
|
105
|
-
b.appendChild(table((d.runs||[]).slice(0,8).map(function(r){var a=h("a",{href:r.url||"#",rel:"noreferrer",target:"_blank"},String(r.databaseId));return [a,show(r.conclusion||r.status),(r.headSha||"").slice(0,8)];}),["Run","Result","SHA"]));
|
|
106
|
-
b.appendChild(table((d.versions||[]).slice(0,10).map(function(v){return [v.version,v.published];}),["Version","Published"]));};
|
|
107
|
-
R.okrs=function(b,d){b.appendChild(table((d.items||[]).map(function(i){
|
|
108
|
-
var cur=i.current?(show(i.current.value)+(i.current.target!==undefined?" / "+i.current.target:"")):"";
|
|
109
|
-
return [i.n,i.title,show(i.owner),h("span",{"class":i.state},i.state),cur];}),["#","Item","Owner","State","Value / target"]));};
|
|
110
|
-
R.roi=function(b,d){var c=d.cost||{},v=d.value||{},r=d.roi||{},m=c.metered||{},u=c.usage||{};
|
|
111
|
-
b.appendChild(h("h3",null,"Agent cost ("+c.label+")"));
|
|
112
|
-
b.appendChild(table([["plan USD per month",show(c.plan_usd_per_month)],["plan USD per day (ESTIMATE)",show(c.plan_usd_per_day)],["daily budget USD",show(c.daily_budget_usd)],
|
|
113
|
-
["weekly plan-usage percent",show(u.weekly_percent)],["5h window percent",show(u.window_percent)],
|
|
114
|
-
["metered run cost",m.state==="MEASURED"?("USD "+m.total_usd+" over "+m.measured_runs+" runs ("+m.unmeasured_runs+" unmeasured)"):("UNMEASURED: "+show(m.reason))]]));
|
|
115
|
-
b.appendChild(h("p",{"class":"mute"},c.label_note+". Usage numbers are plan percentages, not tokens or dollars."));
|
|
116
|
-
b.appendChild(h("h3",null,"Human-equivalent value ("+show(v.state||"standing payroll only")+")"));
|
|
117
|
-
var pr=v.standing_payroll_equivalent;
|
|
118
|
-
b.appendChild(table([["standing payroll equivalent per day",pr?("USD "+pr.per_day_usd+" for "+pr.seats+" seats, "+pr.label):"UNKNOWN"],
|
|
119
|
-
["human-equivalent value",v.human_equivalent_usd===null||v.human_equivalent_usd===undefined?"UNMEASURED":"USD "+v.human_equivalent_usd],["ROI multiple",r.multiple===null?"not printed ("+r.note+")":r.multiple+"x ("+r.weaker_side_label+")"],
|
|
120
|
-
["cost per verified outcome",(d.scoreboard||{}).cost_per_verified_outcome_usd===null?"UNMEASURED":"USD "+d.scoreboard.cost_per_verified_outcome_usd]]));
|
|
121
|
-
b.appendChild(h("p",{"class":"mute"},"Formula: "+v.formula));
|
|
122
|
-
var bs=d.basis||{};b.appendChild(h("p",{"class":"mute"},"Basis: "+bs.path+" at "+show(bs.git_sha)+", snapshot "+show(bs.snapshot_date)+(bs.stale?" (STALE: "+bs.stale_note+")":"")+", source "+show(bs.source_url)));
|
|
123
|
-
(d.notes||[]).forEach(function(x){b.appendChild(h("div",{"class":"err"},x));});};
|
|
124
|
-
R.queue=function(b,d){b.appendChild(h("p",null,"Rows: "+show(d.rows_total)+", last number "+show(d.max_number)+", from cockpit "+show(d.cockpit_rows)));
|
|
125
|
-
b.appendChild(table((d.last||[]).map(function(r){return [r.n,r.date,r.item];}),["#","Date","Item"]));};
|
|
126
|
-
|
|
127
|
-
function render(snap){var ps=snap.panels||{};Object.keys(R).forEach(function(k){if(ps[k])fill(k,ps[k],R[k]);});
|
|
128
|
-
document.getElementById("refreshed").textContent="last refreshed "+new Date().toLocaleTimeString()+" (generated "+snap.generated_at+")";
|
|
129
|
-
document.getElementById("fail").textContent="";}
|
|
130
|
-
function poll(){fetch("/api/snapshot",{cache:"no-store"}).then(function(r){return r.json();}).then(render)
|
|
131
|
-
.catch(function(e){document.getElementById("fail").textContent="refresh failed: "+e;});}
|
|
132
|
-
poll();setInterval(poll,15000);
|
|
133
|
-
|
|
134
|
-
var item=document.getElementById("item");
|
|
135
|
-
item.addEventListener("input",function(){document.getElementById("count").textContent=item.value.length+"/2000";});
|
|
136
|
-
document.getElementById("send").addEventListener("click",function(){
|
|
137
|
-
var btn=this,res=document.getElementById("qres");btn.disabled=true;res.textContent="sending";
|
|
138
|
-
fetch("/api/queue",{method:"POST",headers:{"Content-Type":"application/json","X-Cockpit-Token":TOKEN},
|
|
139
|
-
body:JSON.stringify({item:item.value,why:document.getElementById("why").value})})
|
|
140
|
-
.then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});})
|
|
141
|
-
.then(function(x){res.textContent=x.ok?("Appended row "+x.j.row+": "+x.j.line):("Rejected: "+x.j.error);if(x.ok){item.value="";poll();}})
|
|
142
|
-
.catch(function(e){res.textContent="Failed: "+e;}).then(function(){btn.disabled=false;});});
|
|
143
|
-
})();
|
|
144
|
-
</script>
|
|
145
|
-
</body>
|
|
146
|
-
</html>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"source_url": "https://www.levels.fyi/companies/anthropic/salaries/software-engineer",
|
|
3
|
-
"snapshot_date": "2026-09-24",
|
|
4
|
-
"refetched_on": "2026-10-23",
|
|
5
|
-
"annual_total_comp_usd": {
|
|
6
|
-
"entry": 483000,
|
|
7
|
-
"senior": 621000,
|
|
8
|
-
"lead": 865000,
|
|
9
|
-
"staff": 1410000,
|
|
10
|
-
"median": 883000
|
|
11
|
-
},
|
|
12
|
-
"research_scientist_median_usd": {"value": null, "status": "UNVERIFIED"},
|
|
13
|
-
"research_engineer_usd": {"value": null, "status": "NOT FOUND"},
|
|
14
|
-
"overhead_multiplier": {"value": 1.25, "status": "ASSUMPTION"},
|
|
15
|
-
"work_hours_per_year": {"value": 2000, "status": "ASSUMPTION"},
|
|
16
|
-
"default_tier": "senior",
|
|
17
|
-
"seat_tier_status": "ASSUMPTION",
|
|
18
|
-
"seat_tier": {
|
|
19
|
-
"chief-of-staff": "lead",
|
|
20
|
-
"cto": "staff",
|
|
21
|
-
"developer-experience-lead": "lead",
|
|
22
|
-
"platform-lead": "lead",
|
|
23
|
-
"product-growth-lead": "lead",
|
|
24
|
-
"release-reliability-lead": "lead",
|
|
25
|
-
"research-harness-scientist": "lead",
|
|
26
|
-
"research-outcomes-scientist": "lead",
|
|
27
|
-
"security-lead": "lead",
|
|
28
|
-
"verification-scientist": "lead"
|
|
29
|
-
},
|
|
30
|
-
"hours_per_outcome": {"verified_slice": {"value": null, "status": "ASSUMPTION, unset"}},
|
|
31
|
-
"plan_usd_per_month": 200,
|
|
32
|
-
"daily_budget_usd": 50
|
|
33
|
-
}
|