Commit Graph

138 Commits

Author SHA1 Message Date
Offending Commit
af83be0a32 docs(claude): make CLAUDE.md a shim that imports AGENTS.md
CLAUDE.md was a full, drifting duplicate of AGENTS.md. Replace it with a
one-line @AGENTS.md import so AGENTS.md is the single source of truth for
agent context. Removed content was a stale subset (old openconcho:config
key, older rules description) — AGENTS.md already has the current version.

Type docs → no version bump.
2026-05-29 11:39:38 -05:00
Offending Commit
8f8a64c984 Merge pull request #48 from offendingcommit/docs/refresh-agents-readme
docs: refresh AGENTS.md + README for v0.13.0 accuracy
2026-05-29 11:38:25 -05:00
Offending Commit
ad2d131ae4 docs: refresh AGENTS.md + README for v0.13.0 accuracy
- Correct localStorage key (openconcho:instances, not :config) in both
- AGENTS.md: note local husky pre-commit/pre-push gates
- README: fix prerequisites (Node >=22, pnpm 10)
- README: add shipped features (fleet, seed kits, multi-instance, dream
  viewer, dialectic playground, peer display names, demo mode)
- README: add .rpm to downloads + a Docker/Compose quick-start section
2026-05-29 11:37:03 -05:00
Offending Commit
e3190c0bd7 ci(docker): simplify publish to match working repo pattern
Revert the over-engineered linking attempts (provenance: false,
index annotations, dispatch tag input, Dockerfile source LABEL). Our
working repos (e.g. offendingcommit/infra) link GHCR packages with the
plain metadata-action labels + GITHUB_TOKEN push — none of the extras
helped or were needed. Match that.

Package<->repo linking is handled by the one-time Connect Repository
step in package settings.

Type ci → no version bump.
2026-05-29 11:27:58 -05:00
Offending Commit
3a22f8e9c8 Merge pull request #46 from offendingcommit/build/dockerfile-source-label
build(docker): bake image source label for GHCR repo linking
2026-05-29 11:08:04 -05:00
Offending Commit
e5e930d381 build(docker): bake org.opencontainers.image.source into the image
The canonical, build-tool-independent way GHCR links a container package
to its repo is a Dockerfile LABEL baked into the image config — not
buildx/metadata-action annotations. Add it so freshly-created packages
auto-connect.

Note: GHCR evaluates the source at package CREATION, so this links new
packages; an already-orphaned package needs a one-time manual connect
(or delete + re-publish) regardless.

Type build → no version bump.
2026-05-29 11:05:30 -05:00
Offending Commit
7354879596 Merge pull request #44 from offendingcommit/ci/ghcr-repo-link
ci(docker): link GHCR package to repo via index annotation
2026-05-29 10:43:35 -05:00
Offending Commit
5bd2e8a1f0 Merge branch 'main' into ci/ghcr-repo-link 2026-05-29 10:43:25 -05:00
Offending Commit
526c45d9ce ci(docker): annotate image index so GHCR links the package to the repo
The publish step passed labels but not annotations, so
org.opencontainers.image.source landed only on per-platform configs, not
the multi-arch index. GHCR reads the source from the index annotation to
auto-link a package to its repo, so the package stayed orphaned.

- Set DOCKER_METADATA_ANNOTATIONS_LEVELS=index + pass annotations to the
  build, putting source/url/revision on the index.
- provenance: false keeps the pushed artifact a clean multi-arch index.
- workflow_dispatch now takes a 'tag' input to (re)publish a specific
  version; tags derived from the ref so dispatch and release both work.

Type ci → no version bump; republish v0.13.0 via dispatch.
2026-05-29 10:42:58 -05:00
Offending Commit
ec1a1b3665 Merge pull request #33 from offendingcommit/dependabot/github_actions/actions/checkout-6
chore(ci)(deps): bump actions/checkout from 4 to 6
2026-05-29 10:31:57 -05:00
github-actions[bot]
801555222e chore(release): 0.13.0 [skip ci]
# [0.13.0](https://github.com/offendingcommit/openconcho/compare/v0.12.1...v0.13.0) (2026-05-28)

### Features

