docs(requirements): add 001 Agent Orchestrator and 002 Cosmos
001 fixes the radio and post model, the orchestrator surface and rename, the pkgmgr branch tree with gc states and delete-by-click, the Agents and Artifacts views with 3D, Bootstrap Icons and kvb-org-update. 002 plans the cosmos extraction as an Infinito.Nexus custom role after 001. 🎯 Fix: 97 % 💥 Break: 1 % 💸 Cost: – ⏱️ Time: – 🛡️ Security: 100 % 🏆 Score: 96 🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 % Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5cb5da81ec
commit
50315a8bdb
3 files changed
+548
No files matched your search
@@ -0,0 +1,397 @@
|
||||
# 001 - Agent Orchestrator
|
||||
|
||||
## User Story
|
||||
|
||||
As the operator of many parallel agents, I want one simple Agent Orchestrator
|
||||
surface and a radio that only interrupts for urgent calls, so that agents
|
||||
spend few tokens on talk, urgent news reaches them at once, and I can drill
|
||||
from three views down to any agent, branch or artefact.
|
||||
|
||||
## Decisions (operator-confirmed 2026-11-06; do not re-litigate)
|
||||
|
||||
1. **One document**: radio model, surface, pkgmgr branch tree and views live in
|
||||
this one requirement as phases. Rejected: one document per feature (the
|
||||
operator wants the whole picture in one place).
|
||||
2. **Location**: `docs/requirements/NNN-slug.md`, numbered per repository.
|
||||
Rejected: a file next to the code (no index, no numbering).
|
||||
3. **Radio classes**: `post`, `call`, `newsletter`, `broadcast`, `mayday`,
|
||||
`pan-pan`, `security`. Rejected: `broadcast` only as the umbrella of the
|
||||
three alarms (the operator wants an immediate call to all without alarm).
|
||||
4. **Mailbox**: `post` (one agent) and `newsletter` (all agents) are
|
||||
delivered only when the agent ends its turn and goes idle, batched; an
|
||||
agent already idle is not woken and sees its mailbox at the end of its next
|
||||
turn. Rejected: next prompt, next tool step (interrupts work), batched
|
||||
wake-ups (one turn per wake).
|
||||
5. **Immediate classes**: `call`, `broadcast`, `pan-pan`, `mayday` and
|
||||
`security` reach the agent at its next tool step and wake an idle agent.
|
||||
6. **Call receipt**: the caller gets a delivered/read receipt and does not
|
||||
wait; an answer is a call of its own. Rejected: the caller blocks until
|
||||
the answer (costs the caller), delivery without feedback.
|
||||
7. **Mayday pause**: while a mayday holds, a PreToolUse hook blocks every
|
||||
writing action until `radio.py clear`; reading, the radio and teardown
|
||||
stay allowed. The sender and every agent that joins with `radio.py
|
||||
assist` to help keep working. Rejected: an instruction only (not
|
||||
enforced), heavy jobs only (today's behaviour, too weak), a full blockade
|
||||
that also stops the helpers.
|
||||
8. **Radio and post**: two channels. `radio.py send` is the radio and always
|
||||
immediate (`call`, `broadcast`, `pan-pan`, `mayday`, `security`);
|
||||
`radio.py post` is mail and always delayed (`post` with `--to`,
|
||||
`newsletter` without). `send direct` stays as an alias so running peers
|
||||
keep working: with `--wake` it becomes `call`, without it `post`. Rows
|
||||
stored before the change carry no version mark and are read as before:
|
||||
`direct` as `post`, `broadcast` as `newsletter`. Rejected: `send
|
||||
broadcast` as an alias of `newsletter` (makes the immediate broadcast
|
||||
unreachable).
|
||||
9. **Name**: kvb-hub is renamed in full, with a one-time migration: visible
|
||||
"Agent Orchestrator", technical `kvb-orchestrator` / `kvb_orchestrator`
|
||||
(directory, module, container, systemd unit, MCP server, environment
|
||||
`KVB_ORCHESTRATOR_*`, make targets). Rejected: visible name only (two names
|
||||
for one thing).
|
||||
10. **Navigation**: Stream (sub-items Inbox and Regeln) · Agents (ex Graph) ·
|
||||
Artifacts (ex Tree). Agents and Artifacts each offer Orbit, Chord,
|
||||
Swimlane, Tree and 3D.
|
||||
11. **Header**: title · ⌘K · ⚙ only. The status pills become navigation
|
||||
badges (Inbox: waiting items, Agents: active agents, Artifacts: runner
|
||||
jobs); Mayday shows only as a red banner with "aufheben" while active; the
|
||||
background shows day and night. Rejected: one status dot with a popover
|
||||
(an extra click), a status block in a side bar, a "Lage" screen (effort),
|
||||
no header at all.
|
||||
12. **Tools**: Steuerung (Funk an alle, Mayday aufheben, Priorität, Tag/Nacht)
|
||||
moves to the Agents toolbar, Regeln under Inbox, Himmel, Musik,
|
||||
Leitstand and Benachrichtigungen to ⚙ "Ambiente"; ⌘K reaches every one.
|
||||
Rejected: one ⋯ menu (hides instead of ordering).
|
||||
13. **Stream**: four category chips Für dich · Funk · Arbeit · Transkripte;
|
||||
one search line with `agent:`, `art:`, `seit:`; sub-filters, saved views
|
||||
and a custom range under "Filter ▾"; the time bar becomes "24 h ▾" with
|
||||
the replay inside; transcripts are off by default. Rejected: a
|
||||
self-grouping stream, a Kibana-like query language (effort), preset
|
||||
chips only.
|
||||
14. **3D**: `3d-force-graph` 1.80.1 on `three` 0.186.1, vendored as in
|
||||
meta.infinito.nexus; the Canvas depth axes Zeit and Spawn-Tiefe become 3D
|
||||
options. Rejected: keeping the Orbit-only Canvas depth.
|
||||
15. **Artifacts scope**: git (repositories → branches → worktrees with their
|
||||
agents and reviews) plus the kvb-org-rasci register artefacts (images,
|
||||
volumes, logs) as leaves of the task or worktree that owns them.
|
||||
Rejected: git only.
|
||||
16. **Artifacts views**: Orbit: repository sun, branch planets (size = commits
|
||||
ahead), worktree moons, agent satellites. Chord: branch overlap (same
|
||||
files touched, merges) as conflict risk. Swimlane: one lane per branch
|
||||
with commits, reviews, gates and pushes. Tree: the pkgmgr branch tree.
|
||||
17. **Tree data**: the scan moves from `hub/kvb_hub/tree.py` into pkgmgr as
|
||||
`pkgmgr branch tree --format json|yaml --output FILE`, rewritten by a
|
||||
systemd user timer every minute and after every pkgmgr branch action; the
|
||||
orchestrator only reads the file, no git runs in its container. Rejected:
|
||||
the hub keeps scanning (pkgmgr is not the single source, git runs in the
|
||||
container), a live websocket daemon (effort). Hardened through
|
||||
kvb-think-dialectic before it is built.
|
||||
18. **Order**: 1 radio → 2 surface and rename → 3 pkgmgr branch tree → 4 views
|
||||
and 3D; one bundle per phase, each change set through kvb-code-refactor.
|
||||
19. **Icons over text**: every HTML surface a skill renders (the
|
||||
orchestrator, the review pages, the meditation page) shows Bootstrap
|
||||
Icons instead of text labels wherever an icon carries the meaning, each
|
||||
with a tooltip and an `aria-label`; terminal output and `SKILL.md` keep
|
||||
emoji. Rejected: Font Awesome Free (icons under CC BY 4.0, core loads it
|
||||
from a kit CDN), emoji in HTML (look differs per platform).
|
||||
20. **Branch state**: `pkgmgr branch tree` covers every repository pkgmgr
|
||||
manages and gives each branch and worktree the classification of
|
||||
`pkgmgr branch gc` (one implementation, no second copy): merged and by
|
||||
what, clean or uncommitted changes, unpushed commits, gone upstream,
|
||||
locked, stale, protected and the gc skip reason. The Artifacts Tree shows
|
||||
it as icons. Phase 3 builds the data, phase 4 the icons.
|
||||
21. **Delete from the tree**: merged, orphaned branches are deleted by click
|
||||
in the Artifacts Tree (phase 4), per item and as "Alle gemergten
|
||||
löschen":
|
||||
- **Credentials**: only while KeePassXC is unlocked; it hands pkgmgr the
|
||||
GitHub token through the Secret Service and the SSH key through its SSH
|
||||
agent, and no secret passes the orchestrator container. Rejected: the
|
||||
master password typed into the dialog (secret crosses container and
|
||||
browser), a token-only, local-only delete.
|
||||
- **Scope**: exactly what `pkgmgr branch gc --apply` deletes for a
|
||||
`merged-clean` item (worktree, local and remote branch, compose stack,
|
||||
images); a gc skip reason locks the button. Rejected: local only.
|
||||
- **Confirmation**: the click shows the gc dry-run lines of the chosen
|
||||
items, and "Löschen" needs the operator signature (`/api/sign`).
|
||||
Rejected: a second click without signature, one click without preview.
|
||||
- **Execution**: the orchestrator writes a signed job into a host
|
||||
directory; a systemd user path unit runs `pkgmgr branch gc --apply` for
|
||||
exactly those items and writes the result back. Rejected: an
|
||||
`operator.py` row (not direct).
|
||||
22. **Organisation update**: a new skill `kvb-org-update` tells every agent
|
||||
and client which skills changed and how to use them, as one
|
||||
`newsletter` per update; phase 1 announces the radio change through it.
|
||||
|
||||
## Approach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph P["🧭 0 · Preparation"]
|
||||
P1["📋 Write requirement"] --> P2{"✅ Operator approves?"}
|
||||
P2 -- "✏️ corrections" --> P1
|
||||
end
|
||||
P2 -- "🤖 yes" --> R1
|
||||
subgraph R["📻 1 · Radio model"]
|
||||
R1["🔴 Red tests: classes, mailbox, receipt, mayday block"] --> R2["🛠️ radio.py, Stop mailbox hook, PreToolUse mayday hook, SKILL.md"]
|
||||
R2 --> R3{"🧪 Tests and make test green?"}
|
||||
R3 -- "🔴 no: fix" --> R2
|
||||
R3 -- "🟢 yes" --> R4["🧹 kvb-code-refactor"]
|
||||
R4 --> RF{"💬 Operator feedback?"}
|
||||
RF -- "✏️ changes" --> R2
|
||||
end
|
||||
RF -- "👍 commit word" --> S0
|
||||
subgraph S["🧭 2 · Surface and rename"]
|
||||
S0["🔀 Rebase feature/kvb-hub onto origin/master"] --> S1["🔴 Red tests: nav, header, badges, stream, migration"]
|
||||
S1 --> S2["🛠️ Nav, header, badges, banner, stream, inbox, tools, rename + migration"]
|
||||
S2 --> S3{"🧪 Tests green?"}
|
||||
S3 -- "🔴 no: fix" --> S2
|
||||
S3 -- "🟢 yes" --> S4["📸 Screenshots 1920 / 1366 / 390 px"]
|
||||
S4 --> SF{"💬 Operator feedback?"}
|
||||
SF -- "✏️ changes" --> S2
|
||||
end
|
||||
SF -- "👍 commit word" --> T0
|
||||
subgraph T["🌳 3 · pkgmgr branch tree"]
|
||||
T0["⚖️ kvb-think-dialectic on the data path"] --> T1["🔴 Red tests on fixture repositories"]
|
||||
T1 --> T2["🛠️ pkgmgr branch tree with gc states, timer, orchestrator reads the file"]
|
||||
T2 --> T3{"🧪 Tests green, no git in the container?"}
|
||||
T3 -- "🔴 no: fix" --> T2
|
||||
T3 -- "🟢 yes" --> TF{"💬 Operator feedback?"}
|
||||
TF -- "✏️ changes" --> T2
|
||||
end
|
||||
TF -- "👍 commit word" --> V1
|
||||
subgraph V["🪐 4 · Agents and Artifacts views"]
|
||||
V1["🔴 Red tests: five views per tab, artefact leaves, delete job"] --> V2["🛠️ Orbit, Chord, Swimlane, Tree with state icons and delete, 3D (3d-force-graph), host gc unit"]
|
||||
V2 --> V3{"🧪 Tests green?"}
|
||||
V3 -- "🔴 no: fix" --> V2
|
||||
V3 -- "🟢 yes" --> V4["📸 Screenshots of every view"]
|
||||
V4 --> VF{"💬 Operator feedback?"}
|
||||
VF -- "✏️ changes" --> V2
|
||||
end
|
||||
VF -- "👍 fits" --> D1["🏁 Full gate, commit with operator OK, push hand-over"]
|
||||
```
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Radio model
|
||||
|
||||
- [ ] `radio.py send` accepts exactly `call`, `broadcast`, `pan-pan`,
|
||||
`mayday`, `security` and the alias `direct`; `post`, `newsletter` and
|
||||
any other class exit 2.
|
||||
- [ ] `radio.py post --to X` stores `post`; `radio.py post` without `--to`
|
||||
stores `newsletter`.
|
||||
- [ ] `call` and `send direct` require `--to`; `broadcast`, `pan-pan`,
|
||||
`mayday` and `security` exit 2 with `--to`.
|
||||
- [ ] `send direct --wake` is stored as `call`, `send direct` as `post`.
|
||||
- [ ] New rows carry a version mark; rows without it are read as before:
|
||||
`direct` as `post` (as `call` when it woke), `broadcast` as
|
||||
`newsletter`.
|
||||
- [ ] The UserPromptSubmit hook (`radio.py hook`) and the PostToolBatch hook
|
||||
(`radio.py tool`) never print a `post` or `newsletter` row.
|
||||
- [ ] A new Stop hook `radio.py mailbox`, registered in
|
||||
`scripts/enable-plugins.js`, prints the unseen `post` and `newsletter`
|
||||
rows of the session at most 10 at a time with a "N more" line, marks
|
||||
them seen and exits 2; with nothing unseen it exits 0 and prints
|
||||
nothing.
|
||||
- [ ] `radio.py listen` wakes an idle session only for `call`, `broadcast`,
|
||||
`pan-pan`, `mayday` and `security`, never for `post` or `newsletter`.
|
||||
- [ ] `radio.py tool` delivers `call` (to its addressee), `broadcast`,
|
||||
`pan-pan`, `mayday` and `security` at the next tool step.
|
||||
- [ ] When a call reaches the callee's context, a receipt row (callee, call
|
||||
time, read time) is stored; the caller's mailbox shows
|
||||
"CALL <to> read <time>". The receipt never wakes the caller.
|
||||
- [ ] While `radio-silence.json` holds an active mayday, a PreToolUse hook
|
||||
(matcher `Edit|Write|MultiEdit|NotebookEdit|Bash`) exits 2 for Edit,
|
||||
Write, MultiEdit and NotebookEdit and for every Bash command that
|
||||
matches neither the config's `never_block` nor its new `mayday_allow`
|
||||
regexes nor a plain call of `radio.py`.
|
||||
- [ ] The mayday's sender passes; `radio.py assist` adds the caller to the
|
||||
mayday's helpers, who pass too, and the mayday line names them.
|
||||
- [ ] After `radio.py clear` the same calls pass again.
|
||||
- [ ] `skills/kvb-org-radio/SKILL.md` separates the radio (`send`,
|
||||
immediate) and the post (`post`, delayed), each class with when to use
|
||||
it and how it is delivered; post is the default; markdownlint stays
|
||||
green.
|
||||
|
||||
### Organisation update
|
||||
|
||||
- [ ] A skill `kvb-org-update` with `scripts/update.py` exists.
|
||||
- [ ] `update.py --repo <skills repo> --dry-run` prints every skill whose
|
||||
files changed between the last announced revision (kept in the council
|
||||
directory) and `HEAD`, with the subjects of the commits that touched it.
|
||||
- [ ] Without `--dry-run` it sends one `newsletter` through `radio.py post`
|
||||
that names each changed skill and tells every agent to re-read its
|
||||
`SKILL.md` before the next use, then records `HEAD` as announced; a
|
||||
second run without new commits sends nothing.
|
||||
- [ ] The radio change of phase 1 is announced through it.
|
||||
|
||||
### Orchestrator surface and rename
|
||||
|
||||
- [ ] The page title and heading read "Agent Orchestrator".
|
||||
- [ ] `grep -rnE 'kvb-hub|kvb_hub|KVB_HUB'` over the repository finds only the
|
||||
migration code and its tests.
|
||||
- [ ] The install migrates `~/.local/share/kvb-hub`, `~/.config/kvb-hub`,
|
||||
`~/.local/state/kvb-hub-approvals`, the `kvb-hub` MCP registration, the
|
||||
settings hook entries, the systemd unit and the container to the
|
||||
`kvb-orchestrator` names. A second run changes nothing (scratch-HOME
|
||||
test).
|
||||
- [ ] The navigation has exactly three top-level entries Stream, Agents and
|
||||
Artifacts; Stream has the sub-items Inbox and Regeln.
|
||||
- [ ] Every agent appears once under its current name: a register worker
|
||||
such as "Stage (this session)" or "infinito-nexus-core-c8 (Production)"
|
||||
maps to the agent named before the bracket.
|
||||
- [ ] The keys 1 to 3 switch the top-level entries.
|
||||
- [ ] The hashes `#stream`, `#stream/inbox`, `#stream/rules`,
|
||||
`#agents/<view>` and `#artifacts/<view>` route; `#graph…` and `#tree`
|
||||
redirect to their successors.
|
||||
- [ ] Agents and Artifacts show a switch with Orbit, Chord, Swimlane, Tree and
|
||||
3D in this order, and each view has its own hash.
|
||||
- [ ] The header holds exactly the title, the ⌘K button and the ⚙ button.
|
||||
- [ ] Badges:
|
||||
- [ ] Inbox shows the waiting items that are not snoozed.
|
||||
- [ ] Agents shows the agents with a heartbeat in the last 900 s.
|
||||
- [ ] Artifacts shows the runner jobs that are queued or running.
|
||||
- [ ] A badge at 0 is hidden.
|
||||
- [ ] A red Mayday banner with "aufheben" exists if and only if a mayday is
|
||||
active; "aufheben" runs `radio.py clear`.
|
||||
- [ ] The Agents toolbar holds:
|
||||
- [ ] Funk an alle, with the class choice Newsletter, Broadcast, Pan-Pan,
|
||||
Security, Mayday and Newsletter preselected.
|
||||
- [ ] Mayday aufheben, Priorität and Tag/Nacht.
|
||||
- [ ] The agent panel sends with the choice Post (preselected) or Call.
|
||||
- [ ] ⚙ "Ambiente" holds Himmel, Musik, Leitstand and Benachrichtigungen;
|
||||
⌘K lists every former header tool.
|
||||
- [ ] The Stream shows exactly four category chips Für dich, Funk, Arbeit and
|
||||
Transkripte, and one search line that filters by `agent:`, `art:` and
|
||||
`seit:`.
|
||||
- [ ] "Filter ▾" holds the kind sub-filters, the transcript parts, the saved
|
||||
views and the custom range.
|
||||
- [ ] The time control reads "24 h ▾" and holds the replay.
|
||||
- [ ] Transcripts are off by default.
|
||||
- [ ] The Inbox renders in the main area under `#stream/inbox`; the right
|
||||
rail `#rail` no longer exists, at any width.
|
||||
- [ ] The read-aloud class choice lists exactly the seven classes of
|
||||
decision 3; Mayday stays checked and locked.
|
||||
|
||||
### pkgmgr branch tree
|
||||
|
||||
- [ ] The kvb-think-dialectic result on the data path is recorded in the
|
||||
phase 3 commit body before any code of phase 3 is written.
|
||||
- [ ] `pkgmgr branch tree --format json` prints, for every repository pkgmgr
|
||||
knows and every worktree under `<repo>/.worktrees` and
|
||||
`~/.local/share/worktrees`, these fields:
|
||||
- [ ] the repository's path, remote and default branch;
|
||||
- [ ] per branch: upstream, ahead, behind and gone;
|
||||
- [ ] per worktree: path, HEAD and its state, one of `clean`, `changed` or
|
||||
`missing`;
|
||||
- [ ] detached worktrees, and `generated_at`.
|
||||
- [ ] It lists every repository `pkgmgr list` names, also one without extra
|
||||
branches or worktrees.
|
||||
- [ ] Per branch and worktree it carries the gc state (`merged-clean`,
|
||||
`unmerged`, `dirty`, `protected`, `stale`), what merged it (ancestor,
|
||||
`pr#N`, `line:X`), the counts of staged, unstaged and untracked files,
|
||||
ahead, behind, gone, locked and the gc skip reason.
|
||||
- [ ] Tree and gc share one classification function; on a fixture
|
||||
`pkgmgr branch tree --format json` and `pkgmgr branch gc --json` agree
|
||||
on every item's state.
|
||||
- [ ] Forge facts (open and merged pull requests) are fetched at most once
|
||||
per 10 min per repository, only with a token from the Secret Service;
|
||||
without one the file says `forge: unavailable` and "merged by" falls
|
||||
back to ancestor and line.
|
||||
- [ ] `delete_ready` is true only while the token resolves through the
|
||||
Secret Service and the KeePassXC SSH agent holds a key; otherwise it is
|
||||
false with the reason.
|
||||
- [ ] `--format yaml` prints the same data.
|
||||
- [ ] `--output FILE` writes it atomically.
|
||||
- [ ] The scan starts no hook, filter, fsmonitor, pager or external diff of a
|
||||
scanned repository and never lazy-fetches (fixture test with a planted
|
||||
`core.fsmonitor`).
|
||||
- [ ] `pkgmgr branch open|close|drop|gc` rewrite the file when it exists.
|
||||
- [ ] The orchestrator install enables a systemd user timer that writes it
|
||||
every 60 s.
|
||||
- [ ] The orchestrator mounts the file read-only and reads only it.
|
||||
- [ ] `hub/kvb_hub/tree.py`'s git scan is gone and no module of the
|
||||
orchestrator starts `git`.
|
||||
|
||||
### Agents and Artifacts views
|
||||
|
||||
- [ ] Artifacts:
|
||||
- [ ] Orbit, Chord, Swimlane and Tree draw what decision 16 names, from the
|
||||
pkgmgr tree file.
|
||||
- [ ] Register artefacts (images, volumes, logs) appear as leaves of their
|
||||
task or worktree.
|
||||
- [ ] Agents:
|
||||
- [ ] Orbit, Chord and Swimlane keep today's content.
|
||||
- [ ] Tree shows the operator → chair → sessions → subagents spawn tree
|
||||
with running and finished states.
|
||||
- [ ] 3D in both tabs runs on the vendored `3d-force-graph` 1.80.1 and
|
||||
`three` 0.186.1, with their MIT licence texts beside them and no CDN
|
||||
request (CSP unchanged).
|
||||
- [ ] 3D offers the layouts Kraft, Zeit and Spawn-Tiefe.
|
||||
- [ ] A click on a 3D node opens the same panel as in 2D.
|
||||
- [ ] 3D respects `prefers-reduced-motion`.
|
||||
|
||||
### Delete merged branches
|
||||
|
||||
- [ ] The Artifacts Tree marks every branch and worktree with icons for
|
||||
merged (with what merged it), clean, uncommitted changes (with counts),
|
||||
unpushed commits, gone upstream, locked, stale and protected.
|
||||
- [ ] A `merged-clean` item without a gc skip reason shows a delete button,
|
||||
and the Tree header shows "Alle gemergten löschen"; both are disabled,
|
||||
with the reason as tooltip, while `delete_ready` is false.
|
||||
- [ ] A click shows the gc dry-run lines of exactly the chosen items;
|
||||
"Löschen" requires the operator signature through `/api/sign`.
|
||||
- [ ] The orchestrator writes the signed job (repository, branch, worktree
|
||||
and tip sha per item, no command) into a host-mounted job directory and
|
||||
holds no git, token or key.
|
||||
- [ ] A systemd user path unit verifies the signature on the host and runs
|
||||
`pkgmgr branch gc --apply` for exactly the signed items, matched
|
||||
exactly, never as a pattern.
|
||||
- [ ] The unit refuses, and changes nothing for, an item whose tip or state
|
||||
differs from the signed one, an unknown repository, a non-`merged-clean`
|
||||
item and a job with a bad or missing signature, and reports why.
|
||||
- [ ] The unit writes each item's result back and rewrites the tree file; the
|
||||
Tree shows the result.
|
||||
|
||||
### Icons
|
||||
|
||||
- [ ] Bootstrap Icons 1.13.1 is vendored once as an SVG sprite with its MIT
|
||||
licence text beside it; no page loads it from a CDN.
|
||||
- [ ] The navigation, the header, the view switches, the toolbars, the
|
||||
Stream chips and the Inbox actions of the orchestrator show icons
|
||||
instead of text labels.
|
||||
- [ ] The review pages and the meditation page show icons instead of text
|
||||
labels on their buttons.
|
||||
- [ ] Every icon element has a `title` and an `aria-label` that carry the
|
||||
former text (DOM test over every page).
|
||||
|
||||
### Tests
|
||||
|
||||
- **Unit**
|
||||
- [ ] Radio: class mapping, `--to` rules, the mailbox Stop hook, the
|
||||
receipt and the mayday block hook, each red before and green after.
|
||||
- [ ] Organisation update on a fixture repository: changed skills with
|
||||
their subjects, nothing new sends nothing.
|
||||
- [ ] pkgmgr branch tree on fixture repositories: ahead, behind, gone,
|
||||
detached and missing worktree, JSON and YAML, the planted fsmonitor,
|
||||
staged, unstaged and untracked counts, tree and gc states agreeing.
|
||||
- [ ] Delete job: a bad signature, a changed tip, a non-`merged-clean`
|
||||
item and a branch name with pattern characters are each refused.
|
||||
- [ ] Orchestrator: the scratch-HOME migration, routing including old
|
||||
hashes, badge counts.
|
||||
- **Integration**
|
||||
- [ ] Two scratch sessions exchange `post` and `call` through the real hook
|
||||
entry points (JSON on stdin): the post appears only on the callee's
|
||||
Stop and the call at its next tool step with a receipt to the caller.
|
||||
- [ ] A mayday blocks an Edit until `clear`.
|
||||
- [ ] The orchestrator's `/api/tree` serves a pkgmgr-written file.
|
||||
- [ ] On a fixture repository with a file remote and a test token source, a
|
||||
signed job through the path unit removes the merged worktree, the
|
||||
local and the remote branch, and the rewritten tree no longer lists
|
||||
them.
|
||||
- [ ] `make test` green on the commit of each phase.
|
||||
- **E2E**
|
||||
- [ ] A headless Chromium and Firefox run opens Stream, Inbox, Regeln and
|
||||
every view of Agents and Artifacts at 1920, 1366 and 390 px wide and
|
||||
saves the screenshots shown at each operator checkpoint.
|
||||
- [ ] It sends a Call from the agent panel and sees its receipt in the
|
||||
Stream.
|
||||
- [ ] On fixture data it shows the state icons in the Artifacts Tree and
|
||||
runs the delete flow: dry-run dialog, signature, result.
|
||||
@@ -0,0 +1,143 @@
|
||||
# 002 - Cosmos
|
||||
|
||||
## User Story
|
||||
|
||||
As the operator and the designer, I want the orchestrator's sky, music and
|
||||
orbit scene as one reusable component behind a small live globe, so that the
|
||||
orchestrator and every Infinito.Nexus web app can show the same calm
|
||||
background without carrying its code twice.
|
||||
|
||||
## Decisions (operator-confirmed 2026-11-06; do not re-litigate)
|
||||
|
||||
1. **Scope**: everything of the orchestrator's background moves: the sky (sun,
|
||||
moon, stars, twilight stages, day and night palettes with contrast check),
|
||||
the generated meditative music and the orbit and 3D scene. The radio
|
||||
streams with their schedule stay in the orchestrator. Rejected: the sky
|
||||
only.
|
||||
2. **Repository**: `github.com/kevinveenbirkenbach/cosmos`, not managed by
|
||||
pkgmgr, laid out as an Infinito.Nexus custom role `web-app-cst-cosmos` that
|
||||
core pulls from its inventory-declared source. Rejected: the infinito-nexus
|
||||
organisation, a pkgmgr-managed release.
|
||||
3. **Form**: Web Components (`<cosmos-ambience>` for sky and music,
|
||||
`<cosmos-graph>` for the 3D scene) that also set `--cosmos-*` CSS custom
|
||||
properties every design can follow; a "colors only" mode draws nothing.
|
||||
Rejected: a plain ES module.
|
||||
4. **Globe menu**: a small globe logo turns with the Earth's real rotation and
|
||||
shows the current Earth with its live day and night line; a click on it
|
||||
reveals every control, nothing else is visible while it is closed.
|
||||
Rejected: a visibly spinning globe (not the real orientation).
|
||||
5. **Licence**: MIT, like the skills repository it comes from. Rejected: the
|
||||
Infinito.Nexus Community License (non-commercial, limits reuse).
|
||||
6. **Work split**: Skills extracts the code into cosmos and switches the
|
||||
orchestrator to a pinned cosmos version; the IAM agent builds the core
|
||||
integration: a role that the design service `web-svc-design` activates.
|
||||
Rejected: IAM doing everything.
|
||||
7. **Timing**: implemented after requirement 001; the core part also needs
|
||||
core's custom roles (requirement 046) on core main. Rejected: starting now.
|
||||
8. **Icons**: the controls use Bootstrap Icons per decision 19 of
|
||||
requirement 001.
|
||||
|
||||
## Approach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph P["🧭 0 · Preparation"]
|
||||
P1["📋 Write requirement"] --> P2{"✅ Operator approves?"}
|
||||
P2 -- "✏️ corrections" --> P1
|
||||
P2 -- "🤖 yes" --> P3{"🏁 001 done and 046 on core main?"}
|
||||
P3 -- "⏳ not yet" --> P3
|
||||
end
|
||||
P3 -- "🟢 yes" --> C1
|
||||
subgraph C["🌌 1 · Extract into cosmos (Skills)"]
|
||||
C1["🔴 Red tests: astronomy, palette contrast, globe, attributes"] --> C2["🛠️ cosmos repo as custom role, Web Components, globe menu, demo page"]
|
||||
C2 --> C3{"🧪 Tests and core role lints green?"}
|
||||
C3 -- "🔴 no: fix" --> C2
|
||||
C3 -- "🟢 yes" --> C4["📸 Screenshots: noon, dusk, night, menu open"]
|
||||
C4 --> CF{"💬 Operator feedback?"}
|
||||
CF -- "✏️ changes" --> C2
|
||||
end
|
||||
CF -- "👍 commit word" --> O1
|
||||
subgraph O["🧭 2 · Orchestrator on cosmos (Skills)"]
|
||||
O1["🔁 Pin cosmos, drop ambience.js, sky and generated music"] --> O2{"🧪 Orchestrator tests green?"}
|
||||
O2 -- "🔴 no: fix" --> O1
|
||||
O2 -- "🟢 yes" --> OF{"💬 Operator feedback?"}
|
||||
OF -- "✏️ changes" --> O1
|
||||
end
|
||||
OF -- "👍 commit word" --> I1
|
||||
subgraph I["🏛️ 3 · Core integration (IAM)"]
|
||||
I1["📋 IAM writes the core requirement"] --> I2["🛠️ Role activated by web-svc-design"]
|
||||
I2 --> I3{"🧪 Deploy and Playwright green?"}
|
||||
I3 -- "🔴 no: fix" --> I2
|
||||
I3 -- "🟢 yes" --> IF{"💬 Operator feedback?"}
|
||||
IF -- "✏️ changes" --> I2
|
||||
end
|
||||
IF -- "👍 fits" --> D1["🏁 Commit with operator OK, push hand-over"]
|
||||
```
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Repository
|
||||
|
||||
- [ ] `github.com/kevinveenbirkenbach/cosmos` holds an MIT `LICENSE`.
|
||||
- [ ] `pkgmgr list` does not list cosmos.
|
||||
- [ ] The repository is a role named `web-app-cst-cosmos`: `README.md`,
|
||||
`meta/` (main, info, services, license), `tasks/main.yml`, and the
|
||||
components under `files/`.
|
||||
- [ ] An inventory group `web-app-cst-cosmos` with `custom: true` and a
|
||||
pinned source makes core's `make roles-pull` place it.
|
||||
- [ ] Every core role lint passes on the placed role.
|
||||
|
||||
### Components
|
||||
|
||||
- [ ] `<cosmos-ambience>` takes `latitude`, `longitude`, `mode`
|
||||
(`full` or `colors`) and `music` with a volume, and follows
|
||||
`prefers-reduced-motion`.
|
||||
- [ ] It sets `--cosmos-sky-top`, `--cosmos-sky-bottom`, `--cosmos-stage` and
|
||||
`--cosmos-text` and updates them at least once a minute.
|
||||
- [ ] Text against sky keeps a contrast of at least 4.5:1 at every minute of a
|
||||
day at 0° N 0° W and at 52.5° N 13.4° E (unit test).
|
||||
- [ ] Sun and moon positions match published reference values within 1° for
|
||||
at least six fixed dates (unit test).
|
||||
- [ ] `<cosmos-graph>` renders the 3D scene on vendored `3d-force-graph`
|
||||
1.80.1 and `three` 0.186.1 and takes nodes and links as data.
|
||||
- [ ] The generated meditative music plays with a volume; no radio stream
|
||||
code is in the repository.
|
||||
|
||||
### Globe menu
|
||||
|
||||
- [ ] A globe of at most 48 px shows a public-domain Earth texture with the
|
||||
live day and night line, turned to the Earth's current rotation.
|
||||
- [ ] A click, Enter or Space opens the control panel and Esc closes it.
|
||||
- [ ] While the panel is closed only the globe is visible.
|
||||
- [ ] Every control is a Bootstrap Icon with `title` and `aria-label`.
|
||||
|
||||
### Orchestrator
|
||||
|
||||
- [ ] The orchestrator vendors a pinned cosmos tag and loads it under its
|
||||
nonce CSP.
|
||||
- [ ] `ambience.js`, the sky code and the generated music are gone from the
|
||||
orchestrator; its radio-stream schedule stays.
|
||||
- [ ] The orchestrator's 3D views render through `<cosmos-graph>`.
|
||||
|
||||
### Core (IAM)
|
||||
|
||||
- [ ] IAM writes the core requirement for the integration.
|
||||
- [ ] With `web-svc-design` activating cosmos, a designed web app shows the
|
||||
cosmos background behind its content with the globe.
|
||||
- [ ] With it off, the app loads no cosmos file.
|
||||
|
||||
### Tests
|
||||
|
||||
- **Unit**
|
||||
- [ ] Astronomy against reference values.
|
||||
- [ ] Palette contrast over a day.
|
||||
- [ ] Attribute parsing.
|
||||
- [ ] Globe orientation at fixed times.
|
||||
- **Integration**
|
||||
- [ ] Core's `make roles-pull` places cosmos and its role lints pass.
|
||||
- [ ] The orchestrator serves the pinned cosmos under its CSP.
|
||||
- **E2E**
|
||||
- [ ] Headless Chromium and Firefox open the cosmos demo page and the
|
||||
orchestrator at noon, dusk and night with the menu closed and open,
|
||||
and save the screenshots.
|
||||
- [ ] One designed core app is opened with cosmos on and off.
|
||||
@@ -0,0 +1,8 @@
|
||||
# Requirements 📋
|
||||
|
||||
User stories, operator decisions and acceptance criteria that guide
|
||||
agent-assisted implementation in this repository. The `kvb-create-requirement`
|
||||
skill defines the format.
|
||||
|
||||
- [001 - Agent Orchestrator](001-agent-orchestrator.md)
|
||||
- [002 - Cosmos](002-cosmos.md)
|
||||
Reference in new issue
Block a user