209 Commits

Author SHA1 Message Date
CIAgent c2158af6d3 chore(P06): clear checkpoint — milestone v0.9 complete
Release / release (push) Successful in 2m50s
CI / python (push) Successful in 2m8s
CI / node (push) Successful in 41s
---ci---
phase: 6
milestone: v0.9
status: complete
---/ci---
v0.8.6
2026-09-30 11:03:38 +00:00
CIAgent 0592c9993d merge: milestone/v0.9-payment-engine -> main (v0.9 complete — Payment Engine)
The v0.9 milestone: payment processing and subscription management
(REQ-F-018 activated as REQ-9-001..005 per D-074). The billing module
(ai_service/billing/ — PaymentProvider protocol with deterministic
mock + Stripe-compatible REST over the shared pool, the 7th D-027
store with 7 tables, the HMAC-SHA256 webhook core per D-077), the
seeded catalog + /v1/billing routes, the pricing page's runtime
conversion, posting entitlement enforcement with honest 402 upgrade
CTAs, and the full subscription lifecycle with a queryable audit
trail. Operator-mediated checkout at pilot (D-076); grants exactly-
once per session (G-303); webhook state resolved from local rows only
(G-302); consumption as a single conditional UPDATE (G-304). Tags
v0.8.0..v0.8.6 on the v0.8.x line; the tag lane built every release's
full asset matrix + registry image (D-064).

---ci---
phase: 6
milestone: v0.9
status: complete
requirements:
  covered: [REQ-9-001, REQ-9-002, REQ-9-003, REQ-9-004, REQ-9-005]
  partial: []
---/ci---
2026-09-30 11:03:33 +00:00
CIAgent f831839a90 decision(D-073): founder credential policy — retain, store securely, no rotation
CI / node (push) Successful in 50s
CI / python (push) Successful in 1m45s
CT 113 root password + the org runner registration token are retained for
future use per founder directive (rotation declined; supersedes the G-206
rotation request). Both live only in .ciagent/.env.secrets (gitignored,
0600 — verified the sole copies tree-wide). The live-host deploy key
(nc_ci_deploy -> root@10.0.0.105) is persistent per founder approval.
Release notes updated to match.

---ci---
phase: post-milestone
milestone: v0.8
status: complete
decision: D-073
---/ci---
2026-09-29 16:52:39 +00:00
CIAgent f0ad84fe74 chore(P06): clear checkpoint — milestone v0.8 complete
CI / node (push) Successful in 47s
CI / python (push) Successful in 1m44s
---ci---
phase: 6
milestone: v0.8
status: complete
---/ci---
2026-09-29 16:12:13 +00:00
CIAgent 1e6d035d6d docs(milestone): complete ship-anywhere
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
---ci---
phase: 6
milestone: v0.8
status: complete
---/ci---
2026-09-29 16:12:09 +00:00
CIAgent 1a88ab3199 merge: milestone/v0.8-ship-anywhere -> main (v0.8 complete — Ship Anywhere)
Release / release (push) Successful in 3m45s
CI / python (push) Successful in 1m52s
CI / node (push) Successful in 1m0s
The v0.8 milestone: installable on any Debian-based server via docker
(Gitea registry image, honest sandbox degrade), deb (amd64+arm64,
advisory postinst), and arch-aware binary — with release consistency
enforced by pre-commit hooks + Gitea Actions (3-runner fleet on CT 113,
machine-made releases with the full 8-asset matrix + registry image), the
CLI carrying the full suite (guide, channel-aware doctor), and the admin
runbook (deploy/README.md, evidence-backed recipes).

---ci---
phase: 6
milestone: v0.8
status: complete
requirements:
  covered: [REQ-8-001, REQ-8-002, REQ-8-003, REQ-8-004, REQ-8-005]
  partial: []
---/ci---
v0.7.6
2026-09-29 16:04:40 +00:00
CIAgent d35695e5fa chore(P06): clear checkpoint — milestone v0.7 complete
---ci---
phase: 6
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-001, REQ-7-002, REQ-7-003, REQ-7-004, REQ-7-005]
  partial: []
---/ci---
2026-09-27 10:30:12 +00:00
CIAgent ac65f3ab92 docs(milestone): complete test-harness-review
---ci---
phase: 6
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-001, REQ-7-002, REQ-7-003, REQ-7-004, REQ-7-005]
  partial: []
---/ci---
v0.6.6
2026-09-27 10:29:23 +00:00
CIAgent 1ba8a11189 chore(P06): checkpoint — audit stage
---ci---
phase: 6
milestone: v0.7
status: audit
---/ci---
2026-09-27 10:28:59 +00:00
CIAgent 4a6856711f fix(P06): final review — version literal to 0.6.5 + trailing newlines
Review verdict SHIP: purity gate PASS (22 commits: chore 8, verify 5,
docs 5, test 2, fix 1, decision 1 — zero feat:). P2-1 fixed: pyproject
+ package.json version 0.6.3 → 0.6.5 (the about-to-ship line),
reinstalled dist-info, version pins 3/3 green, ruff + mypy green.
P2-3 fixed: trailing newlines (eslint.config.mjs, helpers.ts).
P2-2 (session-sweep concurrency on shared hosts) recorded as post-hoc
note — not actionable this milestone.