* **docker:** full self-hosted Compose support ([282ba1b](282ba1b76c))
* **web:** add Fleet dashboard view for cross-instance observability ([12712bb](12712bb0b0))
* **web:** configurable peer display name ([3de6832](3de6832a5d))
2026-05-28 22:10:34 +00:00
Offending Commit
04104d1f92 Merge pull request #43 from offendingcommit/feat/docker-compose-support
feat(docker): full self-hosted Compose support
2026-05-28 17:09:23 -05:00
Offending Commit
ab69b0045f Merge pull request #42 from offendingcommit/feat/fleet-dashboard
feat(web): add Fleet dashboard for cross-instance observability
2026-05-28 17:08:35 -05:00
Offending Commit
472b1405a6 Merge pull request #41 from offendingcommit/feat/peer-display-name
feat(web): configurable peer display name
2026-05-28 17:07:50 -05:00
Offending Commit
282ba1b76c feat(docker): full self-hosted Compose support
Make the web image drop-in for a Honcho docker-compose stack:
- nginx reverse-proxies /v3 and /health to $HONCHO_UPSTREAM (variable +
  Docker resolver so it starts even before the upstream resolves), giving
  the SPA a same-origin path to Honcho with no browser CORS.
- Runtime config: an entrypoint writes config.js from
  OPENCONCHO_DEFAULT_HONCHO_URL, so one prebuilt image targets any backend
  ("same-origin" | absolute URL | empty). SPA seeds a first-run default
  instance from it (additive; no-op in dev/desktop).
- docker-compose.yml example service + GHCR multi-arch publish workflow on
  release.
- nginx.conf -> envsubst template; docs rewritten.

Closes #21. Closes #31.
2026-05-28 16:06:03 -05:00
Agents
37eb9bdf59 test(web): add E2E for Fleet route nav + per-instance row render
Two focused Playwright tests, mirroring the existing sidebar.spec
pattern (no backend dependency — instances point at unreachable ports
and we only assert on rendered names + row count, not health):

- Fleet link in the sidebar navigates to /fleet
- /fleet renders one row per configured instance under the table role

Also adds a Fleet link assertion to the existing sidebar.spec so the
nav entry is covered on the dashboard route alongside the other top
links. Both new tests run under the existing `pnpm test:e2e` (not
gated in CI by design — matches the current Compare/Dashboard E2E
posture).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:57:17 -05:00
Agents
e90d20893d docs(fleet): add Fleet dashboard screenshots
Adds dark, light, and mixed-health screenshots used in the PR description.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:57:17 -05:00
Agents
12712bb0b0 feat(web): add Fleet dashboard view for cross-instance observability
Adds a new /fleet route that shows a fleet-wide overview of all
configured Honcho instances. Each row renders per-instance metrics
(workspace count, total conclusions, queue activity, last seen, health)
by fanning out scoped fetches via createScopedClient, and aggregates
into top-level metric cards.

Reuses the Phase 2 scoped-client pattern. Extends compareQueries.ts
with useScopedQueueStatus and useScopedConclusionsCount, plus option
builders so useQueries can fan out per-workspace requests inside
FleetRow without duplicating query logic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:57:17 -05:00
Offending Commit
3de6832a5d feat(web): configurable peer display name
Human peers surface as raw ids (WhatsApp `…-lid`, UUIDs). Read an
optional `display_name` from peer metadata and prefer it over the id in
the peer header and breadcrumb, with the raw id kept as a sub-caption.
An inline edit on the header writes `display_name` via useUpdatePeer
(merging existing metadata); blank clears it. Falls back to the id when
unset.

Closes #32.
2026-05-28 15:56:42 -05:00
github-actions[bot]
dd2edbae99 chore(release): 0.12.1 [skip ci]
## [0.12.1](https://github.com/offendingcommit/openconcho/compare/v0.12.0...v0.12.1) (2026-05-28)

### Bug Fixes

