From e48b17547204ddbee49110034bef66b8bcdfec91 Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Wed, 19 Aug 2026 19:23:18 +0200 Subject: [PATCH] docs: iteration 15 closeout (Task 5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - error catalog: WO-E106 (dependency fetch/shape failures, one code, message names dep + step) and WO-E107 (dep/local module-name collision) rows. - README: a Dependencies subsection under the manifest docs — [deps] syntax, .wo-deps/wo.lock behavior, offline-when-locked, --update-deps, flat-only. - board: iteration 15 row -> landed (deps-accept 8/0), pending row removed; story 15 header records the landing; 08-project-structure notes .wo-deps (gitignored) + wo.lock (committed); plan checkboxes all ticked. (One self-inflicted casualty during this task, restored from git before commit: a buggy doc-edit script truncated 08-project-structure.md; the file was recovered intact and the intended one-liner applied by hand.) Gates at closeout: deps-accept 8/0, woc-test 540/0, oop-e2e 87/0, log-watcher 7/0, employee 8/0. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 18 ++++++++++ docs/00-status.md | 3 +- docs/08-project-structure.md | 3 ++ docs/plan/oop-vm/01-error-catalog.md | 2 ++ .../15-deps-package-manager.md | 9 +++-- .../plans/2026-08-18-deps-package-manager.md | 36 +++++++++---------- 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8954eb0..e59d7f2 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,24 @@ runtime = "../../../runtime/wovm" # path to the wovm the binary is built from `woc myproject/` compiles every `.wo` file under the directory as one program. +### Dependencies + +A project can depend on other writeonce repositories — exact-rev git +dependencies, declared in the manifest: + +```toml +[deps] +niceframework = { git = "https://github.com/shoneyj/niceframework", rev = "v0.1.0" } +``` + +`woc` fetches each dep (via the `git` binary) into `.wo-deps//`, pins +the resolved commit in `wo.lock`, and `use niceframework` (or +`use niceframework/sub`) imports its public names like any module. Builds +never touch the network once the lock is satisfied; a moved tag is reported, +and `woc --update-deps myproject/` refreshes the lock deliberately. Flat +dependencies only (a dep may not have its own `[deps]`) — honest and small, +by design. + Programs that create tables read their data directory from the `WO_DATA` environment variable at run time: diff --git a/docs/00-status.md b/docs/00-status.md index 6ab07f6..c69f319 100644 --- a/docs/00-status.md +++ b/docs/00-status.md @@ -130,7 +130,7 @@ that sequences its tasks. Read one, approve, then the next starts. | 12 | [Blue-green deploy](stories/language-runtime-database/12-blue-green-deploy.md) | ⬜ | Hold | | 13 | [Compile-time metaprogramming](stories/language-runtime-database/13-compile-time-metaprogramming.md) | ⬜ needs a spec first | | 14 | [skillhost host workload](stories/language-runtime-database/14-skillhost-host-workload.md) | ⬜ gaps recorded (branch query-grammar found skillhost needs no new query grammar); each gap a candidate iteration | -| 15 | [deps: `wo.toml [deps]`](stories/language-runtime-database/15-deps-package-manager.md) | ⬜ spec'd 2026-08-18 (web-framework spec §A); the enabler for 16 | +| 15 | [deps: `wo.toml [deps]`](stories/language-runtime-database/15-deps-package-manager.md) | ✅ **landed 2026-08-18** (branch web-framework): [deps] inline tables, git-binary fetch, wo.lock pinning, offline-when-locked, --update-deps, WO-E106/E107; `just deps-accept` 8/0 | | 16 | [web framework](stories/language-runtime-database/16-web-framework.md) | ⬜ spec'd 2026-08-18 (§B; h2c parked §C behind 8/9f/11); TLS proxy-terminated by decision | --- @@ -320,7 +320,6 @@ The C proving-ground work (`exploration/c-runtime/`, phases A–F: 859k reads/s, | 9f | io_uring group-commit write path — batched durability overlapped on shard threads, fsync fallback | **no spec yet** — brainstorm after iterations 8 + 9e | | 9g | Query grammar from real embedded-DB corpora — whole-query count + correlated exists, driven by the skillhost SQL catalogue; add only what a corpus uses | **no spec yet** — three forks; may collapse to "confirm len(query) + add exists" | | 14 | skillhost host workload — port skillhost (MCP host + confined script runner) to writeonce; drives the missing host capabilities into the open (bounded subprocess, stdin/stdout transport, fs metadata, FFI-vs-out-of-process) | **no spec yet** — gaps recorded in the iteration; each gap brainstormed on demand, bounded-subprocess first | -| 15 | deps — `wo.toml [deps]` exact-rev git fetch, `wo.lock`, `.wo-deps` cache, `use ` resolution; flat-only v1 | [spec §A](superpowers/specs/2026-08-18-web-framework-design.md) · [plan](superpowers/plans/2026-08-18-deps-package-manager.md) | | 16 | web framework — `.wo` library (HTTP/1.1 keep-alive behind a TLS-terminating proxy), Handler/Middleware interfaces, @table data layer; web-app sample consumes via [deps] | [spec §B](superpowers/specs/2026-08-18-web-framework-design.md) — depends on 15; h2c parked (§C) behind 8/9f/11 | | 10 | HTTP service layer | [plan 6](superpowers/plans/2026-08-01-http-service-layer.md) | | 11 | Fibers | vision §3, [blue-green exploration](plan/exploration/blue-green-vm/00-vision.md) | diff --git a/docs/08-project-structure.md b/docs/08-project-structure.md index ddc7e9e..f388b8a 100644 --- a/docs/08-project-structure.md +++ b/docs/08-project-structure.md @@ -118,5 +118,8 @@ ASan, single-binary smoke, both unit gates). Sample acceptance: - Plan/spec files: `YYYY-MM-DD-.md` under `docs/superpowers/{specs,plans}/`; compiler plans under `docs/plan/compiler/`; normative contracts under `docs/plan/oop-vm/`. +- A project's dependencies (iteration 15): `wo.toml [deps]` declares + exact-rev git deps; they fetch to `.wo-deps//` (gitignored) and pin + in `wo.lock` (committed). - Sample projects live under `docs/examples//` with their own `wo.toml` and module `justfile`. diff --git a/docs/plan/oop-vm/01-error-catalog.md b/docs/plan/oop-vm/01-error-catalog.md index 851dbd0..193b146 100644 --- a/docs/plan/oop-vm/01-error-catalog.md +++ b/docs/plan/oop-vm/01-error-catalog.md @@ -34,6 +34,8 @@ half of the story ("moved here" / "borrowed here" / etc.). | WO-E101 | generic syntax error: an unexpected token where the grammar expected something else, including running off the end of the file inside an unclosed block/type/interface body. Declaration-level recovery syncs to the next top-level keyword so one bad declaration yields one diagnostic, not a cascade. | `expected ')' or ',', got NEWLINE` | | WO-E102 | an invalid `@table(...)` configuration: `name` given twice, an `index` with no columns, or an argument key other than `name`/`index`. | `@table(name: ...) given twice` | | WO-E103 | haxe-parity Task 2. `inline fn ...` — the haxe keyword verdict table's own reject half of the `inline` row (`const` values are the adopted half). The whole declaration is discarded by the usual top-level recovery, same as any other bad declaration. | `` `inline fn` is rejected — optimization is the compiler's job `` | +| WO-E106 | iteration 15 (deps, 2026-08-18). A dependency fetch/shape failure, driver-level: missing `git` binary, clone/checkout failure, a locked commit missing from the remote, cache/lock drift (a moved `rev` — the message names both SHAs and points at `woc --update-deps`), a fetched dep that is not a writeonce project, or a dep declaring its own `[deps]` (transitive — refused flat-only). One code; the message names the dependency and the failing step. | `` dependency `niceframework`: lock drift — wo.lock pins but .wo-deps has (a moved `rev`?); run `woc --update-deps` or remove .wo-deps/niceframework `` | +| WO-E107 | iteration 15 (deps). A `[deps]` name collides with a local top-level module directory of the same name — `use ` would be ambiguous, so the build refuses instead of silently picking one. | `` dependency `niceframework` collides with the local module directory `niceframework/` `` | | WO-E105 | iteration 5 strictness (2026-08-18). A rejected Haxe keyword used where it would otherwise misparse — or, worst, compile clean (`return super.f()` used to): `extends`/`implements` after a class name, and `extends`/`implements`/`super`/`override`/`cast`/`Dynamic`/`untyped`/`macro`/`extern`/`operator` as an expression head or a top-level declaration head. Each cites the systems-track verdict table's doctrine reason. (`Dynamic`/`untyped` as a *type name* fire WO-E225 with the same doctrine message.) | `` `extends` is rejected: no inheritance, ever — is-a is a tagged union, has-a is composition, polymorphism is structural interfaces (principle 4) `` | | WO-E104 | iteration 7b. `@gc` on a class — the annotation is gone: GC-ness is inferred (structural cycles + demand promotion; `woc --dump-gc`). The annotation is skipped for recovery and the class classifies by inference. | `` `@gc` is not a valid annotation: GC-ness is inferred by the compiler (run `woc --dump-gc`). Remove it. `` | diff --git a/docs/stories/language-runtime-database/15-deps-package-manager.md b/docs/stories/language-runtime-database/15-deps-package-manager.md index 9c7cfb1..f2f509a 100644 --- a/docs/stories/language-runtime-database/15-deps-package-manager.md +++ b/docs/stories/language-runtime-database/15-deps-package-manager.md @@ -3,8 +3,13 @@ > Format: fiberloom `product/story-iteration-template`. Part of > [Story — one language, one runtime, one database, one binary](00-story.md). > -> **Inserted 2026-08-18.** The enabler for code shared between writeonce -> repositories — the web framework (iteration 16) is the driving consumer. +> **Inserted 2026-08-18. LANDED the same day** (branch `web-framework`): all +> acceptance criteria met — `just deps-accept` 8/0 (cold fetch + lock, use +> and /sub, offline-when-locked with the remote deleted, +> lock-beats-moved-tag, --update-deps, drift/transitive/collision +> diagnostics WO-E106/E107, dep `fn main` never the entry, manifest shape). +> The enabler for code shared between writeonce repositories — the web +> framework (iteration 16) is the driving consumer. > > **Spec exists:** [`2026-08-18-web-framework-design.md`](../../superpowers/specs/2026-08-18-web-framework-design.md) > section A is normative for this iteration. **Plan:** diff --git a/docs/superpowers/plans/2026-08-18-deps-package-manager.md b/docs/superpowers/plans/2026-08-18-deps-package-manager.md index e419fc5..f48b0b1 100644 --- a/docs/superpowers/plans/2026-08-18-deps-package-manager.md +++ b/docs/superpowers/plans/2026-08-18-deps-package-manager.md @@ -51,43 +51,43 @@ section A (normative). Story: [`15-deps-package-manager.md`](../../stories/langu **Files:** modify `compiler/bin/main.ml` (manifest_parse + its doc comment). -- [ ] Extend the value grammar with the one-line inline table — a braced, +- [x] Extend the value grammar with the one-line inline table — a braced, comma-separated list of `key = "string"` pairs — accepted ONLY under `[deps]`; anywhere else it stays "only quoted string values are supported". Inside it, `git` and `rev` are required, both non-empty; any other key is the existing unknown-key error. Section whitelist gains `deps`. -- [ ] Represent each entry as (name, git URL, rev) in the parsed manifest; +- [x] Represent each entry as (name, git URL, rev) in the parsed manifest; a duplicate dep name is the duplicate-key error family. -- [ ] Verify: a manifest with a well-formed `[deps]` parses (no behavior +- [x] Verify: a manifest with a well-formed `[deps]` parses (no behavior yet); a missing `rev`, a bare unquoted value, and an inline table outside `[deps]` each produce their named diagnostic. Run `just woc-test` — all existing golden/manifest behavior unchanged. -- [ ] Commit. +- [x] Commit. ## Task 2 — resolver: fetch, cache, lock **Files:** modify `compiler/bin/main.ml` (a `resolve_deps` step inside manifest_build, before discovery); `.gitignore` (`.wo-deps/`). -- [ ] Layout: `.wo-deps//` beside `wo.toml`; `wo.lock` beside it too — +- [x] Layout: `.wo-deps//` beside `wo.toml`; `wo.lock` beside it too — one line per dep, name and resolved commit SHA, sorted, with a one-line header comment naming the generator. -- [ ] Cold path (no lock entry or no cache dir): run `git clone` into the +- [x] Cold path (no lock entry or no cache dir): run `git clone` into the cache dir and `git -C checkout `, then read the resolved SHA via `git -C rev-parse HEAD`; write/refresh the lock entry. Every git invocation's failure is WO-E106 naming the dep, the URL/rev, and which step failed. A missing `git` binary is its own WO-E106 message. -- [ ] Warm path (lock entry present, cache dir present): compare the cache's +- [x] Warm path (lock entry present, cache dir present): compare the cache's HEAD SHA to the lock; equal means proceed with zero network. A cache matching the manifest `rev` label but not the lock (a moved tag) is WO-E106 "lock drift" naming both SHAs and pointing at `--update-deps`. -- [ ] `woc --update-deps `: re-fetches every dep at its manifest rev and +- [x] `woc --update-deps `: re-fetches every dep at its manifest rev and rewrites the lock; document in the usage text. -- [ ] Guard rails, each its own diagnostic: the fetched dep has no `wo.toml` +- [x] Guard rails, each its own diagnostic: the fetched dep has no `wo.toml` or no `name` (not a writeonce project); the dep's `wo.toml` contains `[deps]` (transitive — refused flat-only, per spec); the dep name collides with a local top-level module directory in the app (WO-E107). -- [ ] Verify manually against a local `file://` remote: cold build fetches +- [x] Verify manually against a local `file://` remote: cold build fetches and writes the lock; second build is offline (prove by running with `GIT_TRACE` absent and the remote renamed away); tag-move produces the drift diagnostic; `--update-deps` clears it. Commit. @@ -97,22 +97,22 @@ manifest_build, before discovery); `.gitignore` (`.wo-deps/`). **Files:** modify `compiler/bin/main.ml` (discovery + `module_of` + entry candidate filtering in manifest_build's pipeline call). -- [ ] Discovery: after resolve_deps, discover each dep root exactly as the +- [x] Discovery: after resolve_deps, discover each dep root exactly as the app root is discovered (same skip rules — dot-dirs, `target/`, and now `.wo-deps/` itself under the app root so dep trees are never discovered twice) and append its files to the compilation unit list. Deterministic order: app files first (sorted, as today), then deps sorted by name. -- [ ] Module mapping: `module_of` for a dep file prefixes the dep name — the +- [x] Module mapping: `module_of` for a dep file prefixes the dep name — the dep's root maps to module ``, its subdirectory `sub/` to `/sub` — so the existing `use` resolution, collision diagnostics, and `pub` visibility work across the boundary with no changes in `types.ml`. -- [ ] Entry restriction: the `main` the emitter selects (and WO-E405 checks) +- [x] Entry restriction: the `main` the emitter selects (and WO-E405 checks) must come from the app root's own files; a dep's `fn main` is never an entry candidate. The spec's rule "a dep's main is ignored" means exactly the selection filter — the fn itself still compiles as an ordinary module-scoped fn. -- [ ] Verify: an app importing one dep via `use ` and `use /sub` +- [x] Verify: an app importing one dep via `use ` and `use /sub` builds and runs; the dep having its own `fn main` changes nothing; `woc --dump-owner`/`--dump-bc` on the app still work (multi-file dump conventions apply to dep files like any other unit). Commit. @@ -124,15 +124,15 @@ candidate filtering in manifest_build's pipeline call). script builds its `file://` remotes in a temp dir at run time, so nothing network-shaped or `.git`-shaped is committed). -- [ ] The gate script, one check per behavior, log-watcher-accept style: +- [x] The gate script, one check per behavior, log-watcher-accept style: (1) cold fetch + lock written + app runs; (2) offline rebuild with the remote removed; (3) moved-tag drift diagnostic; (4) `--update-deps` refresh; (5) transitive-dep refusal; (6) dep-name/local-module collision; (7) dep `fn main` ignored — app's entry wins; (8) missing-`rev` manifest diagnostic. Exit nonzero on the first failure, count summary at the end. -- [ ] `just deps-accept` wired; run it plus `just woc-test` and +- [x] `just deps-accept` wired; run it plus `just woc-test` and `just oop-e2e` — all green, nothing pre-existing re-blessed. -- [ ] Commit. +- [x] Commit. ## Task 5 — docs closeout @@ -142,7 +142,7 @@ network-shaped or `.git`-shaped is committed). story `15-deps-package-manager.md` (status note), `docs/08-project-structure.md` (`.wo-deps/` + `wo.lock` in the project-layout listing). -- [ ] Apply; `just deps-accept` still green; commit. +- [x] Apply; `just deps-accept` still green; commit. ## Success criteria (from the story, restated as the gate)