From e900612c62bce9edff125eb4873f14678ae1bb27 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 6 Jul 2026 21:12:04 +0800 Subject: [PATCH 1/3] Add north star release readiness gate --- docs/core-sidecar-north-star.md | 2 + docs/north-star-completion-tracker.md | 365 ++++++++++++++++++++++++++ docs/release-readiness-gate.md | 64 +++++ docs/runtime-authority-dead-paths.md | 7 + package.json | 2 + scripts/verify-north-star-tracker.mjs | 73 ++++++ 6 files changed, 513 insertions(+) create mode 100644 docs/north-star-completion-tracker.md create mode 100644 docs/release-readiness-gate.md create mode 100755 scripts/verify-north-star-tracker.mjs diff --git a/docs/core-sidecar-north-star.md b/docs/core-sidecar-north-star.md index 3d286810..d8c17f3d 100644 --- a/docs/core-sidecar-north-star.md +++ b/docs/core-sidecar-north-star.md @@ -225,3 +225,5 @@ to stay coherent. The command-level working inventory lives in [command-ownership-inventory.md](command-ownership-inventory.md). +The cross-epic completion tracker lives in +[north-star-completion-tracker.md](north-star-completion-tracker.md). diff --git a/docs/north-star-completion-tracker.md b/docs/north-star-completion-tracker.md new file mode 100644 index 00000000..c1ca8296 --- /dev/null +++ b/docs/north-star-completion-tracker.md @@ -0,0 +1,365 @@ +# Aimux North Star Completion Tracker + +This is the measuring stick for the API-first, long-lived-sidecar migration. +It tracks what remains before the architecture is complete, not just what is +needed for the next shippable build. + +Related docs: + +- [core-sidecar-north-star.md](core-sidecar-north-star.md): target architecture +- [release-readiness-gate.md](release-readiness-gate.md): release-candidate gate +- [command-ownership-inventory.md](command-ownership-inventory.md): command-level no-spawn ownership +- [runtime-authority-inventory.md](runtime-authority-inventory.md): source-of-truth map by domain +- [runtime-authority-dead-paths.md](runtime-authority-dead-paths.md): audit commands for old paths +- [runtime-projection-contract.md](runtime-projection-contract.md): projection/cache boundary + +## Progress Scale + +Use these labels consistently: + +- `Done`: replacement shipped, old authority removed or demoted, tests enforce it. +- `Mostly done`: normal paths use the new model, but cleanup, diagnostics, or + edge-case enforcement remains. +- `Partial`: the new model exists, but old authority or bespoke client logic + still participates in normal behavior. +- `Not started`: no durable replacement has landed. +- `Deferred`: intentionally not needed for the next build, but still required + for north-star completion. + +## Executive Snapshot + +| Area | Status | Ship Risk | North-Star Risk | Measurement | +| --- | --- | --- | --- | --- | +| Command no-spawn healthy paths | Mostly done | Medium | Medium | `command-ownership-inventory.md` says no normal command is still `SIDECAR`. Need release-gate no-spawn audit. | +| Daemon/project-service ownership | Mostly done | Medium | Medium | Core command families route through daemon/project-service; diagnostics and internal paths still need periodic audit. | +| TUI shared state API boundary | Mostly done | High | High | TUI reads/mutations are largely API-backed, but connection/retry/repair behavior is still not one central contract. | +| TUI transition stability | Partial | High | High | Pending-action protections exist; repeated start/stop/revive churn still needs focused smoke and regression tests. | +| Web/mobile resource lifecycle | Mostly done | Medium | Medium | Major app resources preserve stale snapshots; remaining screen-local fetch state and route-race patterns need audit. | +| Project-service events parity | Partial | Medium | High | Some push exists; remote clients still need complete change events for all API-backed views. | +| Runtime topology authority | Partial | Medium | High | Agents/services/worktrees are partly topology-owned; old caches and fail-closed lifecycle paths remain. | +| Runtime exchange authority | Partial | Low for next build | High | Notifications are exchange-backed; threads/tasks/handoffs/reviews/waits still have legacy-file authority. | +| tmux boundary | Mostly done | Medium | Medium | tmux is treated as substrate for local navigation/focus, but binding recovery and remote equivalents need finalization. | +| Upgrade/restart coherence | Mostly done | High | Medium | `aimux restart` and install repair are strong; release rehearsal must prove multi-project coherence from old builds. | +| Dead-code/dead-path deletion | Partial | Low for next build | High | Inventories exist; old paths remain until each authority cut lands. | +| Regression smoke coverage | Partial | High | High | Unit coverage is broad; end-to-end churn smoke still needs a documented release gate and recurring execution. | + +## Completion Epics + +### Epic A: Release Coherence Gate + +Goal: every release candidate can be installed over a dirty, running Aimux and +leave the user with coherent daemon, services, dashboards, and tmux runtime. + +Status: `Mostly done` + +Remaining: + +- [x] Add a release-candidate checklist covering local release asset install, + post-install repair, daemon/service/dashboard version coherence, and runtime + contract drift repair. +- [ ] Smoke `aimux restart` across at least two active projects with existing + dashboards and agent windows. +- [ ] Verify `aimux doctor versions` reports coherent daemon, project services, + dashboards, and runtime owners after install. +- [ ] Verify old dashboard/client windows reload or reconnect without exposing + stale-build decision dialogs. +- [ ] Verify agent tmux windows survive restart unless a deliberate runtime + rebuild path is required. +- [ ] Document exactly where repair notices are recorded for debugging. + +Done when: + +- A local release install from `master` can be used as the release rehearsal. +- The checklist has pass/fail evidence for at least one real multi-project run. +- The only user-facing recovery instruction for normal drift is `aimux restart` + or automatic repair. + +### Epic B: Healthy CLI No-Spawn Purity + +Goal: normal installed commands do not spawn Node when a matching daemon is +healthy. + +Status: `Mostly done` + +Remaining: + +- [ ] Add or refresh a release-gate script/test that exercises the installed + shell shim against a healthy daemon and proves all `CUT` commands avoid Node + startup. +- [ ] Reconcile any command not listed in + [command-ownership-inventory.md](command-ownership-inventory.md). +- [ ] Keep bootstrap-only commands explicit: `aimux`, `aimux init`, install, + stale-daemon recovery, and explicit debug/internal plumbing. +- [ ] Ensure invalid args for recognized `CUT` commands fail in the shim without + spawning Node when the daemon is healthy. +- [ ] Keep output parity for text and JSON modes as commands move or change. + +Done when: + +- The inventory has no unclassified normal command. +- Healthy no-spawn tests are part of CI or release gating. +- Stale/missing daemon fallback tests still prove bootstrap works. + +### Epic C: One TUI Connection Contract + +Goal: the TUI has one API connection adapter for refresh, reconnect, repair, +stale snapshots, and lifecycle transition settlement. + +Status: `Partial` + +Remaining: + +- [ ] Inventory current TUI service/API request sites and overlays. +- [ ] Define one connection state machine: + `ready`, `refreshing`, `stale`, `reconnecting`, `repairing`, `repaired`, + `failed`. +- [ ] Route screen refreshes through the shared adapter instead of screen-local + retry/overlay logic. +- [ ] Keep last coherent snapshot visible while reconnecting unless the specific + resource is known invalid. +- [ ] Block only unsafe mutating actions while disconnected; keep local + navigation instant. +- [ ] Emit user-visible repair notices whenever automatic repair happens. +- [ ] Add regression tests for route/service drift, service restart, slow API, + stale snapshot preservation, and failed repair. + +Done when: + +- No TUI screen owns bespoke project-service reconnect semantics. +- Reconnect/repair behavior is consistent across Dashboard, Coordination, + Project, Library, Topology, Graveyard, and Expose/meta surfaces. +- Fast local navigation does not wait on API calls. + +### Epic D: Lifecycle Transition Contract + +Goal: start, stop, revive, create, kill, fork, migrate, service start/stop, and +worktree operations render the same transition state in TUI, web, mobile, and +CLI. + +Status: `Partial` + +Remaining: + +- [ ] Define canonical transition records in the project-service API response: + operation id, target id/path, kind, phase, startedAt, updatedAt, error. +- [ ] Ensure lifecycle mutations return or emit enough state for clients to + render pending rows without guessing. +- [ ] Reconcile optimistic client state only against fresh API-backed state. +- [ ] Preserve pending transition display during transient refresh failures. +- [ ] Prevent stale refreshes from clearing pending rows before matching + settlement. +- [ ] Add fast churn tests for create/start/stop/revive/retry in TUI and app + stores. +- [ ] Document which transitions are tmux-substrate actions versus product-state + actions. + +Done when: + +- The same API state explains every lifecycle transition shown by TUI and app. +- Clients do not infer success from local optimism alone. +- Repeated lifecycle churn does not flicker backward or lose rows. + +### Epic E: App/Web/Mobile Resource Contract + +Goal: every shared app view uses resource lifecycle state rather than +screen-local fetch/loading/error state. + +Status: `Mostly done` + +Remaining: + +- [ ] Audit app screens for local `loading`, `error`, `fetch`, and route-key + request refs that duplicate the resource-store model. +- [ ] Move any remaining shared project views into resource stores with + `value`, `pending`, `stale`, `error`, `updatedAt`, and request keys. +- [ ] Apply route/endpoint stale-response guards to every selected-project + resource. +- [ ] Keep durable preferences in Jotai storage and transient UI state in UI + stores only. +- [ ] Add route-switch tests for critical screens: Dashboard, Threads, + Coordination, Project, Library, Topology, Graveyard, Plan Editor. +- [ ] Verify native/web behavior under daemon restart and project-service + reconnect. + +Done when: + +- App screens render from resource stores for shared project data. +- Route changes cannot apply old endpoint/project responses. +- Refresh failure preserves last good data unless the route itself changed. + +### Epic F: Project-Service Events Parity + +Goal: remote clients can stay current from project-service `/events` without +polling every important view. + +Status: `Partial` + +Remaining: + +- [ ] Inventory all API-backed views and the events that should invalidate them. +- [ ] Emit change events for lifecycle, services, worktrees, graveyard, + notifications, Coordination, threads, tasks, handoffs, reviews, Library, + Topology, Project observability, plans, and repair/coherence changes. +- [ ] Make app event handling invalidate or refresh the right resource stores. +- [ ] Keep TUI push behavior aligned with the same semantic event names, even if + it receives them through an in-process bus. +- [ ] Add tests for event emission on each mutation family. +- [ ] Document event payload compatibility rules. + +Done when: + +- Every shared view has a named event invalidation path. +- Remote app clients do not require ad hoc polling for lifecycle-critical state. +- TUI and app use the same semantic event names. + +### Epic G: Runtime Topology Authority + +Goal: topology is the authority for agents, services, worktrees, lifecycle, +graveyard, bindings, and topology-backed operation state. + +Status: `Partial` + +Remaining: + +- [ ] Finish cutting agent lifecycle resume/revive paths to topology-owned + semantics. +- [ ] Remove or demote `offlineSessions` as lifecycle authority. +- [ ] Remove or demote `graveyardEntries` as agent graveyard authority. +- [ ] Finish service lifecycle authority over topology service records and demote + `.aimux/state.json` service rows to compatibility/debug snapshots. +- [ ] Finalize durable tmux binding records and use tmux metadata only as live + substrate evidence. +- [ ] Decide whether team role config remains separate config authority or moves + into topology schema. +- [ ] Run the Agent Lifecycle, Services, Worktrees, Tmux Binding, and Team audit + commands in [runtime-authority-dead-paths.md](runtime-authority-dead-paths.md) + after every related cut. + +Done when: + +- Lifecycle and graveyard truth does not depend on old in-memory caches. +- Topology survives process restart and can repair tmux bindings. +- Old topology-domain paths are projections, tests, importers, or fail-closed + compatibility only. + +### Epic H: Runtime Exchange Authority + +Goal: runtime exchange is the authority for messages, tasks, reviews, handoffs, +waits, inbox routing, notification records, and notification read/done state. + +Status: `Partial` + +Remaining: + +- [ ] Complete thread/message compatibility APIs over runtime exchange. +- [ ] Move direct messages and delivery state out of `.aimux/threads` authority. +- [ ] Model handoffs as first-class exchange records. +- [ ] Model tasks and reviews as first-class exchange records. +- [ ] Replace scattered wait/inbox truth with exchange-derived inbox state. +- [ ] Move alert recipient derivation into exchange-owned routing semantics. +- [ ] Decide plan, continuity, status, and attachment authority boundaries. +- [ ] Keep old files as explicit import/export artifacts or fail-closed + compatibility only. +- [ ] Run the Exchange, Tasks/Reviews, Waiting/Inbox, Plans, and Continuity audit + commands in [runtime-authority-dead-paths.md](runtime-authority-dead-paths.md). + +Done when: + +- `.aimux/threads` and `.aimux/tasks` are no longer normal write authorities. +- Workflow, Coordination, notifications, and inbox surfaces are exchange + projections. +- Legacy files are import/export/debug artifacts only. + +### Epic I: Tmux Boundary And Remote Equivalents + +Goal: tmux remains local execution/focus/pane transport, while product state +comes from daemon/project-service APIs. + +Status: `Mostly done` + +Remaining: + +- [ ] Keep Expose/meta-dashboard explicitly tmux-native and read-only for + product state. +- [ ] Finalize pane read and stream APIs as the remote equivalent for live pane + output. +- [ ] Define remote behavior for "open/focus": deep link, focus request, or + same-machine-only capability. +- [ ] Ensure fast prefix navigation uses tmux-local metadata/statusline caches, + not slow API calls. +- [ ] Add latency checks for dashboard return, next/prev, attention jump, and + expose/global expose. + +Done when: + +- Remote clients never need raw tmux mechanics. +- Same-machine TUI remains fast because local navigation stays tmux-native. +- tmux metadata cannot become product-state authority. + +### Epic J: Diagnostics, Debug, And Dead-Path Deletion + +Goal: diagnostics explain the authoritative system without recomputing or +reviving old truth. + +Status: `Partial` + +Remaining: + +- [ ] Make `aimux doctor versions` and related diagnostics read daemon/project + truth rather than local recomputation when healthy. +- [ ] Keep debug state read-only and label every source as authority, + projection/cache, substrate, or legacy. +- [ ] Remove old fallback builders after their API-backed replacements are + proven. +- [ ] Remove direct client writers to runtime exchange/topology once service + routes exist. +- [ ] Keep advanced commands documented as debug/internal, not normal user + recovery. +- [ ] Add tests that fail if removed paths silently write old files. + +Done when: + +- Debug output cannot create or repair state. +- No normal user docs point people to advanced repair commands. +- Dead-path audit commands show only allowed projection/cache/importer/exporter, + test, or fail-closed compatibility matches. + +## Release-Ready Versus North-Star Complete + +Release-ready does not require every item above. A new build can ship once: + +- lifecycle transitions are stable under normal user churn; +- install/restart repair coherence is proven on real running projects; +- the TUI no longer exposes confusing repair/sync decision loops; +- app/web route-stale response races are covered for critical screens; +- healthy installed CLI no-spawn behavior is rechecked; +- docs tell users one recovery path, not a menu of internals. + +North-star complete requires every completion epic above to be `Done`. + +## Scorecard Template + +Update this table after each epic PR. + +| Date | PR | Area | Before | After | Evidence | +| --- | --- | --- | --- | --- | --- | +| 2026-07-06 | #339 | App resource lifecycle | Partial | Mostly done | Project tab observability/tasks moved to resource actions; route/endpoint stale response race fixed; app focused tests and PR checks passed. | + +## How To Measure Progress + +At each epic boundary: + +1. Pick one row from the Executive Snapshot. +2. State its current status and target status for the PR. +3. Run the relevant audit commands from the linked inventory docs. +4. Land the cut or cleanup. +5. Add/adjust enforcement tests. +6. Update this tracker with the PR and evidence. + +Do not call an area `Done` because the happy path works once. `Done` requires: + +- old authority removed or explicitly demoted; +- no silent dual-writes; +- no normal user path through debug plumbing; +- tests or smoke evidence that would catch regression; +- docs updated so future agents can measure the same thing. diff --git a/docs/release-readiness-gate.md b/docs/release-readiness-gate.md new file mode 100644 index 00000000..f80447fa --- /dev/null +++ b/docs/release-readiness-gate.md @@ -0,0 +1,64 @@ +# Aimux Release Readiness Gate + +This gate is the release-candidate rehearsal for the API-first, long-lived +sidecar migration. It is narrower than north-star completion: it proves a build +can be installed over a live Aimux and leave normal users with one coherent +system. + +## Automated Gate + +Run from a clean checkout on the candidate branch: + +```bash +yarn release:readiness +``` + +This runs the normal source verification plus the north-star tracker verifier. +It does not replace runtime rehearsal because the live daemon, project services, +tmux windows, and installed bundle are outside source-only tests. + +## Runtime Rehearsal + +Run this before promoting a build: + +```bash +git status --short +yarn build +AIMUX_RELEASE_VERSION=local-$(git rev-parse --short HEAD) yarn release:asset +ASSET="$(ls -t release/aimux-*.tar.gz | head -n 1)" +scripts/install.sh "$ASSET" +aimux doctor versions +aimux restart +aimux doctor versions +``` + +Expected result: + +- daemon, project services, dashboards, and runtime owners report the same + installed build; +- existing dashboard windows reload or reconnect without stale-build decision + dialogs; +- existing agent tmux windows survive unless the runtime contract intentionally + requires a rebuild; +- repair notices are recorded in the debug log and visible enough to explain + why repair happened. + +## Multi-Project Smoke + +Use at least two active projects with existing dashboards and agent windows. +In each project: + +1. Open the dashboard. +2. Start or restore one offline agent and verify the row stays in a pending + state until fresh API state settles. +3. Stop the agent and verify the row does not flicker back to running. +4. Switch through Dashboard, Coordination, Project, Library, Topology, and + Graveyard without losing the last coherent snapshot during reconnect. +5. Run `aimux doctor versions` after the smoke and confirm no drift remains. + +## Release Evidence + +Record the PR, before/after status, and evidence in +[north-star-completion-tracker.md](north-star-completion-tracker.md). Do not +mark a north-star area `Done` unless old authority is removed or explicitly +demoted and tests or smoke evidence would catch regression. diff --git a/docs/runtime-authority-dead-paths.md b/docs/runtime-authority-dead-paths.md index d281281b..604fbf89 100644 --- a/docs/runtime-authority-dead-paths.md +++ b/docs/runtime-authority-dead-paths.md @@ -8,6 +8,13 @@ Use this file with [runtime-authority-inventory.md](runtime-authority-inventory. Every future implementation phase should run the relevant `rg` commands before planning, after implementation, and before commit. A match is acceptable only when the code is a projection/cache, a one-way importer/exporter, a test asserting the cut, or an intentionally blocked compatibility route. +## Completion Gate + +An authority area is complete only when its audit commands show old paths are +gone or explicitly classified as projection/cache, importer/exporter, tests, or +fail-closed compatibility. No normal client, CLI, or TUI path may silently write +through a retired authority. + ## Agent Lifecycle Audit commands: diff --git a/package.json b/package.json index 22a0ff9a..7e47e6d0 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,8 @@ "format:check": "prettier --check src/", "verify": "yarn typecheck && yarn lint && yarn test", "verify:codex-instructions": "bash scripts/verify-codex-developer-instructions.sh", + "verify:north-star": "./scripts/verify-north-star-tracker.mjs", + "release:readiness": "yarn verify && yarn verify:north-star", "release:asset": "bash scripts/build-release-asset.sh", "release:patch": "yarn version --patch && git push --follow-tags", "release:minor": "yarn version --minor && git push --follow-tags", diff --git a/scripts/verify-north-star-tracker.mjs b/scripts/verify-north-star-tracker.mjs new file mode 100755 index 00000000..eab1734a --- /dev/null +++ b/scripts/verify-north-star-tracker.mjs @@ -0,0 +1,73 @@ +#!/usr/bin/env node +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +const root = process.cwd(); +const failures = []; + +function readProjectFile(path) { + return readFileSync(join(root, path), "utf8"); +} + +function fail(message) { + failures.push(message); +} + +function expectIncludes(file, needle, label = needle) { + const text = readProjectFile(file); + if (!text.includes(needle)) { + fail(`${file} is missing ${label}`); + } +} + +function expectPackageScript(name, expected) { + const packageJson = JSON.parse(readProjectFile("package.json")); + const actual = packageJson.scripts?.[name]; + if (actual !== expected) { + fail(`package.json script ${name} should be ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`); + } +} + +const tracker = "docs/north-star-completion-tracker.md"; + +expectIncludes("docs/core-sidecar-north-star.md", "[north-star-completion-tracker.md](north-star-completion-tracker.md)", "tracker link"); +expectIncludes(tracker, "[release-readiness-gate.md](release-readiness-gate.md)", "release readiness gate link"); +expectIncludes("docs/release-readiness-gate.md", "yarn release:readiness", "automated readiness command"); +expectIncludes("docs/release-readiness-gate.md", "aimux doctor versions", "version coherence check"); +expectIncludes("docs/release-readiness-gate.md", "aimux restart", "single recovery command"); +expectIncludes("docs/command-ownership-inventory.md", "No commands currently live in this category.", "empty shim gap marker"); +expectIncludes("docs/runtime-authority-dead-paths.md", "## Completion Gate", "runtime authority completion gate"); + +for (const epic of ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]) { + expectIncludes(tracker, `### Epic ${epic}:`, `Epic ${epic}`); +} + +for (const area of [ + "Command no-spawn healthy paths", + "Daemon/project-service ownership", + "TUI shared state API boundary", + "TUI transition stability", + "Web/mobile resource lifecycle", + "Project-service events parity", + "Runtime topology authority", + "Runtime exchange authority", + "tmux boundary", + "Upgrade/restart coherence", + "Dead-code/dead-path deletion", + "Regression smoke coverage", +]) { + expectIncludes(tracker, `| ${area} |`, `Executive Snapshot row: ${area}`); +} + +expectPackageScript("verify:north-star", "./scripts/verify-north-star-tracker.mjs"); +expectPackageScript("release:readiness", "yarn verify && yarn verify:north-star"); + +if (failures.length > 0) { + console.error("North-star tracker verification failed:"); + for (const failure of failures) { + console.error(`- ${failure}`); + } + process.exit(1); +} + +console.log("North-star tracker verification passed."); From e56c1ac6df918905b288726b994ad6f5f4612d6d Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 6 Jul 2026 21:24:20 +0800 Subject: [PATCH 2/3] Include app checks in release readiness --- .github/workflows/release.yml | 2 +- docs/release-readiness-gate.md | 7 ++++--- package.json | 3 ++- scripts/verify-north-star-tracker.mjs | 5 ++++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f28ab95d..2fe625d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ jobs: - run: yarn --cwd app install --frozen-lockfile - - run: yarn verify + - run: yarn release:readiness - name: Build release asset run: yarn release:asset diff --git a/docs/release-readiness-gate.md b/docs/release-readiness-gate.md index f80447fa..78a53f4a 100644 --- a/docs/release-readiness-gate.md +++ b/docs/release-readiness-gate.md @@ -13,9 +13,10 @@ Run from a clean checkout on the candidate branch: yarn release:readiness ``` -This runs the normal source verification plus the north-star tracker verifier. -It does not replace runtime rehearsal because the live daemon, project services, -tmux windows, and installed bundle are outside source-only tests. +This runs the normal root source verification, app verification, and the +north-star tracker verifier. It does not replace runtime rehearsal because the +live daemon, project services, tmux windows, and installed bundle are outside +source-only tests. ## Runtime Rehearsal diff --git a/package.json b/package.json index 7e47e6d0..dbc85918 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,10 @@ "format": "prettier --write src/", "format:check": "prettier --check src/", "verify": "yarn typecheck && yarn lint && yarn test", + "verify:app": "yarn --cwd app typecheck && yarn --cwd app lint && yarn --cwd app test", "verify:codex-instructions": "bash scripts/verify-codex-developer-instructions.sh", "verify:north-star": "./scripts/verify-north-star-tracker.mjs", - "release:readiness": "yarn verify && yarn verify:north-star", + "release:readiness": "yarn verify && yarn verify:app && yarn verify:north-star", "release:asset": "bash scripts/build-release-asset.sh", "release:patch": "yarn version --patch && git push --follow-tags", "release:minor": "yarn version --minor && git push --follow-tags", diff --git a/scripts/verify-north-star-tracker.mjs b/scripts/verify-north-star-tracker.mjs index eab1734a..1fb9b074 100755 --- a/scripts/verify-north-star-tracker.mjs +++ b/scripts/verify-north-star-tracker.mjs @@ -33,10 +33,12 @@ const tracker = "docs/north-star-completion-tracker.md"; expectIncludes("docs/core-sidecar-north-star.md", "[north-star-completion-tracker.md](north-star-completion-tracker.md)", "tracker link"); expectIncludes(tracker, "[release-readiness-gate.md](release-readiness-gate.md)", "release readiness gate link"); expectIncludes("docs/release-readiness-gate.md", "yarn release:readiness", "automated readiness command"); +expectIncludes("docs/release-readiness-gate.md", "app verification", "app verification scope"); expectIncludes("docs/release-readiness-gate.md", "aimux doctor versions", "version coherence check"); expectIncludes("docs/release-readiness-gate.md", "aimux restart", "single recovery command"); expectIncludes("docs/command-ownership-inventory.md", "No commands currently live in this category.", "empty shim gap marker"); expectIncludes("docs/runtime-authority-dead-paths.md", "## Completion Gate", "runtime authority completion gate"); +expectIncludes(".github/workflows/release.yml", "yarn release:readiness", "release workflow readiness gate"); for (const epic of ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]) { expectIncludes(tracker, `### Epic ${epic}:`, `Epic ${epic}`); @@ -60,7 +62,8 @@ for (const area of [ } expectPackageScript("verify:north-star", "./scripts/verify-north-star-tracker.mjs"); -expectPackageScript("release:readiness", "yarn verify && yarn verify:north-star"); +expectPackageScript("verify:app", "yarn --cwd app typecheck && yarn --cwd app lint && yarn --cwd app test"); +expectPackageScript("release:readiness", "yarn verify && yarn verify:app && yarn verify:north-star"); if (failures.length > 0) { console.error("North-star tracker verification failed:"); From 90bd4e784df0f1d3f167e071e10f9bf895313aa4 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 6 Jul 2026 21:39:46 +0800 Subject: [PATCH 3/3] Tighten release readiness lint gate --- app/app/cli-auth.tsx | 55 +++++++++++++++------------ docs/runtime-authority-dead-paths.md | 8 +--- package.json | 2 +- scripts/verify-north-star-tracker.mjs | 2 +- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/app/app/cli-auth.tsx b/app/app/cli-auth.tsx index 098e978a..43a1794f 100644 --- a/app/app/cli-auth.tsx +++ b/app/app/cli-auth.tsx @@ -47,6 +47,26 @@ export default function CliAuthScreen() { const [phase, setPhase] = useState("checking"); const [error, setError] = useState(""); + let blockingPhase: Phase | null = null; + let blockingError = ""; + let shouldRedirectBlockingError = false; + if (!callback) { + blockingPhase = "error"; + blockingError = "Missing callback parameter"; + } else if (!isAllowedCallback(callback)) { + blockingPhase = "invalid-callback"; + blockingError = "Refusing to authorize: callback is not a localhost loopback URL."; + } else if (LOCAL_MODE) { + blockingPhase = "error"; + blockingError = "This deployment runs in local mode — no remote login needed."; + shouldRedirectBlockingError = true; + } + + const effectivePhase = !isLoaded + ? phase + : (blockingPhase ?? (!isSignedIn ? "need-signin" : phase)); + const effectiveError = blockingError || error; + function redirectToCallback(qs: string) { if (!callback) return; const sep = callback.includes("?") ? "&" : "?"; @@ -57,29 +77,14 @@ export default function CliAuthScreen() { useEffect(() => { if (!isLoaded) return; - if (!callback) { - setError("Missing callback parameter"); - setPhase("error"); - return; - } - if (!isAllowedCallback(callback)) { - // Refuse outright — never even attempt to mint a token for an unsafe - // callback target, and never redirect anywhere we might leak it. - setError("Refusing to authorize: callback is not a localhost loopback URL."); - setPhase("invalid-callback"); - return; - } - if (LOCAL_MODE) { - const msg = "This deployment runs in local mode — no remote login needed."; - setError(msg); - setPhase("error"); + if (blockingPhase) { + if (!shouldRedirectBlockingError) return; redirectToCallback( - `error=${encodeURIComponent(msg)}&state=${encodeURIComponent(loginState ?? "")}`, + `error=${encodeURIComponent(blockingError)}&state=${encodeURIComponent(loginState ?? "")}`, ); return; } if (!isSignedIn) { - setPhase("need-signin"); return; } @@ -130,23 +135,23 @@ export default function CliAuthScreen() { cancelled = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoaded, isSignedIn, callback]); + }, [isLoaded, isSignedIn, callback, blockingPhase, blockingError, shouldRedirectBlockingError]); return ( aimux - {phase === "checking" || phase === "issuing" ? ( + {effectivePhase === "checking" || effectivePhase === "issuing" ? ( <> - {phase === "issuing" ? "Authorizing CLI..." : "Checking session..."} + {effectivePhase === "issuing" ? "Authorizing CLI..." : "Checking session..."} ) : null} - {phase === "need-signin" ? ( + {effectivePhase === "need-signin" ? ( <> Sign in to authorize the CLI @@ -168,14 +173,14 @@ export default function CliAuthScreen() { ) : null} - {phase === "done" ? ( + {effectivePhase === "done" ? ( ✓ CLI authorized. Return to your terminal. ) : null} - {phase === "error" || phase === "invalid-callback" ? ( - {error} + {effectivePhase === "error" || effectivePhase === "invalid-callback" ? ( + {effectiveError} ) : null} diff --git a/docs/runtime-authority-dead-paths.md b/docs/runtime-authority-dead-paths.md index 604fbf89..d1856b4c 100644 --- a/docs/runtime-authority-dead-paths.md +++ b/docs/runtime-authority-dead-paths.md @@ -8,13 +8,6 @@ Use this file with [runtime-authority-inventory.md](runtime-authority-inventory. Every future implementation phase should run the relevant `rg` commands before planning, after implementation, and before commit. A match is acceptable only when the code is a projection/cache, a one-way importer/exporter, a test asserting the cut, or an intentionally blocked compatibility route. -## Completion Gate - -An authority area is complete only when its audit commands show old paths are -gone or explicitly classified as projection/cache, importer/exporter, tests, or -fail-closed compatibility. No normal client, CLI, or TUI path may silently write -through a retired authority. - ## Agent Lifecycle Audit commands: @@ -231,5 +224,6 @@ A hard-cut phase is not complete until: - the relevant audit commands have no authority-bearing matches outside the new topology/exchange/projection stores; - remaining matches are named as projection/cache/importer/exporter/test/fail-closed compatibility; +- no normal client, CLI, or TUI path silently writes through a retired authority; - source verification passes with `yarn typecheck && yarn lint && yarn test`; - runtime verification is run when `src/*.ts` behavior changes, including `yarn build` before manual runtime testing. diff --git a/package.json b/package.json index dbc85918..8de256a3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "format": "prettier --write src/", "format:check": "prettier --check src/", "verify": "yarn typecheck && yarn lint && yarn test", - "verify:app": "yarn --cwd app typecheck && yarn --cwd app lint && yarn --cwd app test", + "verify:app": "yarn --cwd app typecheck && yarn --cwd app lint --max-warnings=0 && yarn --cwd app test", "verify:codex-instructions": "bash scripts/verify-codex-developer-instructions.sh", "verify:north-star": "./scripts/verify-north-star-tracker.mjs", "release:readiness": "yarn verify && yarn verify:app && yarn verify:north-star", diff --git a/scripts/verify-north-star-tracker.mjs b/scripts/verify-north-star-tracker.mjs index 1fb9b074..79bc735e 100755 --- a/scripts/verify-north-star-tracker.mjs +++ b/scripts/verify-north-star-tracker.mjs @@ -62,7 +62,7 @@ for (const area of [ } expectPackageScript("verify:north-star", "./scripts/verify-north-star-tracker.mjs"); -expectPackageScript("verify:app", "yarn --cwd app typecheck && yarn --cwd app lint && yarn --cwd app test"); +expectPackageScript("verify:app", "yarn --cwd app typecheck && yarn --cwd app lint --max-warnings=0 && yarn --cwd app test"); expectPackageScript("release:readiness", "yarn verify && yarn verify:app && yarn verify:north-star"); if (failures.length > 0) {