* **ci:** trigger release build on release publish, not tag push ([52a7f09](52a7f09ce6))
2026-05-28 20:33:28 +00:00
Offending Commit
afcece29c5 Merge pull request #40 from offendingcommit/fix/release-trigger-on-published
fix(ci): trigger release build on release publish, not tag push
2026-05-28 15:32:20 -05:00
Offending Commit
52a7f09ce6 fix(ci): trigger release build on release publish, not tag push
semantic-release creates the tag via the GitHub Releases API
(@semantic-release/github). API-created tags don't emit the
refs/tags/* push event that 'on: push: tags' listens for, so the
artifact build never auto-ran — every release so far was built by
manual workflow_dispatch.

The PAT-published release does fire 'release: published', so trigger on
that. workflow_dispatch stays as a manual fallback.
2026-05-28 15:23:38 -05:00
github-actions[bot]
5fa894dcd7 chore(release): 0.12.0 [skip ci]
# [0.12.0](https://github.com/offendingcommit/openconcho/compare/v0.11.0...v0.12.0) (2026-05-28)

### Features

* **desktop:** auto-discover Honcho instances on localhost ([#1](https://github.com/offendingcommit/openconcho/issues/1)) ([7355884](7355884051))
* **web:** add dialectic reasoning playground ([2340e65](2340e65028))
* **web:** add Dream Output Viewer ([f318555](f318555c82))
* **web:** add live dream progress panel with adaptive polling ([17f8a5a](17f8a5a7bf))
* **web:** add Peer Card Seed Kits ([650bfd7](650bfd7b28))
* **web:** show sidebar last updated status ([7cf94aa](7cf94aa03f))
2026-05-28 19:27:43 +00:00
Offending Commit
0d86a96560 Merge pull request #28 from offendingcommit/feat/dialectic-playground
feat(web): add dialectic reasoning playground
2026-05-28 14:26:39 -05:00
Offending Commit
f52961a112 Merge pull request #27 from offendingcommit/feat/dream-viewer
feat(web): add dream output viewer
2026-05-28 14:25:45 -05:00
Offending Commit
a17b5776be Merge pull request #20 from offendingcommit/feat/peer-card-seed-kits
feat(web): add peer card seed kits
2026-05-28 14:24:48 -05:00
Offending Commit
7d2f7209ea Merge pull request #29 from offendingcommit/feat/live-dream-progress
feat(web): add live dream progress panel with adaptive polling
2026-05-28 14:23:55 -05:00
Offending Commit
aa46d47fc8 Merge pull request #30 from offendingcommit/feat/desktop-auto-discover
feat(desktop): auto-discover Honcho instances on localhost
2026-05-28 14:23:49 -05:00
Offending Commit
972fd8323a Merge pull request #18 from offendingcommit/feat/sidebar-last-updated
feat(web): show sidebar last-updated status
2026-05-28 14:22:54 -05:00
Offending Commit
edc498de7b Merge pull request #26 from offendingcommit/chore/vitest-coverage
test(web): add v8 coverage with truthful baseline floor
2026-05-28 14:22:21 -05:00
github-actions[bot]
8e16dc4f78 chore(release): 0.11.0 [skip ci]
# [0.11.0](https://github.com/offendingcommit/openconcho/compare/v0.10.0...v0.11.0) (2026-05-28)

### Bug Fixes

* harden token and URL handling ([5cfbae6](5cfbae6248))

### Features

* **docker:** add containerized web build with CORS guidance ([cfe07f1](cfe07f1900))
2026-05-28 19:21:59 +00:00
Offending Commit
94c423522a test(web): add v8 coverage with truthful baseline floor
Adds @vitest/coverage-v8 (catalog-pinned), a test:coverage script wired
through turbo (inputs + coverage/** output), and coverage thresholds set
to a floor measured on main (lines 18 / funcs 10 / branches 10 / stmts
17 against current 19.3/11.4/11.7/18.9). Ratchet upward as tests grow.

Adapts the coverage config from @BenSheridanEdwards's fork; the multi-job
CI fan-out from that branch was intentionally left out.

Co-authored-by: Ben Sheridan-Edwards <BenSheridanEdwards@users.noreply.github.com>
2026-05-28 14:21:42 -05:00
dependabot[bot]
793ed230db chore(ci)(deps): bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 19:21:19 +00:00
Offending Commit
ac20ab6271 Merge pull request #22 from offendingcommit/fix/web-security-hardening
fix: harden token and URL transport security
2026-05-28 14:20:51 -05:00
Offending Commit
62a5085202 Merge pull request #24 from offendingcommit/chore/local-prepush-gates
chore(hooks): local pre-push gate + secret scan
2026-05-28 14:20:45 -05:00
Offending Commit
a26b028c5c Merge pull request #25 from offendingcommit/chore/dependabot
ci(deps): add grouped Dependabot config
2026-05-28 14:20:38 -05:00
Offending Commit
a33891982b Merge pull request #23 from offendingcommit/feat/docker-web
feat(docker): containerized web build + CORS guidance
2026-05-28 14:20:32 -05:00
github-actions[bot]
7a478ebbc8 chore(release): 0.10.0 [skip ci]
# [0.10.0](https://github.com/offendingcommit/openconcho/compare/v0.9.0...v0.10.0) (2026-05-28)

### Features

* **api:** add scoped multi-instance query client ([de8db4b](de8db4b7aa))
2026-05-28 19:20:20 +00:00
Offending Commit
5d71d1e7c5 Merge pull request #19 from offendingcommit/feat/scoped-client-foundation
feat(api): add scoped multi-instance query client
2026-05-28 14:19:22 -05:00
Ben Sheridan-Edwards
7355884051 feat(desktop): auto-discover Honcho instances on localhost (#1)
* feat(desktop): auto-discover Honcho instances on localhost

First-launch and on-demand discovery of running Honcho instances on
127.0.0.1:8000-8100. Desktop-only — the browser can't port-scan due to
CORS, so the scan runs in the Tauri Rust shell.

- New Rust command `discover_honcho_instances(start_port?, end_port?)`
  in src-tauri/src/discover.rs: parallel TCP probe of each port with
  150ms connect timeout + 250ms total request budget, looking for a
  /health endpoint returning `{"status":"ok"}`.
- New TS helper `discoverHonchoInstances()` in src/lib/discovery.ts:
  detects Tauri runtime; web build degrades to an empty result.
- `suggestNameForInstance()` fetches the first workspace and derives a
  friendly name from its id ("neo-personal" -> "Neo"). Used to seed the
  Name field for each discovered instance.
- `DiscoveredInstances` component: list of found instances with
  editable suggested names + per-row checkbox + "Add N instances"
  button. Rows are pre-checked by default and filter out already-
  configured baseUrls.
- Wired into `InstancesManager`:
  - First launch (no instances): renders above the connection-type
    chooser with autoRun=true. User sees results immediately.
  - With instances: adds a "Discover instances" button to the list
    view that opens the discovery flow on demand.
  - Both paths gate on `isTauri()`; the web build keeps its existing
    behaviour unchanged.

Adds tokio (with net + io-util + time + rt + macros) and futures to
the Tauri shell to get async TCP + join_all.

Tests:
- deriveNameFromWorkspaceId handles hyphenated, multi-segment, and
  no-hyphen ids

* test(desktop): add probe tests including live Hermes stack integration

- rejects_inverted_port_range
- ignores_ports_with_no_listener
- finds_live_hermes_stacks (#[ignore]d; opt-in with --ignored)

The ignored test exercises discover_honcho_instances against ports
8000-8010, expecting exactly [8001, 8002, 8003, 8004, 8005]. Verified
locally — the probe finds all 5 stacks in <10ms.

---------

Co-authored-by: Agents <agents@Jarviss-Mac-mini.local>
2026-05-28 14:09:45 -05:00
Agents
247ab846e9 docs(web): link panel to plastic-labs/honcho#724
Filed the upstream feature request asking /queue/status to surface
per-work-unit observer/observed, specialist phase, and token telemetry.
Panel now links to the concrete tracking issue instead of a pre-filled
new-issue form. Re-captured the showcase screenshots so the visual
state matches.
2026-05-28 14:08:57 -05:00
Agents
5f61769adc docs(web): add Dream Progress screenshots + capture script
Wires up the DEV-only /dream-progress showcase to a Playwright script
that captures idle/active/stalled variants for documentation. Also
regenerates routeTree.gen.ts to include the new queue + showcase routes
and folds in Biome formatter fixes.

Run `node scripts/screenshot-dream-progress.mjs` from packages/web with
the dev server up to refresh the images.
2026-05-28 14:08:57 -05:00
Agents
93c117b16b test(web): cover queue polling and stale-dream detection
- pickQueueRefetchInterval picks 2.5s when work is active, 10s otherwise
- useStaleQueueDetection only flags after 30 min without forward progress
- stall anchor resets when completed advances or all work finishes
2026-05-28 14:08:56 -05:00
Agents
17f8a5a7bf feat(web): add live dream progress panel with adaptive polling
Watching dreams was a 5-15min black box. Now a dedicated
/workspaces/:id/queue route polls /v3/workspaces/:id/queue/status
every 2.5s while work is in-flight (10s when idle) and surfaces a
warning when in-progress work hasn't advanced the completed count
for >30 minutes.

The Honcho API only exposes aggregate counts (no observer/observed
pair, specialist phase, or token telemetry per work-unit), so the
panel links out to an upstream issue for those.

- queries: adaptive refetchInterval via TanStack Query callback form
- hooks/useStaleQueueDetection: client-side stall detection
- routes/workspaces_.\$workspaceId_.queue: dedicated live view
- routes/_dev.dream-progress: DEV-only showcase for screenshots
- WorkspaceDetail: new "Queue & dreams" nav card
2026-05-28 14:08:56 -05:00
Ben Sheridan Edwards
2340e65028 feat(web): add dialectic reasoning playground
Lets users fire one query at every Honcho reasoning level (minimal / low /
medium / high / max) in parallel and compare answers + latency side-by-side
in a 5-column grid.

- New route: /workspaces/:ws/peers/:peer/playground
- New component: DialecticPlayground with per-column state, level checkboxes
  to skip expensive levels, and a single Run button that fans out via
  Promise.all
- Extends useChat() to accept an optional reasoning_level parameter (was
  hardcoded to "low")
- Adds a Playground button next to Chat on the peer detail page
- Tests cover the parallel fan-out (peak concurrency = 5, no serial
  awaiting) and per-column latency measurement
- Screenshot Playwright spec (idle / mid-flight / settled) drives the
  images in docs/screenshots/ — regen with PLAYWRIGHT_BASE_URL=... pnpm
  exec playwright test e2e/playground.screenshots.spec.ts
2026-05-28 14:08:08 -05:00
Agents
e549200f5d test(web): add playwright e2e for Dreams + docs screenshots
- packages/web/e2e/dreams.spec.ts: 4 tests covering sidebar entry,
  heading/breadcrumb resolution, mocked-API clustering into rows with
  count chips, and the premise-tree expansion path. Uses a function
  matcher for context.route so the trailing ?page=&page_size= query
  string doesn't break a glob.
- docs/screenshots/: dark + light mode list and expanded-detail PNGs
  captured at 2880x1800 (retina) via playwright against the dev
  server with a tiny mock Honcho.
- DreamList.tsx: add a literal space to CountChip's label fragment so
  the rendered text reads "3 explicit" instead of "3explicit" (gap-1
  styles the visual layout but doesn't add a text-node space). Better
  for screen readers, copy/paste, and assertion via toContainText.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:07:22 -05:00
Agents
f318555c82 feat(web): add Dream Output Viewer
Dreams are currently a black box — to benchmark Tier L models on dreamer
induction quality we need to see what each model produced. This adds a
workspace-scoped /dreams route that surfaces every dream run as a
group of conclusions split into explicit / deductive / inductive
columns, with click-to-expand premise trees.

What's here:

- `lib/dreams.ts`: pure helpers. `clusterConclusionsIntoDreams` groups a
  raw conclusions list into per-pair bursts using a configurable time
  window (default 60s). `expandPremiseTree` walks `reasoning_tree` first
  and falls back to a flat `premises` ID list, with cycle detection and
  a depth cap. Defines an `ExtendedConclusion` type that augments the
  generated schema with `conclusion_type`, `premises`, and
  `reasoning_tree` — Honcho's migration f1a2b3c4d5e6 added those
  columns but `schema.d.ts` doesn't expose them yet, so the UI degrades
  gracefully (unknown types fall into "explicit").

- `api/queries.ts`: new `useDreams` hook that paginates the conclusions
  list endpoint up to a configurable cap (default 400) and hands the
  raw list to the UI for clustering. New `dreams` query key.

- `components/dreams/`:
  - `DreamList.tsx` — route entry. Shows recent dreams as rows with
    timestamp, observer→observed pair, and per-type counts. Selecting
    a row expands an inline detail panel above the list.
  - `DreamDetail.tsx` — three-column view (explicit / deductive /
    inductive). Each inductive conclusion has a "Show premises" button
    that expands the reasoning chain.
  - `PremiseTree.tsx` — recursive premise renderer with type badges,
    cycle indicator, and graceful handling of premises that fall
    outside the loaded page.

- Routing: `routes/workspaces_.$workspaceId_.dreams.tsx` registers the
  page; routeTree.gen.ts regenerated.

- Sidebar: new "Dreams" entry between Conclusions and Webhooks
  (MoonStar icon to distinguish from the dark-mode Moon).

- Breadcrumb: "dreams" added to SECTION_LABELS so the trail resolves.

Tests (vitest, 14 new):
- clustering: empty input; same-pair burst within window; gap exceeds
  threshold → split; different pairs don't merge even with overlapping
  timestamps; custom gap window; newest-first ordering; counts default
  unknown types to explicit.
- premise tree: empty children for no premises; flat list → direct
  children; multi-level reasoning_tree recursion; missing premise
  flagged (not in loaded page); cycle detection halts recursion;
  maxDepth cap; reasoning_tree preferred over flat premises.

Verified manually in the preview: route mounts, sidebar/breadcrumb
resolve, error path renders cleanly, typecheck + lint + dream tests
all clean. The unrelated `app.test.tsx` failure is pre-existing on
main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:06:46 -05:00
BenSheridanEdwards
e809409fa3 ci(deps): add grouped Dependabot config
Weekly npm (pnpm workspace), cargo (Tauri shell), and github-actions
updates, grouped by family (TanStack, Tauri, React, test stack, build
tooling, semantic-release, commitlint) to keep related bumps in one PR.

Co-authored-by: Ben Sheridan-Edwards <BenSheridanEdwards@users.noreply.github.com>
2026-05-28 14:02:08 -05:00
BenSheridanEdwards
86bb9d6be0 chore(hooks): pre-push gate, secret scan, pr:evidence drafter
Phase A of the quality-gate rollout — local + pre-push gates that stop
slop before it leaves the laptop. Preventative controls, per the
architect playbook.

- .husky/pre-commit — adds scripts/secret-scan.sh as the first check
  before the existing Biome format/lint. Blocks the commit when a
  likely secret is found in staged additions. Existing Biome behaviour
  is preserved.
- .husky/pre-push (new) — runs `pnpm check` (lint + typecheck + test)
  before the branch leaves the laptop. Mirrors the `check` job in
  .github/workflows/ci.yml so PR-blocking issues surface locally first.
  Bypassable for genuine emergencies with `git push --no-verify`.
- scripts/secret-scan.sh (new) — regex scan over staged additions for
  the common accidents: AWS keys, Anthropic/OpenAI/GitHub/Slack/Google/
  Stripe tokens, JWTs, PEM private key blocks, hardcoded password
  literals. Validated against synthetic leaks of each type. No external
  tool dependency — pure bash + grep, runs in <100ms typical.
- scripts/pr-evidence.sh (new) — drafts a PR_BODY.md from the diff vs
  origin/main: file lists (added/modified/deleted), commit summaries,
  and the QA checklist. Flags screenshots as REQUIRED when the diff
  touches packages/web/src/{components,routes} or packages/desktop.
  Wired as `pnpm pr:evidence` so it runs from anywhere in the
  workspace.
- .gitignore — adds PR_BODY.md so drafts don't get committed by
  accident.

Pre-commit stays fast (<2s typical). Heavy checks (typecheck, full
test run) live in pre-push.
2026-05-28 14:01:20 -05:00
Offending Commit
cfe07f1900 feat(docker): add containerized web build with CORS guidance
Multi-stage Dockerfile (node:22-alpine + pnpm build -> nginx-unprivileged
serve) producing a non-root image that runs under read-only fs + cap_drop
ALL. nginx.conf does SPA-fallback routing, /healthz, immutable asset cache,
and gzip, plus an opt-in same-origin reverse-proxy block.

docs/docker.md documents build/run and the two ways to handle browser CORS
on the web build (configure Honcho's CORSMiddleware, or the nginx proxy).

The Dockerfile and nginx.conf are adapted from @zmarakjanbangash's fork.

Co-authored-by: zmarakjanbangash <zmarakjanbangash@users.noreply.github.com>
2026-05-28 13:59:47 -05:00