Commit graph

14 commits

Author SHA1 Message Date
d1aab85dbe docs: sequence pending iterations in implementation order
- new "Implementation order (sequenced 2026-08-20)" section in 00-status.md
  pending bucket: 7-finish, 17, 9g, 14, 9c/9d, 9e, 8, 9f, 11, 10, 12,
  13 + parked drain
- forcing rules recorded: 9f after 8+9e; 9c precedes 10; 9d folds into 9c;
  12 after 9+10; 11 rides 8's scheduler; h2c behind 8/9f/11; post-12 park
  directive unchanged
- 9e placed before 8 so restructure/perf work has a signed baseline
- 14 early as next driving workload (stdlib-shaped, shard-independent)
- story 00-story.md notes point at the sequenced list

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 01:50:03 +02:00
3e22e42da5 docs: iteration 17 forks settled — kind key, internal/ rule (no code)
- fork 1: library-ness manifest-declared, kind = "library", default program
- fork 2: privacy = Go internal/ directory rule, named diagnostic at use
- fork 3: dep-boundary-only scope; Go subtree rule recorded as later tightening
- fork 4: lib+bin dual — library default action is check, explicit build works
- Go-inherited rule pinned: internal type in public signature allowed, no check
- impact analysis added: framework loses --emit workaround, plumbing under
  internal/; compiler = two seams (driver kind + dep-use refusal WO-E1xx)
- VM zero impact by construction: no .wob change, libs compile whole-program
  into consumer image, internal modules still emitted (privacy strips nothing)
- GC zero mechanism impact; pinned: inference stays whole-program, app usage
  can promote dep classes, internal/ invisible to gcinfer — intended, not bug
- board + roadmap rows: needs-refinement -> forks settled, spec/plan next

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 01:45:06 +02:00
f430bff5c4 docs: iteration 17 — library projects + dependency privacy (needs refinement)
Brainstorm outcome, deliberately NOT implemented (developer decision: keep
as an iteration needing further refinement). Records:
- the two gaps iterations 15/16 exposed: library-ness is implicit (a
  no-main project fails woc <dir> build mode — the framework is verified
  via an --emit workaround) and the dep boundary leaks internals (pub has
  no dep-private tier: parse_request is as importable as Handler).
- the conventions corpus: Go (package decides program-ness; cmd/;
  internal/ = directory-shaped privacy, zero keywords) vs Rust ([lib]/
  [[bin]] manifest targets; pub(crate)-family keyword visibility). Doctrine
  fit points at Go's shape with an explicit manifest key (writeonce HAS a
  manifest; explicit beats inference in errors).
- four open forks for the spec: kind declaration form; internal/ vs
  pub(lib) vs export-allowlist; dep-boundary-only vs Go's subtree rule;
  lib+bin duality. Draft acceptance criteria; web-app 14/0 as the
  regression gate. Roadmap + board rows added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 01:23:10 +02:00
976ccda225 docs: web framework + deps design — spec + iterations 15/16
Brainstorm outcome (forks locked with the developer):
- TLS: proxy-terminated (nginx/caddy gives browsers TLS+ALPN+h2; the
  framework speaks HTTP/1.1 behind it) — zero TLS in the toolchain, no
  doctrine fight; homegrown TLS refused outright.
- Dependencies: a real mini package manager — wo.toml [deps] with exact-rev
  git deps, wo.lock, .wo-deps cache, `use <dep>` as a module root; fetch by
  shelling to the git binary (no network code in woc); flat-only v1.
- HTTP/2: v1 is HTTP/1.1 keep-alive; h2c is the parked successor behind
  iterations 8/9f/11 (multiplexing needs a scheduler to pay off); the
  bytes/buffer type rides with it, not v1.
- Handler model: no function values by doctrine, so Handler/Middleware are
  structural interfaces (ICALL dispatch, WO-E205-checked); middleware returns
  ?Resp and rides the shipped ?T narrowing.
- Incubation: framework at docs/examples/writeonce-framework/, consuming
  storefront at docs/examples/web-app/ importing it THROUGH [deps] — the
  sample exercises fetch -> lock -> build -> serve -> durable-restart.
- Iteration 10 relationship: service blocks later LOWER ONTO this library.

Files: specs/2026-08-18-web-framework-design.md (A deps normative, B
framework normative, C h2c parked); stories 15-deps-package-manager.md +
16-web-framework.md; roadmap + board rows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:07:16 +02:00
b6151333c3 docs: iteration 14 — skillhost as a host-shaped driving workload
- frames a writeonce port of ~/projects/skillhost (C++ MCP host that
  links libllama in-process, discovers filesystem skills, runs their
  scripts confined) as the sample that drives host capabilities into
  the open — the way log-watcher drove the systems stdlib