---ci---
phase: 6
milestone: v0.7
status: review
---/ci---
2026-09-27 10:18:02 +00:00
CIAgent 9d120450da chore(P05): phase 5 complete — v0.6.5 shipped, release 908
---ci---
phase: 5
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-005]
  partial: []
---/ci---
2026-09-27 10:08:17 +00:00
CIAgent 9c8837eb45 verify(P05): MH-5a..5c evidenced — audit attribution corrected
Verifier four layers PASS: structural (production diffs annotation-only:
sandbox-agent Optional guard pre-existed, cursor retyping no behavior
change, protocol fixes align signatures with existing async impls),
behavioral (mypy Success 178 files; full 670 zero warnings; typecheck
9/9; build 248/248 SSR-verified; web 44; cli 63+1; fast 56.6s), security
(zero logic changes in production code), quality (34/34 suppressions
reasoned; 0 bare ignores; G-104 allowlist unchanged). 5-3 attribution
corrected: glob@10.5.0 is c8/test-exclude, not Storybook chain.

---ci---
phase: 5
milestone: v0.7
status: verify
---/ci---
v0.6.5
2026-09-27 10:08:07 +00:00
CIAgent dc00a4f8f5 chore(P05): type & dependency hardening — mypy + recharts 3 (REQ-7-005)
Wave 5-1 mypy adoption (D-058 relaxed-first): mypy 2.3.1, [tool.mypy]
check_untyped_defs + no_implicit_optional + warn_unused_ignores +
warn_redundant_casts + warn_unreachable, no overrides (every dep ships
py.typed), files = ai_service + scripts/sandbox-agent.py + tests (not
excluded). 215 errors → 0: ~140 fixed at source incl. genuine bugs found
by the gate (LLMProvider protocol async-generator shape, SessionStore
protocol sync/async mismatch, structured_reply genericity, get_args
migrations, sandbox-agent Optional guard honesty, proctor test arg-order,
dead ExecResult kwarg, 16 sqlmodel col() sites); 34 live suppressions
scoped-coded + reasoned. Original 27 type:ignore dispositioned: 12 dead
removed, 15 scoped (warn_unused_ignores self-eliminates the rest).
Wired: scripts/typecheck.sh + package.json + turbo task + root
ai:typecheck — pnpm typecheck now 5 tsc + mypy.

Wave 5-2 recharts 2.15.4 → 3.10.1 (D-049/D-059): one breaking class
(Tooltip formatter ValueType typing); 2 one-line inference fixes on the
2 chart files; no rollback needed (well inside the G-106 timebox).
Deprecated direct dep resolved; uuid@9 gone from the tree. Build 248/248
with chart SSR markers verified in exported employer + dashboard pages.

Wave 5-3 deprecated-transitive audit (G-109): 4 lockfile entries remain,
all dev-only, none actionable within NFR budget — glob@7.2.3 + inflight +
rimraf@3 via Storybook docgen chain (flat-cache@3); glob@10.5.0 via
c8→test-exclude (D-052-binding coverage tool — swapping it is out of
budget). Python: no EOL packages; zero-warning regime under
filterwarnings=error is the machine-checked proof.

Counts: 670 py / 44 web / 64 cli, zero warnings, G-104 allowlist still
exactly 2.

---ci---
phase: 5
milestone: v0.7
status: execute
---/ci---
2026-09-27 10:08:07 +00:00
CIAgent 06f049ba37 chore(P04): phase 4 complete — v0.6.4 shipped, release 907
---ci---
phase: 4
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-004]
  partial: []
---/ci---
2026-09-27 05:41:12 +00:00
CIAgent c242808137 verify(P04): MH-4a..4e evidenced — stale D-021 docstrings fixed
Verifier four layers PASS: structural (eslint config parses, RUF100 in
select, 80 noqa removed exactly), behavioral (lint 6/6, typecheck 8/8,
build 248/248, web 44, cli 63+1, pytest 670 zero warnings, app.version
0.6.3 live-probed, browser-voice suppression proven load-bearing both by
lint-fire probe and const-break test probe), security (E402 moves
circular-import-safe by grep; D-021 cut honest), quality (all suppressions
justified, comments verified against PROJECT.md). GAP-1 stale D-021
counterpart docstrings in corpus/telemetry.py + artifacts.py fixed
post-verify (historical-note form).

---ci---
phase: 4
milestone: v0.7
status: verify
---/ci---
v0.6.4
2026-09-27 05:41:03 +00:00
CIAgent 99da159866 chore(P04): lint & suppression hygiene — ESLint everywhere, 0 noqa, version single-source (REQ-7-004)
Wave 4-1 ESLint adoption (D-048): flat config at root — eslint 10 +
typescript-eslint (non-type-checked) + react-hooks CORE rules only
(compiler-era rules excluded with rationale: they fire on 6 shipped
components; restructuring shipped UI is out of NFR scope). lint scripts
in all 5 TS workspaces; pnpm lint now exercises 6/6. 20 violations fixed
(12 unused imports/vars, 2 NODE_TEST_CONTEXT renames, 1 type-alias fix).
5 orphaned eslint-disables resolved explicitly: 2 removed (deploy.ts
no-explicit-any orphan; avatar.tsx jsx-a11y — rule not in set, alt present);
3 kept load-bearing with justification comments (exhaustive-deps:
use-sandbox-session, build-surface, defense-session). 1 new suppression
(browser-voice.ts:65 prefer-const — TDZ-load-bearing, proven by a test that
breaks with const). --report-unused-disable-directives clean repo-wide.

