Skip to content

refactor: professionalize pass — gates in CI, deep seams, component extractions#181

Merged
0xSero merged 30 commits into
mainfrom
loop/professionalize
Jul 13, 2026
Merged

refactor: professionalize pass — gates in CI, deep seams, component extractions#181
0xSero merged 30 commits into
mainfrom
loop/professionalize

Conversation

@0xSero

@0xSero 0xSero commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Overnight professionalization loop (~24 commits, ledger with per-iteration rationale in docs/professionalize-loop.md).

Bugs fixed

  • Chat streams lost their keepalive after the first upstream chunk — long tool-call gaps later in a turn got no heartbeats (Cloudflare-sensitive). Regression test included.
  • Malformed recipe JSON returned 500 instead of 400 (ctx.req.json() threw outside the try).
  • SessionStatus union was voided by | string — zero type safety; session-index re-derived "working" from strings incl. a status that doesn't exist.
  • AggregatedSession client contract omitted four fields the server actually sends, and was defined twice.

Gates & tests

  • The contracts/structure gates now run in CI (they were local-only — the root cause of three contributors' phantom check:contracts failures).
  • Frontend unit tests now gate root npm run check; the misnamed "e2e" suites are honestly named regression.
  • New end-to-end chat proxy tests: upstream forwarding, keepalive-first-byte SSE contract, model_not_running 503 gate.

Deepened seams (controller)

  • One process-inventory parser behind the ProcessRunner seam replaces three independent ps parsers.
  • Engine-specific knowledge (vLLM allowlist/Docker-JIT, llama.cpp binary rules) moved out of backend-builder into their EngineSpec files; backend-builder is engine-agnostic (413→279).
  • Five copy-paste /runtime/{backend}/upgrade routes → one validated /runtime/:backend/upgrade (closes Collapse redundant runtime upgrade routes into /runtime/jobs #145); frontend mirror collapsed too.
  • The 387-line engines god-router split into recipe/lifecycle/download/runtime registrars.
  • The 220-line chat-completions handler decomposed into named stages, pinned by the new tests.

Deepened seams (frontend)

  • session-status.ts: canonical settleTurn/isWorkingStatus replaces five hand-rolled settle copies; SessionStatus and SessionTab.status share the tightened union.
  • tools/selection-persistence.ts single-owns the ToolSelection wire shape (workspace store delegated; persisted JSON byte-identical).
  • Component extractions, markup verified byte-identical: chatterbox modal 750→240, left sidebar 548→212, git-diff panel 544→173, recipe modal 526→126.

Docs & config

  • CONTEXT.md seeds the repo's domain language. README/AGENTS.md corrected (stale pi-runtime paths, removed 3090, Zod→Effect Schema, dead CLI/voice refs).
  • depcheck config hoisted to .depcheckrc.json, jscpd thresholds aligned at the stricter bar (closes Hoist duplicated per-package cleanup tool configs #146); PROGRESS.md scratch removed.

Deliberate skips (rationale in the ledger — please don't re-request blind)

  • SSE keepalive unification (chat path is intentionally different: immediate first byte, byte-aligned frames).
  • GET /runtime/<backend> info-path unification (two discovery mechanisms can disagree; needs design + live verification).
  • Effect-ifying setActiveRecipe (the machinery keeping models alive; not an autonomous-hours change).
  • landing-page vs marketing-page near-total duplication — both are routed; consolidation is a pending product decision.

Validation

Full npm run check (contracts, structure, frontend quality incl. build, controller checks) and npm run test:integration (117 controller + 236 frontend regression) green at head. Every push ran the pre-push quality gate.

⚠️ Post-merge: desktop rebuild owed per AGENTS.md (frontend changes shipped).

🤖 Generated with Claude Code

0xSero and others added 30 commits July 12, 2026 18:07
The check:contracts and check:structure gates only ran when someone
remembered npm run check locally — three contributors independently hit
stale gate failures. Also prunes the validator's reference to the
removed shared/contracts/environments.ts and corrects AGENTS.md's
test-runner note (tsx --test is long gone).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- frontend depcheck ignore-list moves from a 300-char inline --ignores
  flag to .depcheckrc.json, the same mechanism controller already uses
- controller jscpd minTokens 400 -> 200, matching frontend (0 clones at
  the stricter threshold, so the alignment is free)
- delete PROGRESS.md: a session work-log snapshot duplicating git
  history; docs/ carries the durable design notes

Closes #146.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n root check

tests/frontend/e2e ran node:test module regressions, not end-to-end
tests — the name promised browser coverage that doesn't exist. Scripts,
CI step, README, and AGENTS.md now say what actually runs. Root
check:frontend additionally runs the frontend unit suites; previously
the root gate ran controller tests but never frontend's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The feature-side copy silently omitted cwd/provider/archived/archivedAt
fields the /api/agent/sessions/all route actually returns; the route
re-declared the shape locally. One definition in shared/agent extends
SessionSummary where it lives.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me/:backend/upgrade

Five copy-paste handlers (differing only in a backend literal) become
one parameterized route validated against RUNTIME_JOB_BACKENDS. URLs
are unchanged for existing callers; sglang/llamacpp/cuda/rocm now honor
targetId/version/prefer_bundled and receive runningProcess exactly like
the generic /runtime/jobs path, and mlx gains the same endpoint. The
frontend mirror collapses five upgrade methods into upgradeRuntime()
and drops the RuntimeCommandPayload type whose command/args fields the
controller has rejected since the security hardening.

Closes #145.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Runner seam

Three independent ps parsers (listProcesses, buildProcessTree, and
process-manager's listProcessTable) each ran and parsed their own ps
invocation with their own regex — and only one sat behind the
injectable ProcessRunner seam, so the other two were untestable.
listProcessInventory() returns the superset row (pid/ppid/stat/
command/args) and all three derive from it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tatus union

The status enum was 'idle | starting | running | loading | done | string'
— the string arm voided type checking entirely, 'done' was a tool-block
status that leaked into the session union, and session-index re-derived
'is working' from raw string comparisons that would silently misclassify
any new status as running. settleTurn/settleTurnFinalizingTools replace
five hand-rolled copies of the idle-settle transform (engine abort,
failed-turn, agent_end, runtime poll, runtime-idle); SessionTab.status
now shares the tightened union (persistence already coerces hydrated
tabs to idle).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lder into their specs

backend-builder advertised itself as engine-agnostic while carrying the
vLLM extra-args allowlist filter, the vLLM Docker JIT wrapper, and the
llama.cpp binary resolution/serialization rules. Those now live in
specs/vllm-spec.ts and specs/llamacpp-spec.ts where the EngineSpec
docstring says they belong; backend-builder keeps the generic
serialization seam (appendSerializedArguments + ExtraArgumentSerializer)
and the shared docker-run shape. Adding an engine no longer means
editing the shared builder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- AGENTS.md pointed at frontend/src/features/agent/pi-runtime*.ts; the
  runtime moved to services/agent-runtime/src/ months ago
- the RTX 3090 left the remote box in June
- controller README claimed Zod config validation (it's Effect Schema)
  and a CLI consumer (cli/ was deleted)
- frontend README diagrammed /api/voice/* (voice feature removed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/v1/chat/completions only had an invalid-JSON assertion; the actual
proxy behavior (upstream forwarding, SSE pass-through with the
keepalive-first-byte contract, and the model_not_running 503 gate for
managed recipes) was untested. Three tests against a stub upstream now
pin all of it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed stages

The 220-line straight-line handler becomes parseChatBody /
resolveChatUpstream / gateOnRunningModel / normalizeCompletionChoices
closure functions plus a ~90-line dispatch, with behavior pinned by the
new chat-proxy-forwarding tests. Also: malformed JSON on the recipe
CRUD routes now 400s via parseJsonObjectBody instead of escaping as a
500 (ctx.req.json() threw outside the try).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
750-line modal becomes a 240-line composition over three verbatim-moved
sections (runtime overview, voice creator, preview player); non-view
helpers join the existing chatterbox-voice-model.ts per the model/view
split.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
548-line shell sidebar becomes a 212-line composition; markup verified
byte-identical (className/aria/role multiset diff) across the move.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
routes.ts carried recipe CRUD, launch lifecycle, model downloads, and
the runtime-management surface in one 387-line file. It becomes a
12-line aggregator over recipe-routes / lifecycle-routes /
download-routes / runtime-routes, with the shared observed-process
closure extracted to a factory. Handler bodies verbatim; registration
order preserved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One term per concept, grounded in current file paths — recipes,
engines/specs, runtime targets, launch-state vs process-scan vs failure
budget, the chat proxy stages, session/turn/pane vocabulary, and the
contracts/gates conventions. Future reviews and agents should use these
names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sections

544-line panel becomes a 173-line container; DiffViewMode alias replaces
a union repeated six times across props; pairDiffLines joins the model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ry, footer

526-line modal becomes a 126-line view over useRecipeModalModel (hook
order preserved), pure source/format helpers, and two section views.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ToolSelection wire shape was known in two modules — tools/ owned
the live selection while workspace/store.ts hand-rolled its
serialization (and wrote promptTemplates past its own type via spread).
selection-persistence.ts is now the single owner; persisted JSON is
byte-identical and PersistedSessionMeta's type is honest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oad-state sections

501-line modal becomes a 263-line container; response schema and
external-open helpers join a google-account-model per the sibling
convention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… use-setup

512-line hook becomes 309 lines over setup-load.ts and
setup-actions.ts (verbatim moves; hook order unchanged). Completed
after the extraction agent was cut off mid-verification; all gates
re-run green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…feature, drop marketing clone

features/marketing was a ~90% clone of the newer features/landing-page
(same scaffolding, nav, screenshot frames). The unique content — the
agents DLTL setup page — moves into landing-page/agents-page.tsx reusing
the landing nav/frames/styles (agent CSS + responsive rules ported);
/download now redirects to /landing; features/marketing is deleted.
Also fixes two stale strings in DocsPage (test:e2e rename, dead CLI ref).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@0xSero 0xSero merged commit 404166b into main Jul 13, 2026
6 of 7 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.65.3 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hoist duplicated per-package cleanup tool configs Collapse redundant runtime upgrade routes into /runtime/jobs

1 participant