Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
176 commits
Select commit Hold shift + click to select a range
9fdfcc9
fix: tighten Eidoverse header for mobile, hide empty federation bar
atomantic Sep 8, 2026
89c1479
hide CoS Learning stat tile on mobile
atomantic Sep 8, 2026
4bbae9a
Merge pull request #6597 from atomantic/cos/task-mts8jw69/agent-713dd6e1
atomantic Sep 8, 2026
933bb80
fix: disable selecting a disabled provider in AI model pickers
atomantic Sep 8, 2026
15bc323
fix: clarify video production setup recheck action
atomantic Sep 8, 2026
69f5a1b
Merge pull request #6600 from atomantic/cos/task-mts9356m/agent-ee861283
atomantic Sep 8, 2026
1ae53f7
Merge pull request #6599 from atomantic/cos/task-mts8xuts/agent-c287213f
atomantic Sep 8, 2026
e5fd870
fix: stop the sidebar's glass-theme background from bleeding into the…
atomantic Sep 8, 2026
4226830
Merge pull request #6601 from atomantic/cos/task-mts8i957/agent-898645bb
atomantic Sep 8, 2026
cbf7d24
feat: select configured providers and models for code review
atomantic Sep 8, 2026
8069cfb
Merge pull request #6602 from atomantic/cos/task-mtsb0a65/agent-f8d4bd25
atomantic Sep 8, 2026
5a67dd3
Merge pull request #6598 from atomantic/cos/task-mts8lrbr/agent-cdb69e2b
atomantic Sep 8, 2026
269d972
fix: separate agent workspace lookup from JIRA prompt support
atomantic Sep 8, 2026
0e46d2a
fix: remove trailing blank line from workspace module
atomantic Sep 8, 2026
91db895
Merge pull request #6603 from atomantic/cos/sys-portos-d-module-hygie…
atomantic Sep 8, 2026
c9de351
move the CoS task intake mapping out of addTask and pin it to the req…
atomantic Sep 8, 2026
505099c
narrow the task intake's imports and drop tests the store boundary al…
atomantic Sep 8, 2026
13fbc0b
Merge pull request #6604 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 8, 2026
6c726d8
pin the songbook chord shapes above the sheet and collapse the audio …
atomantic Sep 8, 2026
03e3740
fold the songbook header cards onto the shared disclosure and storage…
atomantic Sep 8, 2026
69779b7
emit aria-controls only while a CollapsibleSection body is in the DOM
atomantic Sep 8, 2026
68cac2f
re-export the provider predicates from server/lib instead of copying …
atomantic Sep 8, 2026
59f75ae
Merge pull request #6606 from atomantic/cos/task-mtssabuh/agent-3a21fc4e
atomantic Sep 8, 2026
2a634b4
Merge pull request #6607 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 8, 2026
69669f4
feat(cos): schedule every do:better audit lens as its own self-improv…
atomantic Sep 8, 2026
6d89f90
refactor: derive the workflow audit stage and the lane tests from the…
atomantic Sep 8, 2026
fd866ab
Merge pull request #6609 from atomantic/cos/task-mtsuf8fj/agent-d2f10b67
atomantic Sep 8, 2026
bc39797
fix: contain scheduled handler loading and execution failures
atomantic Sep 8, 2026
889b5bc
Merge pull request #6610 from atomantic/cos/sys-portos-d-code-quality…
atomantic Sep 8, 2026
d5fe812
fix: keep scheduled tasks from drawing unrelated skill guidance (#6608)
atomantic Sep 8, 2026
7af8a24
fix: align provider controls with the Claude launch harness (#6605)
atomantic Sep 8, 2026
71311b6
Merge pull request #6611 from atomantic/claim/issue-6608
atomantic Sep 8, 2026
2597887
fix: stop badging claim and read-only agent runs as coding on main
atomantic Sep 8, 2026
83d0793
Merge pull request #6612 from atomantic/claim/issue-6605
atomantic Sep 8, 2026
efaa96e
Merge pull request #6614 from atomantic/cos/task-mtsxyte6/agent-b45f6962
atomantic Sep 8, 2026
2e6db5d
refactor: declare CLAIM_FLOW_TASK_TYPES once so the claim writer and …
atomantic Sep 8, 2026
b8c3439
Merge pull request #6615 from atomantic/claim/issue-6613
atomantic Sep 8, 2026
6260e8b
fix: stop the api prompt telling tool-free and read-only tasks to com…
atomantic Sep 8, 2026
4d96b6d
test: pin every runAgentSpawn block-and-bail gate at the spawn bounda…
atomantic Sep 8, 2026
f066157
test: pin the four uncovered writeTaskUpdate status-transition edges …
atomantic Sep 8, 2026
83f6c89
test: pin the CLI/TUI agent finalize sequence with paired boundary te…
atomantic Sep 8, 2026
aeee56a
refactor: derive writeTaskUpdate's status transition once instead of …
atomantic Sep 8, 2026
9e1f458
refactor: trim the stale terminal-predicate note and name the clear-t…
atomantic Sep 8, 2026
e241cb6
refactor: resolve the agent completion mode once instead of in five f…
atomantic Sep 8, 2026
d71ef4a
refactor: give the CLI and TUI spawners one shared agent finalize seq…
atomantic Sep 8, 2026
2fc41a0
Merge pull request #6621 from atomantic/claim/issue-6620
atomantic Sep 8, 2026
770d7af
refactor: collapse runAgentSpawn's eight block-and-bail epilogues int…
atomantic Sep 8, 2026
fe4b26d
feat: bucket related instance features under a group toggle
tzioup Sep 8, 2026
39d3023
refactor: expose the shared seams the beeper feature hooks into
tzioup Sep 8, 2026
ad7d78f
Merge pull request #6622 from atomantic/claim/issue-6619
atomantic Sep 8, 2026
908acfb
Merge pull request #6623 from atomantic/claim/issue-6616
atomantic Sep 8, 2026
26fafb9
Merge pull request #6625 from atomantic/claim/issue-6617
atomantic Sep 8, 2026
e5d59b6
fix: parse sources instead of regex-tokenizing them in the prompt-sta…
atomantic Sep 8, 2026
54dc865
feat: organize scheduled audits with labels and run guidance
atomantic Sep 8, 2026
0b75f4a
Merge pull request #6626 from atomantic/claim/issue-6624
atomantic Sep 8, 2026
056f188
fix: share one on-demand drain loop so #3294's registry guard covers …
atomantic Sep 8, 2026
c0b3e66
Merge pull request #6628 from atomantic/cos/task-mtt24i7l/agent-d55df52d
atomantic Sep 8, 2026
fb10e33
fix task-schedule card top alignment and tighten the page header
atomantic Sep 8, 2026
8d1b46c
fix task-schedule card top alignment and tighten the page header
atomantic Sep 8, 2026
fd9fbc2
Merge pull request #6630 from atomantic/cos/task-mtt2wz0l/agent-a1bdee35
atomantic Sep 8, 2026
0d5377e
render the Morse reference tree full-width and scale it to fit
atomantic Sep 8, 2026
f3113a0
Merge pull request #6631 from atomantic/cos/task-mtt33z8u/agent-d97f5cdd
atomantic Sep 8, 2026
88d7d52
name scheduled-task run order by task type instead of describing it i…
atomantic Sep 8, 2026
a44cfa8
Merge pull request #6633 from atomantic/cos/task-mtt3e3c6/agent-7df3e85d
atomantic Sep 8, 2026
78bf584
fix: keep the call opening line pending until TTS actually delivers i…
atomantic Sep 8, 2026
3380096
claim the app-operation lock synchronously so two self-updates cannot…
atomantic Sep 8, 2026
112bd18
fix: cap guest mic frames and re-read the live session in the hosted …
atomantic Sep 8, 2026
a09583e
Merge pull request #6640 from atomantic/claim/issue-6639
atomantic Sep 8, 2026
4ac0a30
Merge pull request #6641 from atomantic/claim/issue-6638
atomantic Sep 8, 2026
44a62e1
fix: give pm2 log stdout and stderr their own line buffers (#6637)
atomantic Sep 8, 2026
48657c9
fix: resolve backup schedule defaults once so the Settings tab can't …
atomantic Sep 8, 2026
5d88a89
Merge pull request #6643 from atomantic/claim/issue-6636
atomantic Sep 8, 2026
d0a0d8e
fix: judge issue claims against substantive issue requirements
atomantic Sep 8, 2026
58c6fbb
fix: decode misaligned PCM frames in voice:call:audio instead of drop…
atomantic Sep 8, 2026
e2bcc53
fix: reject out-of-range cron expressions at every schedule save boun…
atomantic Sep 8, 2026
44fe02b
raise the prompt stage call-site drift test timeout above its own sca…
atomantic Sep 8, 2026
ed5e3d1
Merge pull request #6642 from atomantic/claim/issue-6632
atomantic Sep 8, 2026
41ca5e2
Merge pull request #6646 from atomantic/claim/issue-6635
atomantic Sep 8, 2026
b3a7fd8
Merge pull request #6645 from atomantic/cos/task-mtt5ru5h/agent-6a1cb2fe
atomantic Sep 8, 2026
46b9a36
Merge pull request #6647 from atomantic/claim/issue-6634
atomantic Sep 8, 2026
c52b71e
Merge pull request #6644 from atomantic/claim/issue-6637
atomantic Sep 8, 2026
a6b484d
fix: preserve exact Git paths in CI test selection
atomantic Sep 8, 2026
c7afe09
feat: add a beeper desktop bridge as a third comms chat source
tzioup Sep 8, 2026
0eff204
Merge pull request #6648 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 8, 2026
9701d2e
feat: compact completed agents in a responsive grid
atomantic Sep 8, 2026
435ba42
Merge pull request #6650 from atomantic/cos/task-mtt7cqn2/agent-53369f5b
atomantic Sep 8, 2026
5c50b6b
feat: add ordered maintenance sequence to quota burn
atomantic Sep 8, 2026
9c0d138
Merge pull request #6651 from atomantic/cos/task-mtt71x70/agent-831848dd
atomantic Sep 8, 2026
a760a95
fix: require shared issue labels across autonomous filing
atomantic Sep 8, 2026
99b2231
Merge pull request #6653 from atomantic/cos/task-mtt99pod/agent-b8e32a9b
atomantic Sep 8, 2026
1eb38a6
fix: describe backup exclusion rule state without promising file incl…
atomantic Sep 8, 2026
a4a3821
fix: use neutral styling for disabled backup rules (#6652)
atomantic Sep 8, 2026
4f6d9b6
Merge pull request #6654 from atomantic/claim/issue-6652
atomantic Sep 8, 2026
28f06d4
feat: launch maintenance sequence from scheduled tasks
atomantic Sep 8, 2026
ebd97aa
fix: use HTTP-compatible maintenance sequence identifiers
atomantic Sep 8, 2026
4ea0967
fix: preserve maintenance plans and browser-safe provider lookup
atomantic Sep 8, 2026
9ddff54
fix: require substantive review in issue-only audits
atomantic Sep 8, 2026
757699c
fix: guard audits against issue count quotas
atomantic Sep 8, 2026
f5ef731
Merge pull request #6657 from atomantic/cos/task-mttabeyt/agent-4672e5a2
atomantic Sep 8, 2026
2c5a7e2
Merge pull request #6658 from atomantic/cos/task-mttar7xl/agent-03afb112
atomantic Sep 8, 2026
e1dda61
fix: make disabled maintenance runs actionable
atomantic Sep 8, 2026
675358f
fix: preserve maintenance setup after refresh failures
atomantic Sep 8, 2026
5185659
fix: keep notification unread badges aligned with server totals (#6656)
atomantic Sep 8, 2026
431bc7f
fix: offer every notification type in Telegram forwarding settings (#…
atomantic Sep 8, 2026
571d9fc
docs: keep notification catalog entry in the module table
atomantic Sep 8, 2026
2913925
Merge pull request #6659 from atomantic/cos/task-mttbb8ou/agent-0730e150
atomantic Sep 8, 2026
1fc3747
Merge pull request #6660 from atomantic/claim/issue-6656
atomantic Sep 8, 2026
e524348
Merge pull request #6661 from atomantic/claim/issue-6655
atomantic Sep 8, 2026
7954641
fix: keep feature navigation consistent across mounted views (#6662)
atomantic Sep 9, 2026
2284bf7
fix: preserve visible feature navigation during refresh (#6662)
atomantic Sep 9, 2026
a05f07b
Merge pull request #6663 from atomantic/claim/issue-6662
atomantic Sep 9, 2026
ce052b3
fix: support effort pins for configured provider reviewers
atomantic Sep 9, 2026
ecbfb0e
Merge pull request #6664 from atomantic/cos/task-mttd82hd/agent-daf258b8
atomantic Sep 9, 2026
feabe03
fix: report completed backup outcomes consistently (#6665)
atomantic Sep 9, 2026
0220bca
fix: share SongBook save normalization with unsaved edit guards
atomantic Sep 9, 2026
ccda3d9
run the maintenance sequence from the Schedule tab independently of Q…
atomantic Sep 9, 2026
f7d1772
Merge pull request #6666 from atomantic/claim/issue-6665
atomantic Sep 9, 2026
a6dcae7
feat: configure larger-model fallback for oversized PR review issues
atomantic Sep 9, 2026
11017e3
Merge pull request #6667 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 9, 2026
07ca954
merge maintenance-run writes so a Stop or completion cannot be overwr…
atomantic Sep 9, 2026
aa82950
fix: expose review fallback assignments and apply pins only to safe i…
atomantic Sep 9, 2026
510bd59
wait for the dispatch to start before issuing Stop in the maintenance…
atomantic Sep 9, 2026
ce5c73f
Merge pull request #6668 from atomantic/cos/task-mttd6w3v/agent-24e95e42
atomantic Sep 9, 2026
206c513
Merge pull request #6669 from atomantic/cos/task-mtte9xbu/agent-2157d00a
atomantic Sep 9, 2026
70a2c13
fix: gate database restore on valid preview (#6671)
atomantic Sep 9, 2026
a85e87a
feat: stream maintenance progress with active agent notifications
atomantic Sep 9, 2026
de1b7e8
feat: add babble and prune catalog creation flow
atomantic Sep 9, 2026
63534ec
Merge pull request #6673 from atomantic/cos/task-mttg9q2j/agent-83b6a8db
atomantic Sep 9, 2026
5a37ab4
Merge pull request #6674 from atomantic/cos/task-mttgk7r9/agent-9d618913
atomantic Sep 9, 2026
12a4bb0
fix: bind restores to previewed scope (#6670)
atomantic Sep 9, 2026
9d641ed
address review (claude): lock live restore controls
atomantic Sep 9, 2026
a8ed02e
Merge branch 'main' into claim/issue-6671
atomantic Sep 9, 2026
94625d9
Merge pull request #6672 from atomantic/claim/issue-6671
atomantic Sep 9, 2026
912fb37
Merge branch 'main' into claim/issue-6670
atomantic Sep 9, 2026
c08946a
Merge pull request #6675 from atomantic/claim/issue-6670
atomantic Sep 9, 2026
5ef9f67
feat: redesign universe cast as character sheets
atomantic Sep 9, 2026
f9c30f4
Merge pull request #6676 from atomantic/cos/task-mtth13db/agent-ae644fa0
atomantic Sep 9, 2026
d990126
fix: harden Beeper integration and resolve upstream conflicts
atomantic Sep 9, 2026
4afe41c
fix: incorporate current upstream safeguards
atomantic Sep 9, 2026
e74a1cd
refactor: unify media queue lane admission accounting (#6677)
atomantic Sep 9, 2026
330471c
fix: attribute feature group toggles to the user
atomantic Sep 9, 2026
776b089
test: document and restore concurrent remote adapter stub (#6677)
atomantic Sep 9, 2026
9dded62
fix: normalize send guard paths on Windows
atomantic Sep 9, 2026
c16860b
Merge pull request #6649 from tzioup/pr/beeper-upstream
atomantic Sep 9, 2026
728f210
feat: add a relationship Graph tab to the Universe Builder
atomantic Sep 9, 2026
5e84897
feat: give local model metadata a shared service owner
atomantic Sep 9, 2026
18d0d96
Merge pull request #6679 from atomantic/cos/task-mttin1b2/agent-b2c5ce09
atomantic Sep 9, 2026
eb65cbf
Merge pull request #6678 from atomantic/claim/issue-6677
atomantic Sep 9, 2026
ccaaa80
Merge pull request #6683 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 9, 2026
c54f83c
refactor: name VideoGen backend predicates (#6680)
atomantic Sep 9, 2026
90ec4ce
serve hashed client chunks as immutable so warm page loads stop reval…
atomantic Sep 9, 2026
fe04448
name the stale-chunk test for what it asserts: not the SPA index, rat…
atomantic Sep 9, 2026
56a7111
fix: restore completed agent card mobile layout
atomantic Sep 9, 2026
83cb74d
Merge pull request #6686 from atomantic/cos/task-mttkgqky/agent-cfe65e34
atomantic Sep 9, 2026
c69ca4c
Merge pull request #6684 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 9, 2026
17705de
refactor: centralize pinned video snapshot resolution (#6682)
atomantic Sep 9, 2026
a7eeefa
Merge remote-tracking branch 'origin/main' into claim/issue-6680
atomantic Sep 9, 2026
8b3073a
Merge pull request #6685 from atomantic/claim/issue-6680
atomantic Sep 9, 2026
b3e6794
Merge remote-tracking branch 'origin/main' into claim/issue-6682
atomantic Sep 9, 2026
ac2a79c
Merge pull request #6687 from atomantic/claim/issue-6682
atomantic Sep 9, 2026
9e73718
refactor: unify video asset readiness and repair warnings (#6681)
atomantic Sep 9, 2026
d3aacae
fix: keep video repair labels readable with missing metadata (#6681)
atomantic Sep 9, 2026
0a0aa3f
Merge pull request #6688 from atomantic/claim/issue-6681
atomantic Sep 9, 2026
c1e1739
perf: avoid redundant CoS status work during live activity polls (#6689)
atomantic Sep 9, 2026
79fb2fe
Merge pull request #6691 from atomantic/claim/issue-6689
atomantic Sep 9, 2026
0639e9e
perf: fetch only generating 3D summaries for activity polls (#6690)
atomantic Sep 9, 2026
3a50e00
fix: collapse Writers Room controls for focused editing and stabilize…
atomantic Sep 9, 2026
7b726db
fix: keep writing actions on one row on narrow phones
atomantic Sep 9, 2026
6de5f75
Merge pull request #6692 from atomantic/claim/issue-6690
atomantic Sep 9, 2026
6a75142
Merge pull request #6693 from atomantic/cos/task-mttmqfgu/agent-29c3056f
atomantic Sep 9, 2026
b586bad
refactor: make self-update launch readiness explicit (#6694)
atomantic Sep 9, 2026
9fe0f0b
test: preserve app updater mock contract in preflight checks
atomantic Sep 9, 2026
2e83895
Merge pull request #6695 from atomantic/claim/issue-6694
atomantic Sep 9, 2026
4302758
fix: clarify database selection during setup
atomantic Sep 9, 2026
59ae2da
Merge pull request #6696 from atomantic/cos/app-improve-portos-defaul…
atomantic Sep 9, 2026
7e5f191
chore: release v2.61.0
atomantic Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
74 changes: 74 additions & 0 deletions .changelog/v2.61.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Release v2.61.0

Released: 2026-09-09

## Highlights

**Chief of Staff and scheduled work**
- Scheduled audits can now be organized by labeled lenses, with shared guidance, actionable disabled states, and live maintenance progress.
- Quota Burn and scheduled maintenance now preserve ordered plans and invoke the same maintenance sequence independently of one another.
- Agent lifecycle and completion handling now share one consistent path across CLI, TUI, read-only, and claim runs.

**Providers and review operations**
- Code review configuration now selects supported providers, models, and effort pins from the shared catalog, with a larger-model fallback for oversized reviews.
- Provider controls, model metadata, and local backend management now use shared ownership and safer readiness rules.

**Communication and federation**
- Added Beeper as a third communications source, including a desktop bridge and feature-group controls alongside existing messaging integrations.
- Hosted Eidoverse guest sessions now cap microphone input and re-read live session state before relaying it.

**Creative workspaces**
- Universe Builder now offers character-sheet casting plus relationship graph views, timeline navigation, gap inspection, and poster export.
- Writers Room editing is more focused with collapsible sections and stabilized saves, while video asset readiness and repair warnings are now unified.

**Reliability and everyday UI**
- Backup, restore, update, notification, voice-call, and cron paths now report failures and preserve state more consistently.
- Responsive layouts, navigation, disabled controls, and mobile headers received focused fixes across the main workspaces.

## Changes

### Chief of Staff, audits, and maintenance

- Added labeled scheduled-audit lenses and shared run guidance, with catalog-derived audit stages and lane tests.
- Added maintenance sequences that can be launched from scheduled tasks or directly from the Schedule tab, with HTTP-safe identifiers and streamed agent notifications.
- Added ordered maintenance steps to Quota Burn and preserved maintenance plans across refresh failures and disabled-run states.
- Hardened autonomous issue filing with shared labels, substantive-review requirements, and issue-count quota guards.
- Compacted completed agents into a responsive grid and kept claim, read-only, and non-coding runs accurately identified.

### Agent execution and task lifecycle

- Centralized agent completion and status-transition handling across CLI and TUI spawners.
- Contained scheduled handler loading and execution failures and prevented unrelated skill templates from entering scheduled-task prompts.
- Exposed safe shared seams for provider controls and aligned launch behavior with the Claude harness.
- Preserved boundary contracts for task intake, write-task updates, and spawn block-and-bail gates.

### Providers, models, and review

- Added catalog-backed provider and model selection for code review, including effort pins and safe fallback assignments for oversized reviews.
- Gave local model metadata a shared service owner and unified hosted VideoGen backend predicates and asset readiness.
- Added a feature-group toggle for related instance features and attributed group changes to the user.
- Preserved provider control state across refreshes and kept disabled providers from being selected.

### Communications, federation, and voice

- Added Beeper as a desktop-bridge communications source and hardened its integration and feature-group behavior.
- Preserved Telegram notification coverage and aligned unread badges with authoritative server totals.
- Kept voice-call openings pending until TTS delivery, decoded misaligned PCM frames, and capped hosted guest microphone input.

### Creative and media workspaces

- Redesigned Universe Builder cast entries as character sheets and added relationship graph, timeline, gaps, and poster-export workflows.
- Added focused Writers Room controls, collapsible sections, and stable save behavior for narrow and mobile layouts.
- Centralized pinned video snapshot resolution and unified video repair labels and readiness warnings, including missing metadata.
- Preserved scene, media-queue, and render-lane accounting through retries, cancellations, and recovery paths.

### Backup, restore, update, and infrastructure

- Made backup schedule defaults resolve consistently and clarified exclusion-rule state without promising unsupported file inclusion.
- Bound database restores to previewed scope and valid previews, with locked live restore controls.
- Made self-update launch readiness explicit and preserved exact Git paths in CI test selection.
- Improved PM2 log line buffering, cron validation, and cross-platform send guards.

## Full Changelog

**Full Diff**: https://github.com/atomantic/PortOS/compare/v2.60.0...v2.61.0
12 changes: 5 additions & 7 deletions .claude/skills/portos-file-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ description: PortOS conventions for filing GitHub issues and capturing deferred

- **Decide, don't defer — avoid decision-blocked issues (`future` / `needs-input`).** A cluster of open issues that each wait on a human decision is worse than a shipped best-guess the user can iterate on. When you would file a follow-up (or claim one) whose only obstacle is an **undecided design choice** — "option A vs B", "which API shape", "is this in scope" — **make the call yourself**: pick the most reasonable option, state it as *the decision* in the issue body (with a one-line rationale), and file it **ready-to-work**, not parked. The user has explicitly accepted the tradeoff — they would rather iterate on top of a wrong-but-shipped choice than accumulate issues that need decisions. Default to your own recommendation; do not punt the decision back to a human.
- **Ready-to-work is the default.** Label an issue for its kind (`bug`, `enhancement`, `code-quality`, `plan`) and write a decision-complete body — the problem, the chosen approach, affected files/paths, and acceptance criteria — so another agent can pick it up cold and ship it. `plan` marks the claimable queue that `/do:next --issues` drains.
- **Dispatch hints and contributor labels are optional and independent.** When the work you just inspected justifies them, also apply:
- `model:light|medium|heavy` — capability (mechanical vs. hard reasoning)
- `effort:low|medium|high|xhigh|max` — reasoning budget per step, independent of `model:`
- `good first issue` — self-contained, well-specified, a new contributor can ship it without deep repo context. A `model:light` 40-file sweep is **not** a good first issue.
- `help wanted` — extra hands welcome and the body is scoped enough to pick up cold.
- **Planner attribution (`planner:<model>`) records who WROTE the plan.** It is a third independent axis — the author, not a recommendation about how to run the work. Take the label verbatim from the "Planner Attribution" section of your own run's prompt (PortOS resolves it from the provider/model it dispatched you with); **never guess it from what you believe you are**, and omit the axis entirely when your run was given none. Create it like any other label: `gh label create planner:<model> --color C2185B --description 'Plan authored by the <model> model' 2>/dev/null || true`.
Omit an axis rather than guessing. Do not stamp `medium` on both dispatch axes. Do not put `[model:…]` / `[effort:…]` / `[category]` / `[SEVERITY]` in the title. Create each missing label immediately before applying it (`gh label create <name> --color <hex> 2>/dev/null || true`; colors: model:light `D4C5F9`, model:medium `A371F7`, model:heavy `6F42C1`, effort:low `BFE5E5`, effort:medium `76C7C7`, effort:high `1D7874`, effort:xhigh `0E4F4C`, effort:max `05403D`, good first issue `7057FF`, help wanted `008672`). Use repeated `--label` flags. Never relabel a deduplicated existing issue.
- **Apply the canonical issue-label contract.** Follow the runtime **Issue Filing Labels** section and take planner identity from **Planner Attribution**. For a standalone run without that section, read the shared contract from the repository root:
```bash
node --input-type=module -e "import { MANDATORY_DISPATCH_HINT_GUIDANCE } from './server/lib/dispatchLabels.js'; console.log(MANDATORY_DISPATCH_HINT_GUIDANCE)"
```
This is the source of truth for mandatory dispatch axes, contributor-label eligibility, label creation, and read-back verification. Do not maintain a second vocabulary here.
- **`future` is almost never correct.** Do NOT use it to park a choice you could make yourself. The narrow legitimate park is work a **human must personally drive** — a real fidelity/validation run only they can judge, or a step that needs **specific hardware/credentials** the agent doesn't have (e.g. a CUDA box, an Apple-Silicon-only validation). Mark those `blocked` (skipped by autonomous claim runs), not `future`, and say in the body exactly what human action unblocks it. `blocked` also covers a genuine dependency on another unshipped issue/PR — for that case, name the dependency on its own line as `Blocked by #N` (or `Blocked by #N, #M` for more than one): the `issue-reconcile` scheduled task (`blockedIssueReconcile.js`) parses exactly that line, and removes the label automatically once every named issue is closed. An issue with no `Blocked by` line is never auto-unblocked, so the human/hardware case is unaffected.
- **`needs-input` is a last resort, not a reflex.** When claiming an ambiguous issue, prefer proceeding on your best interpretation and shipping it. Fall back to `needs-input` only when proceeding would be **destructive/irreversible** or genuinely requires the human (hardware, credentials, a personal judgment call) — never merely because more than one reasonable reading exists.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Dependencies
node_modules/
/client/node_modules
/server/node_modules

# Build output
dist/
Expand Down
6 changes: 5 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ Client- and server-specific conventions live in nested memory files that load wh

`server/lib/navManifest.js` is the single source of truth for navigation: `NAV_COMMANDS` + `resolveNavCommand()`, consumed by both the `⌘K` palette and the voice agent's `ui_navigate` tool. **Adding a `<Route>` without a `NAV_COMMANDS` entry leaves the page unreachable from `⌘K` and un-navigable by voice.** Invoke the `portos-add-page` skill for the entry shape, palette-action wiring, and the fail-fast guards.

**Optional features gate navigation, not routes.** `server/lib/instanceFeatureRegistry.js` declares the optional per-install features (`post`, `datadog`, `jira`) the user toggles in **Settings > Features**; `server/services/instanceFeatures.js` resolves each one as stored override → auto-detection of the integration it fronts → `defaultEnabled`. A nav entry tagged `feature: '<id>'` (or living in a section listed in navManifest's `SECTION_FEATURE` map) drops out of `⌘K` and the sidebar while that feature is off — **the `<Route>` keeps working, so bookmarks, direct links, and voice `ui_navigate` still resolve**. The gate is applied CLIENT-side (`useInstanceFeatures` + `client/src/lib/navFeatures.js`), not by filtering the manifest response: `⌘K` and the voice widget each fetch `/api/palette/manifest` once per session and it is HTTP-cached, so a server-side filter would both defeat that cache and still show hidden pages until a reload. Tag the sidebar row in `client/src/components/Layout.jsx` with the same id; `navManifest.test.js` scrapes both lists and fails when they drift, when a tag names an unregistered feature, or when a `SECTION_FEATURE` key stops matching a live section.
**Optional features gate navigation, not routes.** `server/lib/instanceFeatureRegistry.js` declares the optional per-install features (`post`, `datadog`, `jira`) the user toggles in **Settings > Features**; `server/services/instanceFeatures.js` resolves each one as stored override → auto-detection of the integration it fronts → `defaultEnabled`. A nav entry tagged `feature: '<id>'` (or living in a section listed in navManifest's `SECTION_FEATURE` map) drops out of `⌘K` and the sidebar while that feature is off — **the `<Route>` keeps working, so bookmarks, direct links, and voice `ui_navigate` still resolve**. The gate is applied CLIENT-side (`useInstanceFeatures` + `client/src/lib/navFeatures.js`), not by filtering the manifest response: `⌘K` and the voice widget each fetch `/api/palette/manifest` once per session and it is HTTP-cached, so a server-side filter would both defeat that cache and still show hidden pages until a reload. A sidebar row still needs its own `NAV_PRESENTATION` entry in `client/src/components/Layout.jsx` (path → icon); `feature`, `section` and `label` are inherited from `NAV_COMMANDS`, so the path is the one thing declared twice — the icon lives only in `NAV_PRESENTATION` — and a manifest tag alone yields no sidebar row — `NAV_PRESENTATION`'s keys are the set the sidebar iterates. `Layout.test.jsx` pins that every Settings, Digital Twin and Messages sub-tab path has a `NAV_PRESENTATION` entry, and that each entry stays presentation-only (an icon, no `to`/`label`/`section`/`feature`) keyed to a live manifest path. `navManifest.test.js` fails when a tag names an unregistered feature, or when a `SECTION_FEATURE` key stops matching a live section.

**Feature groups bucket related features under one toggle, additively.** `INSTANCE_FEATURE_GROUPS` in `server/lib/instanceFeatureRegistry.js` declares the groups (today: `comms`, holding FaceTime Audio, iMessage, Signal, X, Stacker News and Beeper); a feature joins one by carrying `group: '<groupId>'` on its descriptor, which is the whole edit. `resolveOne` in `server/services/instanceFeatures.js` resolves a grouped feature as **its own stored override → the group flag → the detector → `defaultEnabled`**: an explicit per-feature override always wins, and only a feature left on "inherit" answers to its group (group off hides it, group on hands it straight back to its normal resolution). Setting an override back to inherit deletes the stored key rather than writing a third sentinel, so it reads exactly like a feature nobody ever touched. **A group's own `enabled` defaults to `true` when no group state is stored** — that default is the parity guarantee: an install with no `instanceFeatureGroups` in settings resolves every member exactly as it did before the group existed, so registering a group is never a silent hide and needs no settings migration. Malformed group settings fail toward `false`, matching the per-feature override's own posture. An ungrouped feature is completely unaffected.

**A feature toggle that arms background work must reconcile that work at toggle time, not only at boot.** A subsystem gated on "feature on AND credential present" and started once in `services/bootstrap.js` is silently wrong the moment either half of that gate moves at runtime: on a live install, storing a Beeper credential left the realtime transport down and no sweep registered for 48 minutes, until a restart — and the mirror-image gap left a socket relaying on a token a disconnect had just revoked. Give the subsystem one idempotent `reconcile…()` that reads the gate and moves everything to match it, and call it from every path that can move the gate (each credential write, the feature toggle, the group toggle, disconnect). Make repeat calls no-ops rather than re-registrations — re-`schedule()`ing an existing event resets `nextRunAt` a full interval out, so an unrelated toggle would keep pushing the next run away — serialize overlapping calls on one tail, and log transitions only, so an install that has never enabled the feature still narrates nothing. `server/services/beeperArming.js` is the worked example.

### Slashdo Commands (`lib/slashdo`)

Expand Down
1 change: 1 addition & 0 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export default function App() {
<Route path="cos" element={<Navigate to="/cos/tasks" replace />} />
<Route path="cos/mind/tools" element={<Navigate to="/cos/mind?panel=tools" replace />} />
<Route path="cos/tools" element={<Navigate to="/cos/mind?panel=tools" replace />} />
<Route path="cos/:tab/:agentId" element={<ChiefOfStaff />} />
<Route path="cos/:tab" element={<ChiefOfStaff />} />
<Route path="calendar" element={<Navigate to="/calendar/agenda" replace />} />
<Route path="calendar/:tab" element={<CalendarPage />} />
Expand Down
Loading
Loading