feat(ensemble): UI workflow + OpenRouter backend + explicit chapter selection#113
Open
kostadis wants to merge 3 commits into
Open
feat(ensemble): UI workflow + OpenRouter backend + explicit chapter selection#113kostadis wants to merge 3 commits into
kostadis wants to merge 3 commits into
Conversation
Sister doctrine to the mneme constitution, governing CG's LLM rendering pipeline. Nine principles, each naming the anti-pattern it kills: I. Disk is Truth, the Model is a Draft (Optimistic Lies) II. The Human Checkpoint is Non-Negotiable (Error Compounding) III. Retrieval and Render are Separated (Renderer Scope Decisions) IV. Verbatim is Sacred (Hallucinated Dialogue) V. One Seam per Boundary (Fragmented Integration) VI. CLI is the Engine, UI is a Face (Split-Brain) VII. Extract Once, Synthesize Deliberately (Depth Regression) VIII. State is Discoverable (Opacity / Tribal State) IX. The UI Mechanizes; Claude Converses (The Walled Garden) Plus Architecture is Destiny (token/precision economics), Authority & the Human Checkpoint (Spec Kit plans are drafts), and Governance (I & II outrank all; semver amendments). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…election Turn the ensemble grounding-doc CLI workflow (docs/cli/ensemble_workflow.md) into a stepped UI page (Setup → Extract → Bundle → Synthesize), add OpenRouter as a per-stage LLM backend through the single campaignlib seam, and make chapter selection explicit. The existing Anthropic /grounding path is untouched. Built via the Spec Kit flow (specs/001-ensemble-workflow-ui: spec/plan/research/ tasks/contracts/quickstart). Backend / seam (Constitution V): - campaignlib/api: _OpenRouterClient branch in make_client(backend="openrouter"); reasoning-off mapping; _require_nonempty guards stream_api/call_api against empty model output. OpenRouter is constructed only inside campaignlib/api. - Uniform add_backend_args / client_from_args; --backend/--endpoint added to the four synthesis scripts. Default backend=anthropic is byte-identical to before. UI (Constitution VI/IX): - New /ensemble route + nav entry; EnsembleWorkflow shell with disk-derived status; Setup, Extract, Bundle (scope + alias gates), Synthesize (diff-before- promote). server/routers/ensemble.py shells out to the CLI and exposes disk-derived status; it issues no retrieval/render calls. Chapter picker + Constitution Principle X (operator-elevated): - "Selection is Explicit; There is No Silent 'All'" added to the constitution (v1.1.0 -> 1.2.0, MINOR). New ChapterPicker.vue (Resolve glob, Select all / none / only, natural sort, extracted/pending badges). - ensemble_batch.py --chapters is now nargs="+" (unions globs/paths); the engine gains the capability, the UI mechanizes it. - chapters_selected stores the literal chosen set; an empty selection is refused (no glob fallback) by GET /run/extract and the disabled Run button. Tests: +new suites (openrouter seam, ensemble status/gates/chapters, batch nargs). Full suite 940 passed; isolation guard green; frontend builds clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ort + durable record Implements spec 002-ensemble-run-observability (T001–T032; T033 = manual QA pending): Engine / shared seam - atomic_write_text / atomic_write_json in campaignlib.util (FR-014): temp-then-rename so a SIGKILL never leaves a truncated merged.json or dossier at a resume-trusted path - subprocess_runner: classify_result(), extended _save_run_log with result field (T003/T004) - subprocess_runner: start_new_session=True + SIGTERM→wait(4 s)→SIGKILL process-group teardown on every exit path — normal, explicit abort, and disconnect (T020/T021) - subprocess_runner: emits `event: command` as first SSE event carrying the secret-free invocation string; `done` payload includes aborted flag on signal exit (T006/T022) - ensemble_merge + facts_to_state: atomic cache writes (T018/T019) Frontend - sse.ts: onCommand callback; onerror while running closes EventSource (no auto-restart) and transitions to aborted — a network drop is an implicit abort (T007/T025, I1) - useEnsembleRun: command state, aborted status, abort() method (T008/T024/T025) - RunCommandBar.vue: monospace copyable command box (T009) - EnsembleExtract/Bundle/Synthesize: RunCommandBar wired; Abort button while running; aborted/connection-lost labels; success vs failure color distinction (T010/T014/T015/T026) Tests (tests/test_subprocess_abort.py) - secret-safety + explicit-selection-faithfulness (T011/T012) - process-group kill on explicit abort and disconnect, child + grandchild (T027) - grace→force timing; aborted record written (T028) - atomic-write integrity under SIGKILL; lock released after abort (T029) - non-ensemble SSE route regression — group-killed on disconnect, no orphan (T031) - success and failure run records verified (T017) Docs: web_ui.md + ensemble_workflow.md updated with abort/reconnect/per-run-log notes (T030) Spec: specs/002-ensemble-run-observability/ — full artifact set committed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Turns the ensemble grounding-doc CLI workflow (
docs/cli/ensemble_workflow.md) into a stepped UI page (Setup → Extract → Bundle → Synthesize), adds OpenRouter as a per-stage LLM backend through the singlecampaignlibseam, and makes chapter selection explicit. The existing Anthropic/groundingpath is untouched.Built via the Spec Kit flow — see
specs/001-ensemble-workflow-ui/(spec, plan, research, tasks, contracts, quickstart).What's in it
Backend / seam (Constitution V — One Seam per Boundary)
campaignlib/api:_OpenRouterClientbranch inmake_client(backend="openrouter"); reasoning-off mapping;_require_nonemptyguardsstream_api/call_apiagainst empty model output. OpenRouter is constructed only insidecampaignlib/api.add_backend_args/client_from_args;--backend/--endpointadded to the four synthesis scripts. Defaultbackend=anthropicis byte-identical to before.UI (Constitution VI/IX — CLI is Engine, UI Mechanizes)
/ensembleroute + nav entry;EnsembleWorkflowshell with disk-derived status; Setup, Extract, Bundle (scope + alias gates), Synthesize (diff-before-promote).server/routers/ensemble.pyshells out to the CLI and exposes disk-derived status; it issues no retrieval/render calls.Chapter picker + new Constitution Principle X (operator-elevated)
ChapterPicker.vue: resolve glob, Select all / none / only, natural sort, per-chapterextracted/pendingbadges.ensemble_batch.py --chaptersis nownargs="+"(unions globs/paths) — the engine gains the capability, the UI mechanizes it.chapters_selectedstores the literal chosen set; an empty selection is refused (no glob fallback) byGET /run/extractand the disabled Run button.Testing
openai/dgxlibaren't installed in this env.Notes / follow-ups
T027(provenance stamping of backend+model into output artifacts) andT042(full live-env quickstart run) are deferred — tracked intasks.md.🤖 Generated with Claude Code