Wave 4-2 suppression + hygiene: 80 noqa removed via RUF100 --fix (census
correction: 81→80 after P2's probe merge); 6 were LIVE (E402 ×4, E731 ×2)
— fixed at source (imports to top, lambdas → defs), not suppressed; RUF100
joined the select set. Dead exports removed: ai-scenarios.ts module,
NavItem/ThemeConfig, Spawn, MicControl + stories. D-021 corpus pin CUT
(contract dissolved with the deleted TS counterpart; would have skipped
silently forever). Version single-source (D-061): pyproject 0.6.3 =
last shipped tag, _resolve_version() importlib.metadata → tomllib
fallback (no second literal), FastAPI(version=__version__), 2 new pinning
tests. Stale comments fixed (board-client search copy, sandbox-terminal);
pricing + employers-index kept (verified still accurate). engines fields:
root node>=20 pnpm>=12.3.4, 5 workspaces node>=20.

Counts: 670 py (669 + 2 version pins − 1 dissolved pin) / 44 web / 64 cli,
zero warnings.

---ci---
phase: 4
milestone: v0.7
status: execute
---/ci---
2026-09-27 05:41:03 +00:00
CIAgent 85be77188f chore(P03): phase 3 complete — v0.6.3 shipped, release 903
---ci---
phase: 3
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-003]
  partial: []
---/ci---
2026-09-27 04:36:23 +00:00
CIAgent 93502f9daf verify(P03): MH-3a..3e evidenced — the one GAP fixed in-tree
Verifier four layers PASS: structural (filterwarnings letter-correct,
regex-escaped), behavioral (669 full + 620 fast, both zero-warning;
ignore-necessity 1:1 probe; SQLModel equivalence spot-checks), security
(every upload guard inside try; bare-raise preserves exception; PII
sentinel green), quality (G-107 behavior-preservation confirmed both
routes; AsyncKillableProxy.stop() G-101-additive). GAP-1 dead branch
removed post-verify, 25/25 identity tests re-run green.

---ci---
phase: 3
milestone: v0.7
status: verify
---/ci---
v0.6.3
2026-09-27 04:36:14 +00:00
CIAgent 4e662f1d03 fix(P03): warning elimination — zero-warning suite (REQ-7-003)
Wave 3-1 session.exec (14 sites): session.query() → select()/exec() per
SQLModel's non-deprecated API — marketplace/store.py ×12, identity/store.py
×2. Counts via select(func.count()).one() (int unwrap probe-verified);
rowid DESC tie-break preserved; incremental stmt.where() chains preserved.
207 consumer tests green = the equivalence proof.

Wave 3-2 resource cleanup: defense.py audio.close() post-read (before
guards); marketplace.py form.close() in try/finally spanning ALL guard
paths (manual request.form() means framework auto-close never runs — the
explicit close is load-bearing); sandbox-agent.py raw-socket close on
failed TLS/handshake (BaseException + bare raise — backoff logic
unchanged). 12 ResourceWarnings → 0, proven under -W error::ResourceWarning.

Wave 3-3 filterwarnings=error: exactly 2 module+message-scoped upstream
ignores (fastapi.testclient StarletteDeprecationWarning;
starlette.testclient anyio BlockingPortal DeprecationWarning) — 1:1
necessity probe-proven; asyncio_default_fixture_loop_scope pinned.
The policy flip caught a real leak: AsyncKillableProxy.stop() added
(G-101-additive; in-loop shutdown/close, no kill/revive change), wired
into both durability tests. Dead 'if False' branch removed
(test_identity.py:194).

Result: full suite 669 passed ZERO warnings (174.7s); fast subset
620/49 deselected, zero warnings. Counts: 669 py / 44 web / 64 cli.

---ci---
phase: 3
milestone: v0.7
status: execute
---/ci---
2026-09-27 04:36:14 +00:00
CIAgent 57c65d7a12 chore(P02): phase 2 complete — v0.6.2 shipped, release 902
---ci---
phase: 2
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-002]
  partial: []
---/ci---
2026-09-27 03:24:38 +00:00
CIAgent cc968d93ff verify(P02): MH-2a..2e evidenced — triage table corrected, byte-identity confirmed
Verifier four layers PASS: structural (diff scoped, ruff clean), behavioral
(669 py full / 620 fast / 44 web / 64 cli, foreign-CWD pins 8/8, proxies
byte-diffed with zero non-allowed deltas, droppings absent post-suite),
security (sweeps reach only anchored literals; production sandbox roots
unreachable; seed narrowing intact), quality (3 cuts independently
re-derived — all match D-057 clauses; cross-boundary pins confirmed at
pins.test.ts:48-201). GAP-P2-1 wirePosting fixed; GAP-P2-2 triage rows
corrected in ship record: segmentFromPath is behavioral KEPT-in-place (not
a cut); the 53→44 delta = 8 full cuts + 1 G-106 wire merge (2→1 in pins).