- names each gap as a candidate iteration (surveyed 2026-08-16 vs the
  running compiler + skillhost source):
    - Blocker A: in-process native-lib FFI (no FFI today) — fork:
      FFI-as-language vs out-of-process model driver over proc/net+json
      (llama-server, needs nothing new); leaning out-of-process
    - Blocker B: stdio transport — no stdin/stdout builtins; port uses
      a TCP socket meanwhile; io.stdin_read/stdout_write a candidate
    - Blocker C: bounded/killable subprocess — proc.run has no timeout/
      signal/process-group kill; smallest + most broadly useful, do 1st
    - partials: recursive fs walk, exec-bit check, symlink-resolving
      confinement (realpath) — one small fs-metadata iteration
- records what is already expressible (catalog via @table/9g skill-
  catalog, discovery, frontmatter text-parse, config, single-thread
  serve, context-gate arithmetic — no VRAM query needed)
- out of scope: in-process libllama/CUDA, VRAM introspection, exact
  sampler chain / per-turn memory clear
- roadmap + board rows added

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 19:53:06 +02:00
86e1fd4a4e docs: iteration 9g story -- query grammar from real embedded-DB corpora
- method: an embedded-SQL app is a grammar corpus; catalogue what it
  actually uses and add only that, translating its statements 1:1 as
  the acceptance (the postgres/System.Linq reference pattern applied to
  a whole application)
- corpus #1 = ~/projects/skillhost (C++ MCP host, embedded SQLite skill
  catalog): surveyed, entire SQL footprint is one file — 1 table, a
  single-row parameterized INSERT, 4 SELECTs. 3 of 5 statements already
  run on the 9b surface (insert, where name==?, order by name; PK ≈
  @unique). Exactly 2 are the real gap:
    - whole-query `count` (group-free; the degenerate aggregate, NOT
      the parked group-by)
    - correlated `not exists` subquery (skillhost's roots-of-the-tree)
- notable finding: skillhost's NOT EXISTS is naturally a `backlink`
  emptiness in writeonce (children backlink + len==0), so the corpus
  may be fully expressible once len(query) is confirmed — the iteration
  may collapse to "confirm len(query) + add exists"; forks record this
- explicitly parks everything skillhost does NOT use (join/having/
  offset/distinct/CTE/window/union/upsert/returning/json/fts/triggers)
  and the full group-by; each enters only when a corpus demands it
- acceptance: docs/examples/skill-catalog mirroring skillhost's schema
  + its 5 catalog ops as writeonce translations
- roadmap + board rows added

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 19:28:25 +02:00
ad8cfb456e docs: iteration 13 story -- compile-time metaprogramming (derive)
- captures the toCSV/reflection thread: principle 13 forbids runtime
  reflection, so a generic serializer can't be a user-written function;
  Rust answers with derive macros (compile-time codegen), and
  json.encode is already a single hand-built instance of exactly that
- iteration generalizes json.encode's mechanism into a reusable derive
  facility: @derive(Json/Csv/Eq/Hash/Show) -> the compiler generates
  per-type routines from the class-table metadata it already emits,
  monomorphic, no runtime type tag, no dynamic dispatch
- closes the query-result-serialization gap
  (csv.encode(from e in Employee ... select e)) that has no expression
  today; acceptance requires json.encode retrofitted onto the framework
  with byte-identical output, and disassembly proving no reflection
- four forks: request surface (lean @derive annotation), invocation
  (lean compiler-recognized encode builtins, no UFCS/methods), Eq/Hash
  sharing the engine's key comparison, static applicability checking
- out of scope: full trait/typeclass system, user proc-macros, general
  generics, cross-channel derive -- a CLOSED compiler-known derivable
  set, the pragmatic 80% without the type-system weight
- numbered 13 to echo the principle it lives inside; roadmap + board
  rows added

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 04:57:00 +02:00
71d3985e81 docs: performance arc as story iterations (9e measure, 9f io_uring)
- 9e durability/throughput/scale: the measurement backbone -- run the
  employee program, restart to prove persistence, benchmark read/write
  through compiled .wo, ~1M-row mixed load with throughput floor + p99
  ceiling + flat RSS; the gate every optimization signs (before/after
  delta required, no measured delta = not accepted)
- 9f io_uring group-commit: replace fsync-per-commit with batched
  io_uring durability overlapped on shard threads; same ack-after-
  durable contract, crash battery unchanged, automatic fsync fallback
  on kernels without it; deliberately LAST (needs 8's threads to
  overlap and 9e's baseline to beat)
- wired the existing levers into the arc: iteration 8 (thread-per-core)
  = "optimize multithreading", 7b (mark-sweep) = "implement GC" --
  each now gated by re-running 9e and recording the delta
- explicit sequence recorded in 9e: 9b lands -> 9e baseline -> 7b
  re-bench -> 8 re-bench -> 9f re-bench
- roadmap + board rows for 9e/9f; four forks each for the specs
  (load generator, absolute vs relative budgets, what "1M" means,
  durable vs RAM headline; ring model, liburing vs raw, batch
  boundary, fallback testing)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 22:12:48 +02:00
fe56ba0944 docs: iteration 9d story -- keypair authentication for attach
- promotes 9c's identity fork to its own iteration: program identity
  is a keypair (first-boot generated into WO_DATA, 0600, printable
  fingerprint); A's [share] grants name PUBLIC KEYS, B pins A's key
  in [connect.a]; mutual challenge-response, fresh nonces, transcript-
  hash signing (protocol tag + fingerprints + nonces + channel)
- acceptance criteria: registered-key attach carries 9c rights
  unchanged; unregistered key refused pre-statement with fingerprint
  logged; same-uid-wrong-key refused (uid SUPERSEDED, not
  supplemented); impostor on A's socket path aborted by B's pinned-key
  check; handshake replay refused; rotation = manifest change
- four forks recorded: crypto provenance (lean: vendored compact
  Ed25519 as the one sanctioned vendored component), keygen home
  (lean: first-boot into WO_DATA), signed-transcript layout, uid
  survival (lean: keys only, peer-cred demoted to log enrichment)
- out of scope: transport encryption, CA machinery, key escrow,
  root-attacker protection
- plan folds into 9c's when specced (neither ships alone); 9c fork 3
  marked superseded-as-end-state; roadmap + board rows added

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 12:26:49 +02:00
b92357b6b9 docs: iteration 9c story -- cross-program tables (attach over IPC)
- program B attaches to running program A's persistent database via an
  IPC string in B's wo.toml [connect.<name>]; A registers clients by
  name with read / read+write rights in its [share] manifest section;
  unregistered = refused at connect, under-privileged = catchable trap
- doctrine preserved: A stays the single writer -- B's statements
  execute inside A through the same choke-point row API, B never
  touches A's WAL or slabs; typed statements checked by B's compiler
  against A's table shapes, schema handshake at attach
- four forks recorded for the spec: channel carrier (lean: unix
  socket + SO_PEERCRED), how B's compiler learns A's shapes (lean:
  project reference + live handshake), grant granularity (lean:
  whole-db rights, name+uid identity), blocking semantics (lean:
  blocking round-trip, stop-flag rule applies)
- acceptance sketch: employee sample as A, a thin employee-report
  client as B (read-only GroupBy over the wire) + audit-log writer
  exercising the rights matrix
- slots after 9b (shares its typed surface), before 10 (HTTP is the
  external face; this is the writeonce-native one); prior art:
  04-client-api.md wire protocol + the WAL's value encoding
- roadmap + status board rows added

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 12:13:38 +02:00
79605cbb4f feat: milestone 1 complete — .wob emitter, conformance corpus, single binary; GC redesign specced
- `woc` now emits `.wob` that `wovm` runs: emit.ml lowers the typed,
  owner-annotated AST (scope-stack registers with a >64 WO-E401 diagnostic,
  Lua-style call windows, ICALL by slot, dedup const pool, drop maps, line
  tables, implicit terminators); disasm.ml backs `--dump-bc` goldens.
- Ownership lowering consumes the four owner tables verbatim; RESIDUAL is the
  only source of borrow ops, coalesced per operand. Review caught the emitter
  consuming only 2 of owner.ml's 4 residual producers — an assignment-anchored
  aliasing violation ran to exit 0 instead of trapping; fixed, plus a backstop
  raising WO-E404 for any residual region left unconsumed.
- Conformance harness `scripts/oop-e2e.sh` (`just oop-e2e`): four fixture
  kinds with exact outcomes — byte-exact stdout, one WO-E### anchored on
  `error CODE:`, numeric trap code, gc trace. 25 fixtures incl. pricing-demo
  logic, the ownership suite, and DB_STUB's parse-but-trap. `tests/` un-ignored
  so the corpus is actually tracked.
- `woc build` produces a self-contained binary: wovm copy + appended image +
  20-byte trailer, self-exec via /proc/self/exe. Verified relocated outside
  the repo, argless, and against adversarial trailer corruption.
- Milestone 1's five spec criteria all MET (`just oop-accept`). Criterion 3
  closed by WO-E405 — the entry must return `Int`, since program mode already
  says its return value is the exit code — which deletes the leak class
  without adding return-type metadata to the format. `gc/held-cycle` retired:
  an externally-held cycle is not expressible in a post-exit pump.
- New spec: inferred GC + incremental per-shard tri-color mark-sweep, retiring
  `@gc` and reference counting. Story gains iterations 7b (that work) and 9b
  (`@table`, relations, compiler-checked query); `.dev/reference` gains a
  sparse System.Linq checkout. Priority: 5→6→7 (log-watcher) then 7b, 8, 9, 9b.
2026-08-11 19:31:26 +02:00
49872a4b11 docs: six-bucket status board; recover lost vision doc; stop ignoring docs/
- 00-kanban.md rebuilt: ▶ NEXT PLAN pointer (iteration 4 — emitter, corpus,
  `woc build`) then six buckets — stories, in progress, done, pending,
  discarded, learnings. It tracked only the Rust runtime before, so the whole
  OOP track (wovm shipped, woc Tasks 1-8 shipped) was invisible.
- Board now records iteration 3's known gaps instead of silently owing them:
  `?T` plumbed but unenforced; E205/E201/E203/E204 dead, so structural
  interface satisfaction is unchecked.
- New discarded.md — settled rejections with reasons so they are not
  re-proposed: inheritance, `abstract` newtypes, Money/SKU/Float, Dynamic/cast/
  macro/extern, AOT-to-C, Menhir, shared engine state, external deployer.
- RECOVERED docs/plan/exploration/blue-green-vm/00-vision.md — gone from disk,
  never committed (gitignored path), cited by five docs incl. principle 12.
- Root cause was broader: all seven forward-roadmap plans in
  docs/superpowers/plans/ were untracked and ignored, on one disk only. Rules
  were half-fiction — 33 of 34 exploration files were already tracked, so they
  swallowed only *new* files.
- Dropped the docs ignore rules (exploration, oop-vm, superpowers/plans,
  examples/agent-loop, examples/mcp-think) with a do-not-re-add comment; added
  __pycache__/*.pyc. `tests/` stays ignored but warns that the next plan lands
  the corpus there.
2026-08-10 21:52:59 +02:00
2de724df11 feat(compiler): MVS ownership pass + woc driver; drop Money/SKU/Float, reject abstract
Completes plan 2 Tasks 7-8. owner.ml: mutable-value-semantics flow analysis
producing the four plan-3 emitter tables (moves, drops incl. LIVE-MASK for trap
unwinding, rc with elision, residual borrow sites) plus WO-E301-304 two-site
diagnostics. Alias questions run over canonicalized places, so a double-mut
reached through let-bound aliases lands in the residual table like the direct
form; dump.ml's contract notes the emitter must coalesce guards per operand.
main.ml: directory discovery, cross-file programs (symbols merge before bodies
check), diagnostics ordered by (file,line,col), new WO-E214 for a name declared
in two files. New docs/plan/oop-vm/01-error-catalog.md (14 emitted + 10 reserved
codes), un-ignored so both plan tracks can cite it; justfile regains woc-*.

builtin_scalars is now the five that work: Int, Bool, Text, Timestamp, Id.
Money/SKU/Float and the abstract_types allowlist are gone — `abstract` never
lexed, and Float had no literal syntax and no wob kind, so no value could exist.
Fixtures and samples retype Money->Int, SKU->Text. The abstract newtype feature
is rejected outright (verdict row adopt->reject); haxe-parity Task 7 keeps `is`.

nullable-types-implementation.md corrected: ?T is plumbed but UNENFORCED
(E211-213 declared, never emitted; probe exits 0), handed to haxe-parity Task 6
as next work item. Records all 10 dead codes incl. E205 — interface satisfaction
is unchecked. crates/rt keeps its Money/SKU fixtures (opaque strings, Stage 2).

Gate: build warning-clean, 14 + 264 checks 0 failures, pricing golden exit 0,
docs/examples histograms unchanged (13/70, zero WO-E225).
2026-08-10 21:24:50 +02:00
2986c3c906 language-runtime-database iterations 2026-08-07 19:36:49 +02:00