---ci---
phase: 2
milestone: v0.7
status: verify
---/ci---
v0.6.2
2026-09-27 03:24:29 +00:00
CIAgent 6adf0fd20c test(P02): suite composition — evidence-based cuts + infra consolidation (REQ-7-002)
Python (tests/helpers/ package, D-060):
- free_port ×5 → 1; userns probe ×4+6 call sites → 1 (userns.py, skip
  reasons preserved verbatim); uvicorn serve boilerplate ×6 → 1 serve()
  contextmanager (per-site poll constants preserved)
- KillableProxy → TWO helpers per G-101, semantics never unified:
  ThreadedKillableProxy (hard-down) + AsyncKillableProxy (fail-fast RST),
  moved verbatim (byte-diffed vs HEAD: class-name line + free_port only)
- cut test_budget_constant_defined (self-asserting tautology, D-057)
- deterministic waits: _drain sleep removed (blocking recv IS the wait),
  durability 1.5s/1.0s settles → _await_file_diffs deadline polls;
  0.3s outage pacing retained (no observable inside severed link, recorded);
  :542 poll untouched per G-102
- droppings: one-time sweep 4.6 MiB + session-end autouse sweeps for all
  four anchored roots (G-110: no tmp_path moves, fabric constraint doc'd)

Web (D-057/G-103 triage — 17 pin tests, per-assertion):
- CUT 9 local-grep pins (board/detail/employer shells, facets copy, badge
  labels, OG-tag greps, empty-search copy, hook greps) — sole evidence is
  this recorded triage per G-103
- KEEP 8 → tests/pins.test.ts named after regressions/boundaries (G-108):
  E87 generateStaticParams, TS↔py dual-schema ×3 (PostingSummary, SearchResult,
  facets), P4 provenance/resume, TaskVariant env contract, G-106 matchScore
  wire guard, P5 SEO sitemap/robots + JSON-LD
- all readFileSync anchored on import.meta.url (CWD-independent, proven
  from /tmp); environment-kinds.test.ts emptied → deleted
- wirePosting ×2 → tests/helpers.ts (verifier GAP-P2-1)

Counts: 669 py (670−1 cut) / 44 web (53−9 cuts) / 64 cli (63+1 skip).
Full suite 669 green 172s; fast subset 620/49 deselected 56.5s.

---ci---
phase: 2
milestone: v0.7
status: execute
---/ci---
2026-09-27 03:24:26 +00:00
CIAgent 59b21b484d chore(P01): phase 1 complete — v0.6.1 shipped, release 895
---ci---
phase: 1
milestone: v0.7
status: complete
requirements:
  covered: [REQ-7-001]
  partial: []
---/ci---
2026-09-26 17:40:15 +00:00
CIAgent d27706abeb verify(P01): all gates green — MH-1a..1f evidenced, GAP-1/2 fixed
Verifier four layers: structural PASS (configs coherent), behavioral PASS
(670 py / 53 web / 63+1skip cli, dual-tier timeout probes re-run, hook
introspection confirmed 22+6 items at 180s), security PASS (IntegrityError
narrowing exact-match verified vs identity/store.py:149; E2E clone target
mkdtemp), quality PASS (ruff clean; timings re-measured). GAP-1 fixed
(FAST implies NO_COV — fast loop 55.4s), GAP-2 recorded (6.8s combined
integration suites — no split).

---ci---
phase: 1
milestone: v0.7
status: verify
---/ci---
v0.6.1
2026-09-26 17:40:08 +00:00
CIAgent 02d324b896 test(P01): harness wiring — coverage, timeouts, markers, turbo pipeline, leak fixes (REQ-7-001)
- pytest-cov + [tool.coverage] config (95% branch, term-missing every run); c8
  wired around tsx --test in web (95.9%) + cli (76.9%) — no runner swap (D-052)
- markers fast/real_server/userns under --strict-markers (D-053); real_server ×5
  uvicorn suites + userns ×2 files + 1 test (test_manager real-unshare catch);
  test_sandbox_agent unmarked per G-105 (plain stdlib process), outlier timeout(120)
- pytest-timeout signal method: 60s global, 180s via conftest collection hook for
  marked tiers; BOTH tiers probe-proven (60.07s / 180.07s)
- FAST=1 fast subset: 621 passed, 49 deselected, 55.4s bare (MH-M2 <60s holds);
  FAST implies NO_COV per verifier GAP-1 fix
- CLI fresh-clone E2E env-gated (CLI_E2E=1, D-055): visible skip, opt-in green
  (902s aggregate step budget); path-invocation silent return → visible skip
- web#test turbo task + root test/web:test/web:test:cov/cli:test:cov/cli:test:e2e/
  ai:test:fast scripts; pnpm test runs 3/3 workspaces (3m)
- leak fixes: AI_PROVIDER via monkeypatch (probe-proven restore),
  seed_verified_identity check-first + IntegrityError-only, test_engine.py:428
  Path.read_text (P3 item done early)
- PLAN.md count discipline: baseline 670/53/64 (671→670 collection fact; 61→64
  v0.5.7 hotfix tests); Task 1-1-04 no-split decision recorded (6.8s combined)

---ci---
phase: 1
milestone: v0.7
status: execute
---/ci---
2026-09-26 17:40:05 +00:00
CIAgent 9692712e63 chore(P00): phase 0 complete — v0.6.0 shipped, release 894
---ci---
phase: 0
milestone: v0.7
status: complete
---/ci---
2026-09-26 16:13:33 +00:00
CIAgent 660fb471cc decision(P00): mvp/ux gate — verified (3 sections present, pre-execute)
---ci---
phase: 0
milestone: v0.7
status: mvp_ux_check
---/ci---
v0.6.0
2026-09-26 16:13:24 +00:00
CIAgent ae12f01998 docs(P00): grill — 1×P0 + 6×P1 binding amendments applied (G-101..G-110)
KillableProxy two-helpers correction (G-101, P0), de-flake exemplar fix
(G-102), pin-cut evidence rule (G-103), filterwarnings growth rule
(G-104), marker taxonomy verification + timing baseline (G-105), recharts
probe ownership + timebox (G-106), purity-gate confirmation (G-107),
pin-cut value stance (G-108), transitive audit wave 5-3 (G-109),
sandboxes-droppings correction (G-110).

---ci---
phase: 0
milestone: v0.7
status: grill
---/ci---
2026-09-26 16:13:20 +00:00
CIAgent 63f9a0fc59 docs(P00): create phase plans — v0.7 six-phase NFR (wiring→composition→warnings→lint→typing→ship)
---ci---
phase: 0
milestone: v0.7
status: plan
---/ci---
2026-09-26 16:01:24 +00:00
CIAgent 69811f953b docs(P00): research findings — harness/warning census + persona assessment
Probe-verified baseline: 785 tests green, zero coverage/timeouts/markers,
1,716 warnings/run (14 session.query sites + 14 ResourceWarning sites),
81 inert noqa, 5 orphaned eslint-disables, no ESLint, no Python type
checker. Research conclusions 44-50 (D-062 wave order). Personas: backend
+ frontend + data + lead active for NFR; security-auditor phase-specific.

---ci---
phase: 0
milestone: v0.7
status: research
---/ci---
2026-09-26 15:54:46 +00:00
CIAgent ba0afa757a docs(P00): clarify — 10 ambiguities auto-decided (D-052..D-061)
Coverage tooling (pytest-cov + c8), marker taxonomy (fast/real_server/userns,
strict-markers), pytest-timeout (signal/60s/180s), CLI E2E env-gated,
filterwarnings error-first, pin-triage rule, mypy relaxed-first baseline,
recharts verification net, tests/helpers/ package, version single-source.

---ci---
phase: 0
milestone: v0.7
status: clarify
---/ci---
2026-09-26 15:54:03 +00:00
CIAgent bbcb84ec6c docs(init): validate specification — v0.7 test-harness-review (NFR)
---ci---
phase: 0
milestone: v0.7
status: specify
---/ci---
2026-09-26 15:51:29 +00:00
CIAgent cda6ab1936 merge: hotfix/deploy-stale-checkout → main (v0.5.7 — deploy fails loudly on a stale checkout)
Escalation note: merge_to_main hook — proceeding per full autonomy +
founder report (deploy on the host reported success without updating;
the fix makes the failure loud and adds the freshness gate).

---ci---
phase: hotfix
milestone: v0.6
status: complete
type: hotfix
---/ci---
v0.5.7
2026-09-26 15:46:00 +00:00
CIAgent efeaece465 chore(P06): clear checkpoint — milestone v0.6 complete
---ci---
phase: 6
milestone: v0.6
status: complete
---/ci---
2026-09-26 15:07:00 +00:00
CIAgent e2f3dbdc11 merge: milestone/v0.6-marketplace-engine → main (v0.6 complete — the Marketplace Engine)
The real marketplace backend behind the existing surfaces, all six
requirements (REQ-6-001..006) shipped across six patches:

- P1 (v0.5.1): postings backend — 6th D-027 store family (six tables),
  PostingSource adapter contract + seeded corpus (20+10 ported once from
  mock-data, matchScore dropped), /v1/marketplace/* public API, REAL
  apply route replacing the G-18 501 stub (D-043 gate composition
  preserved, idempotent), fail-closed admin surface (SecretStr +
  constant-time bytes compare), web client shells (G-101 placeholder
  export + FastAPI catch-all serving — the grill-caught E87 build break
  fixed before execute).
- P2 (v0.5.2): AI tagging via the D-020 pipeline (skills ≤10 enforced,
  extra=forbid honesty), tag-on-ingest, re-tag overwrite on edit,
  facets data-driving the filter sidebar.
- P3 (v0.5.3): EmbeddingProvider protocol (deterministic mock-first;
  OpenAI-compatible real path with key redaction — probe-corrected:
  ollama-cloud exposes no /embeddings), SQLite-local float32 vectors
  with lazy re-embed, hybrid facet+cosine search, computed match
  scores ONLY in search context (G-106).
- P4 (v0.5.4): employer enrichment — append-only provenance rows,
  merge-on-read manual>llm>raw with visible per-field markers (A-304),
  enrich-on-first-publish; resume parsing — pypdf (the only new dep),
  honest bounds (2MB, text-layer-required, no OCR), DRAFT-then-confirm
  gate with ParsedProfile re-validation, raw bytes never stored/logged.
- P5 (v0.5.5): SEO — build-time metadata + OG + JSON-LD on the static
  set, client JobPosting/Organization JSON-LD on runtime pages,
  dynamic /sitemap.xml + /robots.txt (request-time enumeration, API
  beats the static mount, every URL resolves 200, XML-escaped,
  forgery-hardened, G-105 fail-honest unset-origin behavior).
- P6 (v0.5.6): final review CLEAN (zero P0s; all G-101..G-110 honored;
  MH-M1..M6 met; admin-token bytes-compare + catch-order fixes) +
  audit PASS (reconstruction clean, discipline intact).

670 backend tests (+182 over v0.5's 488), web 53/53 (+31), CLI 61/61,
typecheck green, ruff clean, static export builds (G-101 shells).

Escalation note: merge_to_main hook — proceeding per full autonomy
(D-007); the v0.6 scope was auto-decided at SPECIFY (D-047, confidence
0.80) and every phase shipped under the per-phase + final gates.

---ci---
phase: 6
milestone: v0.6
status: complete
requirements:
  covered: [REQ-6-001, REQ-6-002, REQ-6-003, REQ-6-004, REQ-6-005, REQ-6-006]
  partial: []
---/ci---
v0.5.6
2026-09-26 15:06:37 +00:00
CIAgent d72cea1786 docs(hotfix): v0.4.7 records — P1 flags closed, deployed, verified
---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 21:02:30 +00:00
CIAgent 192fa6a655 merge: hotfix/pre-public-hardening → main (v0.4.7 — the 4 P1 flags closed)
HMAC ingest tokens on the WS grading input (LAN poisoning closed),
nonce+counter defense-id mint (same-ms collision closed), browser-mode
client SR/TTS implemented per the descriptor's v0.5 contract (gap
closed), and 8 module pins for the browser voice path.

Escalation note: merge_to_main hook — proceeding per full autonomy +
founder directive (troubleshooting round + patch release, P1 flags
included per the 2026-09-21 scope answer).

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
v0.4.7
2026-09-21 21:01:07 +00:00
CIAgent 4193552460 fix(hotfix): pre-public hardening — the 4 P1 flags from the v0.5 final review
P1-1 WS ingest auth (grading DoS): the ingest socket is a grading input,
LAN-reachable in network mode, and identity params were self-asserted —
anyone could poison or flood a learner's trace. New HMAC ingest token
(telemetry/tokens.py): the sandbox manager mints it into NC_INGEST_URL
(bound to learner+task+sandbox, length-prefixed binding — no delimiter
injection), the WS endpoint verifies before accept. Mint/verify share one
app.state instance (per-boot random secret when
AI_TELEMETRY_INGEST_SECRET is unset; env-set for multi-process deploys).
Untokened/bad/cross-identity dials close 1008 storing nothing.

P1-2 defense-id collision: `dfn-{ms:x}` collided on same-millisecond
starts — the insert-only store's PK then 500'd the second start
permanently (the identity-resubmit P0-C1 class). Nonce+counter mint
(the identity/mock.py pattern); ids stay opaque, PII-free.

P1-3 browser-mode SR/TTS client gap: the mode="browser" descriptor has
advertised client-native SpeechRecognition + speechSynthesis since v0.5
(D-030/CUT-1) — the client never implemented it, so browser-mode voice
posted audio the server had no provider to transcribe. New pure module
apps/web/lib/browser-voice.ts (recognizeOnce + speakText, injectable
seams); the defense session uses it when descriptor.mode === 'browser'
(text answers; examiner questions spoken via speechSynthesis), keeps
MediaRecorder upload for server/mock modes, honest 'unsupported' state.

P1-4 browser-mode audio coverage: 8 node:test pins for the module
(transcript roundtrip, silent-user, permission/unsupported error maps,
timeout overrun, TTS absent/empty/cancel-prior/resolve-on-end).

488 backend tests (+10); web 22/22 (+8); CLI 61/61; typecheck 8/8;
ruff clean; export builds.

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 21:01:03 +00:00
CIAgent 0324067fa7 docs(hotfix): v0.4.6 records — root cause, deploy experience, host verification
---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 20:44:09 +00:00
CIAgent 75bde88e0d fix(hotfix): toolchain prefix carries node dir + pnpm dir (split installs)
The host dogfood run, bug three: pnpm came from PNPM_HOME while node
lives in nvm — the prefix carried only pnpm's dir, so `pnpm build`
spawned turbo, which exec'd bare `node` and died rc 127. The
discovered prefix now includes every candidate dir carrying node OR
pnpm (pnpm's own dir first), so pnpm children resolve the same node
family on split installs — the exact production-host layout.

CLI 61/61 (+1 split-install regression pin).

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
v0.4.6
2026-09-21 20:42:18 +00:00
CIAgent e14e1fa3d2 fix(hotfix): deploy update path — local main + ff-pull for origin/main, immutable checkout for tags
The host dogfood run caught the second first-run bug: `git checkout
origin/main` detaches HEAD, and `git pull --ff-only` refuses to run on a
detached HEAD — deploy dead-ended on the production clone. origin/main
now resolves through local main (checkout main; checkout -B main
origin/main when absent), pulls only on that branch; --ref tags are
immutable checkouts (no pull attempted).

CLI 60/60 (+1 detached-HEAD regression).

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 20:41:18 +00:00
CIAgent 843f16d737 fix(hotfix): dispatch pass-through for subcommand flags + dev-mode verify semantics
Two first-run bugs found deploying v0.4.6 to the host (the dogfood run):

- run() filtered flags EVERYWHERE, so `deploy --service` never reached
  the command ("unknown flag: --service" + help) — the exact command the
  installer tells the user to run. Global flags are now only those
  BEFORE the command name; subcommands own their own flags. doctor and
  bootstrap gained arg validation (they previously ignored unknown
  flags silently) to keep the exit-2 contract the old dispatcher gave.
- verify's web-export check failed fresh DEV clones (bootstrap → verify
  → exit 1: no export until pnpm build, by design in dev mode). Now
  warn-only when absent; the runtime catch is the live mount probe +
  the loud boot warning. Deploy builds the export before verify runs,
  so single-port deploys keep the hard guarantee.

CLI 59/59 (fresh-clone E2E green against the rebuilt SEA binary).

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 20:39:10 +00:00
CIAgent 3291914eaa merge: hotfix/deploy-static-404 → main (v0.4.6 one-command deploy + mount detection)
The public site was down for three releases: the domain root served the
API's JSON 404 because the deployed service ran mount-less — the web
export was never built on the host (silent dev.ts auto-wire skip) and
nothing detected it. This hotfix fixes the class:

- nextcraft deploy: clone/update → install → venv → build export →
  restart → verify, one idempotent command; --service installs a
  systemd unit for reboot persistence.
- toolchain discovery: pnpm behind nvm/PNPM_HOME/corepack is found —
  the host had pnpm all along, non-interactive shells just couldn't
  see it.
- loud mount-less boot warning + verify's live mount probe (GET / must
  be HTML, not JSON 404) — the outage can no longer ship silently.

Escalation note: merge_to_main hook — proceeding per full autonomy +
founder directive (troubleshooting round + patch release requested
2026-09-21, dev-experience fixes for the one-liner incorporated).

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 20:35:15 +00:00
CIAgent 4465e6325d fix(hotfix): deploy-static-404 — one-command deploy, loud mount-less boot, reboot persistence
The domain root (nextcraft.coreci.dev) served the API's JSON 404 for three
releases. Root cause (probe-verified on the host): the deployed uvicorn ran
without AI_WEB_STATIC_DIR because apps/web/out was never built — dev.ts
auto-wiring silently skips when the export is absent, and NOTHING detects
the mount-less boot. HAProxy was never the problem; the JSON 404 at / IS
the mount-less signature (pinned by test_web_static.py since v0.3.6).

Class fixes (the deploy experience, per founder directive):
- toolchain discovery (lib/toolchain.ts): node/pnpm behind nvm,
  PNPM_HOME, or corepack are FOUND even when non-interactive shells
  can't see them — the host had pnpm the whole time; doctor, bootstrap
  and deploy all resolve through it (PATH → nvm → PNPM_HOME → corepack).
- nextcraft deploy: the one command the installer hands off to —
  clone-or-update → pnpm install → venv → web export build → restart →
  verify. Fails LOUDLY if the site isn't actually served. Idempotent:
  same command for first install and upgrades. deploy --service installs
  a generated systemd unit (real paths, Restart=always, enabled) so the
  stack survives reboots; systemd becomes the supervisor (dev -d and
  stop respect it).
- create_app(): a mount-less boot now WARNs naming the fix (G-11
  doctrine — the failure was silent for three releases).
- verify: web-export presence check + LIVE MOUNT PROBE — when :8420 is
  serving, GET / must return HTML, not the API's JSON 404. This is the
  check that would have caught every prior outage.
- install.sh next-steps → `nextcraft deploy --service`; README +
  deploy/README rewritten around the one-command flow.

478 backend tests (+1 loud-boot pin); CLI 59 (45→59: toolchain discovery
x7, deploy x4, verify probes x3, hermeticity fixes); web 14/14;
typecheck 8/8; ruff clean; static export builds.

---ci---
phase: hotfix
milestone: v0.5
status: complete
type: hotfix
---/ci---
2026-09-21 20:35:10 +00:00
CIAgent c9709e0f38 chore(P05): clear checkpoint — milestone v0.5 complete
---ci---
phase: 5
milestone: v0.5
status: complete
---/ci---
2026-09-13 23:05:20 +00:00
CIAgent 62bff575af merge: milestone/v0.5-real-voice-identity-envs → main (v0.5 complete)
Real Server Voice, KYC/Identity, Sandbox Environments, Seq-Lease — the four
seams D-016 deferred out of v0.4, shipped:

- P1 (v0.4.1) seq-ack protocol: ingest acks durable latest_seq; the capture
  agent trims its spool to the ack — the replay margin collapses from
  one-line to the unacked in-flight window (the P07-documented gap, closed
  with a real-server mid-burst regression).
- P2 (v0.4.2) real server voice: OpenAIAudioProvider (STT multipart + TTS
  streaming) on the shared pool, boot-safe config, codec-strip + 10MB guard
  + format-aware media_type on the defense routes, web audio answers with
  bounded recording and an honest provider badge.
- P3 (v0.4.3) identity + age-gating: provider protocol + 5th SQLite store
  (derived age bands, document refs, PII never stored/logged — pinned),
  D-043 gate composition (allowlist → identity → caps) on
  variants/sandboxes/defense (16+) + one marketplace route (18+ verified,
  honest 501 stub), /enroll flow, G-10 403 discrimination. Verifier-
  hardened: malformed-DOB boundary validation (was a remote permanent
  lockout + log leak), fail-closed gate, band constraints.
- P4 (v0.4.4) design/simulation environments: template-layer kind registry
  (G-15 shlex-roundtrip validated commands), kind + test_command on the
  wire (Run/Test stop hardcoding pytest), per-kind exact-token exec policy
  (sh -c passthrough blocked), in-ns python3 harness, real-server design
  E2E.
- P5 (v0.4.5) review + audit: 3 cross-phase P0s fixed (identity resubmit
  500, audio 502, v0.4 DB migration backfill); doc-reality audit clean.

477 backend tests, web 14/14, CLI 45/45, typecheck 8/8, ruff clean,
static export builds. All 7 requirements (REQ-5-001..007) complete.

Escalation note: merge_to_main hook — proceeding per full autonomy; the v0.5
scope was locked by the founder at phase 0 SPECIFY (the D-016 deferred seams)
and approved via the phase-0 confirmations in this run.

---ci---
phase: 5
milestone: v0.5
status: complete
requirements:
  covered: [REQ-5-001, REQ-5-002, REQ-5-003, REQ-5-004, REQ-5-005, REQ-5-006, REQ-5-007]
  partial: []
---/ci---
v0.4.5
2026-09-13 23:04:47 +00:00
CIAgent 8a43e95a4d merge(P05): final review + audit → milestone/v0.5-real-voice-identity-envs
---ci---
phase: 5
milestone: v0.5
status: ship
---/ci---
2026-09-13 23:04:47 +00:00
CIAgent ee5be13c94 docs(milestone): complete v0.5-real-voice-identity-envs
---ci---
phase: 5
milestone: v0.5
status: complete
requirements:
  covered: [REQ-5-001, REQ-5-002, REQ-5-003, REQ-5-004, REQ-5-005, REQ-5-006, REQ-5-007]
  partial: []
---/ci---
2026-09-13 23:04:33 +00:00
CIAgent 1da814e790 fix(P05): final review — 3 cross-phase P0s (identity resubmit 500, audio 502, v0.4 DB migration)
P0-C1: mock identity ids were hash(learner, DOB)-deterministic — resubmit
after a TERMINAL verdict collided on the insert-only PK → unhandled 500,
permanently blocking re-verification (the D1 lockout one path deeper).
Ids now mint uniquely per submit (nonce + counter, PII-free); verdict
determinism preserved in poll(). Regression: resubmit-after-reject → 200
fresh pending → G-13 409.

P0-C2: defense audio answers 500'd on every default deployment — the mock
provider's empty transcript queue raised MockVoiceFailure (unhandled) the
first time a learner used the mic; same for a real endpoint outage.
transcribe() now maps provider RuntimeErrors to honest 502s (house
pattern); typed answers unaffected. Regression: unscripted mock → 502,
then typed answer → 200 on the same defense.

P0-C3: v0.5's variant_record columns brick a pre-v0.5 DB (create_all
never ALTERs) — every variant read/write raised OperationalError after an
in-place upgrade. Idempotent _ensure_v05_columns() backfill in the store
constructor (PRAGMA table_info → ALTER ADD COLUMN with defaults; legacy
rows read as build-kind). Regression: literal v0.4 table → open → read →
write → reopen idempotent. deploy/README documents the in-place note
(fresh-state directive still honored).

477 backend tests (+3); ruff clean; typecheck 8/8.

P1 flags recorded for pre-public hardening (non-blocking): unauthenticated
WS ingest on LAN (grading DoS), browser-mode SR/TTS client gap, defense-id
ms collision, browser-mode audio E2E.

---ci---
phase: 5
milestone: v0.5
status: review
---/ci---
2026-09-13 22:45:39 +00:00
CIAgent cc7ec5d03f chore(P05): checkpoint — final phase 2026-09-13 21:50:22 +00:00