Establish the project-as-crate authoring loop: aura new, Aura.toml discovery, cdylib vocabulary loading #180

Closed
opened 2026-07-02 14:16:57 +02:00 by Brummel · 11 comments
Owner

Reference issue for the milestone "Project environment — the project-as-crate authoring loop". Seeded from a chat-ratified milestone decision (provenance below); fork decisions made autonomously during the milestone run are logged as comments here.

Decision provenance

Chosen 2026-07-02 as the next milestone from a grounded comparison of six candidate thrusts, each assessed against the design ledger (docs/design/INDEX.md), the code, and the tracker. The user ratified the recommendation verbatim: "ok" (2026-07-02).

Alternatives considered and set aside:

  • Validation instrumentation (a fusion of #172 real-data block-bootstrap MC, #124 instrument/cost resolution tiers, and conditional R-curve analysis): without a project tier there are no real external signals to condition, and its paired-run comparison family would pull composable-orchestration design in ad hoc.
  • Composable orchestration / World-as-library (#147): no consumer until projects exist; the natural successor once this milestone ships.
  • Construction consolidation (#159-adjacent polish): its ready parts dissolve into other tracks; not milestone-shaped.
  • Live/deploy edge (#149): design-open by its own text; the record-then-replay and frozen-deploy layers it needs have no realization yet.
  • Visual face II: the ledger marks the playground's form downstream-and-optional while naming the unbuilt World halves elsewhere.

Sequencing revision (recorded)

An earlier recorded sequencing decision placed this layer late — "after the World layer ships and the experiment API hardens". The World families shipped (milestone "World/C21: run + orchestrate harness families from blueprint-data", closed 2026-07-01). The experiment API has not hardened, but C24 (the blueprint as a serializable, World-owned data value; docs/design/INDEX.md) changed what that precondition gates: a v1 project layer needs only project node logic plus a vocabulary resolver, not the experiment-builder API. That seam is built and tested today: blueprint_from_json resolves each primitive's type identity through an injected &dyn Fn(&str) -> Option<PrimitiveBuilder> (crates/aura-engine/src/blueprint_serde.rs:165), and the std vocabulary's charter names the project-cdylib path through the same seam (crates/aura-std/src/vocabulary.rs:1-10). Experiments therefore stay CLI-verb-driven within this milestone.

Scope

In:

  • Design of the load boundary: the cdylib contract (exported vocabulary entry point; load-and-hold lifetime — never unload while builder closures live; same-toolchain verification, refuse-don't-guess — C13 fixes same-toolchain Rust ABI and forbids foreign-toolchain plugins, docs/design/INDEX.md), the project-resolver charter (project vocabulary plus std vocabulary, closed set, collision policy), and the Aura.toml v1 schema (static project context only, never logic — C17, the no-DSL contract).
  • #171 settled ahead of the first external consumer: once real project artifacts exist, any later content-id canonicalization becomes a breaking change against them.
  • Engine loader: project-cdylib load, toolchain check, merged-resolver injection into blueprint loading and construction.
  • CLI project awareness: cargo-style walk-up discovery of Aura.toml as the project root; per-invocation load of the project's cdylib; registry/runs-dir from Aura.toml (replaces the cwd-bound default noted at crates/aura-cli/src/main.rs:1510-1512).
  • aura new scaffolder: cdylib crate-type, empty [workspace] table, engine dependencies, a sample node plus blueprint, Aura.toml, a project CLAUDE.md fragment.
  • Authoring-loop end-to-end: edit a project node, cargo build, and the next aura invocation resolves the new dylib through the blueprint verbs (run/sweep/mc/walkforward/graph build/introspect/reproduce); a guard that no single run ever spans a reload (C1 — one deterministic run, one binary state).
  • Milestone fieldtest as a genuine external consumer: a real project crate outside this repo, public surface only.

Out (deferred, each with its home):

  • Experiments-in-crate / the experiment-builder library API — the composable-orchestration half of the World layer (#147).
  • Freeze/deploy and the live broker edge (#149).
  • Hard-wired-harness retirement (#159): gated on serializable sinks/brokers — the recording sinks capture an mpsc::Sender and construction-arg builders (LinComb(arity), CostSum(n_costs), SimBroker(pip_size), Session(..)) are deliberately absent from the resolvable vocabulary (crates/aura-std/src/vocabulary.rs:11-16, the scope note from #155) — so a project signal keeps running through the existing R-harness wrapping within this milestone.
> Reference issue for the milestone "Project environment — the project-as-crate authoring loop". Seeded from a chat-ratified milestone decision (provenance below); fork decisions made autonomously during the milestone run are logged as comments here. ## Decision provenance Chosen 2026-07-02 as the next milestone from a grounded comparison of six candidate thrusts, each assessed against the design ledger (docs/design/INDEX.md), the code, and the tracker. The user ratified the recommendation verbatim: "ok" (2026-07-02). Alternatives considered and set aside: - Validation instrumentation (a fusion of #172 real-data block-bootstrap MC, #124 instrument/cost resolution tiers, and conditional R-curve analysis): without a project tier there are no real external signals to condition, and its paired-run comparison family would pull composable-orchestration design in ad hoc. - Composable orchestration / World-as-library (#147): no consumer until projects exist; the natural successor once this milestone ships. - Construction consolidation (#159-adjacent polish): its ready parts dissolve into other tracks; not milestone-shaped. - Live/deploy edge (#149): design-open by its own text; the record-then-replay and frozen-deploy layers it needs have no realization yet. - Visual face II: the ledger marks the playground's form downstream-and-optional while naming the unbuilt World halves elsewhere. ## Sequencing revision (recorded) An earlier recorded sequencing decision placed this layer late — "after the World layer ships and the experiment API hardens". The World families shipped (milestone "World/C21: run + orchestrate harness families from blueprint-data", closed 2026-07-01). The experiment API has not hardened, but C24 (the blueprint as a serializable, World-owned data value; docs/design/INDEX.md) changed what that precondition gates: a v1 project layer needs only project node logic plus a vocabulary resolver, not the experiment-builder API. That seam is built and tested today: `blueprint_from_json` resolves each primitive's type identity through an injected `&dyn Fn(&str) -> Option<PrimitiveBuilder>` (crates/aura-engine/src/blueprint_serde.rs:165), and the std vocabulary's charter names the project-cdylib path through the same seam (crates/aura-std/src/vocabulary.rs:1-10). Experiments therefore stay CLI-verb-driven within this milestone. ## Scope In: - Design of the load boundary: the cdylib contract (exported vocabulary entry point; load-and-hold lifetime — never unload while builder closures live; same-toolchain verification, refuse-don't-guess — C13 fixes same-toolchain Rust ABI and forbids foreign-toolchain plugins, docs/design/INDEX.md), the project-resolver charter (project vocabulary plus std vocabulary, closed set, collision policy), and the Aura.toml v1 schema (static project context only, never logic — C17, the no-DSL contract). - #171 settled ahead of the first external consumer: once real project artifacts exist, any later content-id canonicalization becomes a breaking change against them. - Engine loader: project-cdylib load, toolchain check, merged-resolver injection into blueprint loading and construction. - CLI project awareness: cargo-style walk-up discovery of Aura.toml as the project root; per-invocation load of the project's cdylib; registry/runs-dir from Aura.toml (replaces the cwd-bound default noted at crates/aura-cli/src/main.rs:1510-1512). - `aura new` scaffolder: cdylib crate-type, empty [workspace] table, engine dependencies, a sample node plus blueprint, Aura.toml, a project CLAUDE.md fragment. - Authoring-loop end-to-end: edit a project node, cargo build, and the next aura invocation resolves the new dylib through the blueprint verbs (run/sweep/mc/walkforward/graph build/introspect/reproduce); a guard that no single run ever spans a reload (C1 — one deterministic run, one binary state). - Milestone fieldtest as a genuine external consumer: a real project crate outside this repo, public surface only. Out (deferred, each with its home): - Experiments-in-crate / the experiment-builder library API — the composable-orchestration half of the World layer (#147). - Freeze/deploy and the live broker edge (#149). - Hard-wired-harness retirement (#159): gated on serializable sinks/brokers — the recording sinks capture an `mpsc::Sender` and construction-arg builders (`LinComb(arity)`, `CostSum(n_costs)`, `SimBroker(pip_size)`, `Session(..)`) are deliberately absent from the resolvable vocabulary (crates/aura-std/src/vocabulary.rs:11-16, the scope note from #155) — so a project signal keeps running through the existing R-harness wrapping within this milestone.
Brummel added the feature label 2026-07-02 14:16:57 +02:00
Brummel added this to the Project environment — the project-as-crate authoring loop milestone 2026-07-02 14:17:30 +02:00
Author
Owner

Design decisions — the project-as-crate load boundary (settled autonomously)

Method: ten enumerated forks were populated by five opposed synthetic-user stances, each answer carrying a source citation or an explicit ungrounded flag; forks converging on cited ground were decided as grounded, splits were resolved by derivation from repo sources, and the two riskiest derivations were adversarially reviewed — both reviews upheld the conclusion while pinning one missing constraint each (items 1 and 4). All decisions are vetoable. Status: design settled — ready for spec production.

  1. Export protocol: one versioned descriptor symbol, two ABI tiers. Options: a single query-fn export / a table-fn export / a descriptor struct. Chosen: descriptor — with the pinned constraint that the compatibility stamp is a C-ABI-readable prefix (#[repr(C)], C-typed fields only) verified before any Rust-ABI field (resolver fn, type list) is touched: a stamp cannot certify the channel it is itself transported by. Ground: the export surface is at least three items anyway (resolver + enumerable type list + stamp — crates/aura-std/src/vocabulary.rs:58-64 documents that a fn(&str)->Option<...> resolver cannot be listed, so introspection reads the list), and separately-dlsym'd lockstep symbols are the same drift class #160 guards against in std_vocabulary's hand-synced copies.

  2. Stamp content: rustc version + aura-core crate version; mismatch refuses (runtime failure, exit 1). PrimitiveBuilder is an aura-core type crossing the boundary from the project's own aura-core compilation (crates/aura-engine/src/blueprint_serde.rs:165), so layout compatibility requires both the toolchain (C13, the same-toolchain hot-reload contract) and the crate version; a build-profile/feature fingerprint guards no named risk and is deferred until one is demonstrated.

  3. Panic across the boundary: propagate. A load-boundary catch_unwind cannot guard an eval-time panic in the run loop (category mismatch); the CLI is one-shot per invocation, so propagation and process-abort coincide; the codebase has no catch_unwind precedent and the exit-code taxonomy (docs/design/INDEX.md:1080-1086) keeps a loud crash the honest authoring-bug signal.

  4. Vocabulary identity: duplicate-id hard error plus a mandatory ::-namespace prefix for project ids. Options: bare ids + hard collision error / project shadows std / std shadows project / namespaced ids. Chosen: hard error AND prefix charter — project type-ids carry a namespace prefix (<ns>::Vwap), std ids stay bare, the loader refuses unprefixed project ids and any duplicate in the merged project ∪ std set. Bare ids with only a collision error leave a stale-reference hole: when aura-std later ships a node name a project already used, the forced project rename makes OLD project blueprints silently resolve the bare id to the new std node — a silent wrong graph, which the load path forbids (crates/aura-engine/src/blueprint_serde.rs:105). Prefixing closes the hole structurally while no external blueprint artifacts exist yet. Pinned constraint from adversarial review: the separator must be disjoint from the param-path dot — a dot-prefixed type id would flow through the op-script default-name rule (lowercased type label, docs/design/INDEX.md:1983) into node names containing '.', corrupting the by-name param address space check_param_namespace_injective protects — hence ::, and the default-name rule strips the namespace (type myproj::Vwap → default node name vwap). One verification rides into spec production: member_key filesystem sanitization for param paths containing ::.

  5. Zero-arg restriction inherited. Project vocabularies resolve zero-argument builders only, exactly as std_vocabulary scopes itself (crates/aura-std/src/vocabulary.rs:11-18); construction-arg widening remains the queued additive extension (#156), shared by std and project through the same seam.

  6. v1 export surface: vocabulary only. No composite/blueprint-factory exports — a composite already travels as pure data (NodeData::Composite recursion, crates/aura-engine/src/blueprint_serde.rs:44-47), and factory exports would smuggle compiled topology back past the blueprint-as-data contract (C24).

  7. Aura.toml v1: paths only. IN: the data archive root and the runs dir — both replace live hardcoded placeholders (crates/aura-cli/src/main.rs:1510-1512; the ingest DEFAULT_DATA_PATH) — plus the project namespace. OUT: instrument/pip metadata — the C15 realization deleted the authored floor (cycle 0074) and #124 collapsed to recorded-sidecar-geometry-or-refuse; docs/project-layout.md:33 is stale on this point and is corrected this cycle. OUT: default symbol/window/broker — no present consumer; deferred demand-driven per the repeatedly ratified default-simple discipline.

  8. Build responsibility: the author builds; aura only loads. The authoring-surface contract already assigns the build step to the author ("writes the Rust, builds it, runs it via the aura CLI" — docs/design/INDEX.md:1206-1208); aura reports which dylib it loaded (path + stamp) instead of orchestrating cargo. Recorded v1 reading of C13's "hot-reload": per-invocation load of the freshest build — the process restart IS the reload; no in-process swap exists.

  9. Loader home: a module inside aura-cli. The engine cannot hold it (it stays vocabulary-agnostic — crates/aura-std/src/vocabulary.rs:7-8), and the repo's ratified precedents are extract-on-second-consumer (the aura-analysis split, C16 realization) and research-side dependencies confined to the leaf binary (the clap admission, C14 realization); libloading enters under the same per-case review and can never be linked into the frozen deploy artifact.

  10. Dylib location: cargo metadata. A hand-rolled target/ convention silently loads the wrong artifact under custom target dirs or workspace setups, and an authored path field in Aura.toml is the redundant-authored-state shape the C15 realization already deleted once; asking cargo's own introspection cannot diverge from what cargo built. Profile: debug by default (cargo's own default), release opt-in per invocation; a missing artifact refuses with a build hint.

  11. Enumerable companion required. The descriptor carries the type-id list beside the resolver (the std_vocabulary_types pattern); at load, every listed id is cross-checked to resolve, so build-free introspection can never silently omit project types.

  12. Run provenance: the manifest records the loaded project dylib. A run built from project logic is no longer identified by the engine commit alone — the same gap the registry contract's refinement named for topology (docs/design/INDEX.md:1305-1313), one layer down. RunManifest gains a Tier-1 additive project-provenance field: a content hash of the loaded dylib, plus the project git commit best-effort.

  13. Load-and-hold scope boundary goes into the ledger. The never-unload rule is trivially satisfied only because the CLI is one-shot per invocation; a future long-running host (the open local-server thread) must re-solve reload (host restart or subprocess isolation), never in-process dlclose. To be recorded with the C13 realization when the cycle lands.

  14. Multi-crate composition inside a project. A project's exported vocabulary is ONE merged set the project composes in ordinary Rust (chaining the tables of its shared node-crate dependencies); the loader sees only the merged result and applies the same duplicate refusal; per-crate ::-prefixes are the recommended convention for shared crates.

Rejected framings, recorded: inverting the host relation (the project as top-level binary statically linking the CLI as a library — no dylib at all) contradicts the ratified milestone frame ("the aura host loads and runs it", docs/project-layout.md:24-25; C13/C16) and forfeits the shared-binary UX for no cited gain. A post-load behavioural canary as a substitute for the stamp was set aside: a canary cannot prove layout compatibility; the two-tier C-ABI stamp is the sound gate.

## Design decisions — the project-as-crate load boundary (settled autonomously) Method: ten enumerated forks were populated by five opposed synthetic-user stances, each answer carrying a source citation or an explicit ungrounded flag; forks converging on cited ground were decided as grounded, splits were resolved by derivation from repo sources, and the two riskiest derivations were adversarially reviewed — both reviews upheld the conclusion while pinning one missing constraint each (items 1 and 4). All decisions are vetoable. Status: design settled — ready for spec production. 1. **Export protocol: one versioned descriptor symbol, two ABI tiers.** Options: a single query-fn export / a table-fn export / a descriptor struct. Chosen: descriptor — with the pinned constraint that the compatibility stamp is a **C-ABI-readable prefix** (`#[repr(C)]`, C-typed fields only) verified **before** any Rust-ABI field (resolver fn, type list) is touched: a stamp cannot certify the channel it is itself transported by. Ground: the export surface is at least three items anyway (resolver + enumerable type list + stamp — crates/aura-std/src/vocabulary.rs:58-64 documents that a `fn(&str)->Option<...>` resolver cannot be listed, so introspection reads the list), and separately-dlsym'd lockstep symbols are the same drift class #160 guards against in std_vocabulary's hand-synced copies. 2. **Stamp content: rustc version + aura-core crate version; mismatch refuses (runtime failure, exit 1).** `PrimitiveBuilder` is an aura-core type crossing the boundary from the project's own aura-core compilation (crates/aura-engine/src/blueprint_serde.rs:165), so layout compatibility requires both the toolchain (C13, the same-toolchain hot-reload contract) and the crate version; a build-profile/feature fingerprint guards no named risk and is deferred until one is demonstrated. 3. **Panic across the boundary: propagate.** A load-boundary `catch_unwind` cannot guard an eval-time panic in the run loop (category mismatch); the CLI is one-shot per invocation, so propagation and process-abort coincide; the codebase has no `catch_unwind` precedent and the exit-code taxonomy (docs/design/INDEX.md:1080-1086) keeps a loud crash the honest authoring-bug signal. 4. **Vocabulary identity: duplicate-id hard error plus a mandatory `::`-namespace prefix for project ids.** Options: bare ids + hard collision error / project shadows std / std shadows project / namespaced ids. Chosen: hard error AND prefix charter — project type-ids carry a namespace prefix (`<ns>::Vwap`), std ids stay bare, the loader refuses unprefixed project ids and any duplicate in the merged project ∪ std set. Bare ids with only a collision error leave a stale-reference hole: when aura-std later ships a node name a project already used, the forced project rename makes OLD project blueprints silently resolve the bare id to the new std node — a silent wrong graph, which the load path forbids (crates/aura-engine/src/blueprint_serde.rs:105). Prefixing closes the hole structurally while no external blueprint artifacts exist yet. Pinned constraint from adversarial review: the separator must be disjoint from the param-path dot — a dot-prefixed type id would flow through the op-script default-name rule (lowercased type label, docs/design/INDEX.md:1983) into node names containing '.', corrupting the by-name param address space `check_param_namespace_injective` protects — hence `::`, and the default-name rule strips the namespace (type `myproj::Vwap` → default node name `vwap`). One verification rides into spec production: member_key filesystem sanitization for param paths containing `::`. 5. **Zero-arg restriction inherited.** Project vocabularies resolve zero-argument builders only, exactly as std_vocabulary scopes itself (crates/aura-std/src/vocabulary.rs:11-18); construction-arg widening remains the queued additive extension (#156), shared by std and project through the same seam. 6. **v1 export surface: vocabulary only.** No composite/blueprint-factory exports — a composite already travels as pure data (`NodeData::Composite` recursion, crates/aura-engine/src/blueprint_serde.rs:44-47), and factory exports would smuggle compiled topology back past the blueprint-as-data contract (C24). 7. **Aura.toml v1: paths only.** IN: the data archive root and the runs dir — both replace live hardcoded placeholders (crates/aura-cli/src/main.rs:1510-1512; the ingest DEFAULT_DATA_PATH) — plus the project namespace. OUT: instrument/pip metadata — the C15 realization deleted the authored floor (cycle 0074) and #124 collapsed to recorded-sidecar-geometry-or-refuse; docs/project-layout.md:33 is stale on this point and is corrected this cycle. OUT: default symbol/window/broker — no present consumer; deferred demand-driven per the repeatedly ratified default-simple discipline. 8. **Build responsibility: the author builds; aura only loads.** The authoring-surface contract already assigns the build step to the author ("writes the Rust, builds it, runs it via the aura CLI" — docs/design/INDEX.md:1206-1208); aura reports which dylib it loaded (path + stamp) instead of orchestrating cargo. Recorded v1 reading of C13's "hot-reload": per-invocation load of the freshest build — the process restart IS the reload; no in-process swap exists. 9. **Loader home: a module inside aura-cli.** The engine cannot hold it (it stays vocabulary-agnostic — crates/aura-std/src/vocabulary.rs:7-8), and the repo's ratified precedents are extract-on-second-consumer (the aura-analysis split, C16 realization) and research-side dependencies confined to the leaf binary (the clap admission, C14 realization); `libloading` enters under the same per-case review and can never be linked into the frozen deploy artifact. 10. **Dylib location: `cargo metadata`.** A hand-rolled `target/` convention silently loads the wrong artifact under custom target dirs or workspace setups, and an authored path field in Aura.toml is the redundant-authored-state shape the C15 realization already deleted once; asking cargo's own introspection cannot diverge from what cargo built. Profile: debug by default (cargo's own default), release opt-in per invocation; a missing artifact refuses with a build hint. 11. **Enumerable companion required.** The descriptor carries the type-id list beside the resolver (the `std_vocabulary_types` pattern); at load, every listed id is cross-checked to resolve, so build-free introspection can never silently omit project types. 12. **Run provenance: the manifest records the loaded project dylib.** A run built from project logic is no longer identified by the engine commit alone — the same gap the registry contract's refinement named for topology (docs/design/INDEX.md:1305-1313), one layer down. `RunManifest` gains a Tier-1 additive project-provenance field: a content hash of the loaded dylib, plus the project git commit best-effort. 13. **Load-and-hold scope boundary goes into the ledger.** The never-unload rule is trivially satisfied only because the CLI is one-shot per invocation; a future long-running host (the open local-server thread) must re-solve reload (host restart or subprocess isolation), never in-process dlclose. To be recorded with the C13 realization when the cycle lands. 14. **Multi-crate composition inside a project.** A project's exported vocabulary is ONE merged set the project composes in ordinary Rust (chaining the tables of its shared node-crate dependencies); the loader sees only the merged result and applies the same duplicate refusal; per-crate `::`-prefixes are the recommended convention for shared crates. Rejected framings, recorded: inverting the host relation (the project as top-level binary statically linking the CLI as a library — no dylib at all) contradicts the ratified milestone frame ("the aura host loads and runs it", docs/project-layout.md:24-25; C13/C16) and forfeits the shared-binary UX for no cited gain. A post-load behavioural canary as a substitute for the stamp was set aside: a canary cannot prove layout compatibility; the two-tier C-ABI stamp is the sound gate.
Author
Owner

Spec auto-sign (cycle 0102)

The cycle-0102 spec (docs/specs/0102-project-load-boundary.md — the project-as-crate load boundary: two-tier cdylib descriptor, loader with stamp gate and vocabulary charter, Aura.toml walk-up discovery, merged project-plus-std resolution across all blueprint verbs, manifest provenance) is signed. The signature is a grounding-check PASS: 7 load-bearing assumptions about current behaviour, each ratified by a named currently-green test; greenfield surfaces have no current behaviour to ratify and were excluded per that agent's contract. No human signed; the sign is vetoable and reverts forward (the spec commit is unpushed).

One refinement over the design-decision log recorded earlier on this issue: Aura.toml v1 carries strictly paths (data archive root, runs dir) and NO namespace field — the project namespace lives solely in the dylib descriptor, so it cannot drift against a second authored copy; the same anti-drift rationale that excluded the dylib path and the instrument/pip fields.

## Spec auto-sign (cycle 0102) The cycle-0102 spec (docs/specs/0102-project-load-boundary.md — the project-as-crate load boundary: two-tier cdylib descriptor, loader with stamp gate and vocabulary charter, Aura.toml walk-up discovery, merged project-plus-std resolution across all blueprint verbs, manifest provenance) is signed. The signature is a grounding-check PASS: 7 load-bearing assumptions about current behaviour, each ratified by a named currently-green test; greenfield surfaces have no current behaviour to ratify and were excluded per that agent's contract. No human signed; the sign is vetoable and reverts forward (the spec commit is unpushed). One refinement over the design-decision log recorded earlier on this issue: Aura.toml v1 carries strictly paths (data archive root, runs dir) and NO namespace field — the project namespace lives solely in the dylib descriptor, so it cannot drift against a second authored copy; the same anti-drift rationale that excluded the dylib path and the instrument/pip fields.
Author
Owner

Design reconciliation (specify, cycle 0103 — the aura new scaffolder)

The scaffolder's design is settled by the sources (the scope list in this issue's body, docs/project-layout.md, and the cycle-0102 fixture crates/aura-cli/tests/fixtures/demo-project/ as the living template). Two load-bearing forks resolved before spec production:

  • Fork: which engine-dependency line the scaffolded Cargo.toml carries (path dep vs git URL vs placeholder) → path dependencies on the engine checkout, defaulting to the engine root baked into the aura binary at compile time, overridable via --engine-path, refusing with a hint when the default path no longer exists. Basis: derived — the engine is unpublished (workspace Cargo.toml: publish = false, proprietary), so crates.io is not an option; a git-URL dep would embed a host-specific URL in every scaffold and can pin a revision whose aura-core version differs from the running host binary's, provoking exactly the stamp refusal the load boundary exists to catch; a path dep on the host binary's own engine root makes the C13 same-toolchain/same-core stamp match hold by construction, and the cycle-0102 fixture (the template) already builds this way. A stale baked default fails loud (refuse + --engine-path hint), never silent.
  • Fork: namespace derivation → default namespace = the project name with dashes mapped to underscores (a valid Rust-identifier-ish prefix for the ns::Type charter), overridable via --namespace. Basis: derived — predictable one-to-one mapping from the one argument the user already supplies, mirroring cargo's crate-name normalization; the charter validates it at load anyway.

Minor shapes going straight into the spec (cargo-new-mirror conventions, not preference forks): refusal on an existing target directory (runtime refusal, exit 1), best-effort git init, no cargo build inside the scaffolder (the author builds — the cycle-0102 decision that aura only loads).

## Design reconciliation (specify, cycle 0103 — the aura new scaffolder) The scaffolder's design is settled by the sources (the scope list in this issue's body, docs/project-layout.md, and the cycle-0102 fixture crates/aura-cli/tests/fixtures/demo-project/ as the living template). Two load-bearing forks resolved before spec production: - **Fork: which engine-dependency line the scaffolded Cargo.toml carries** (path dep vs git URL vs placeholder) → path dependencies on the engine checkout, defaulting to the engine root baked into the aura binary at compile time, overridable via --engine-path, refusing with a hint when the default path no longer exists. Basis: derived — the engine is unpublished (workspace Cargo.toml: publish = false, proprietary), so crates.io is not an option; a git-URL dep would embed a host-specific URL in every scaffold and can pin a revision whose aura-core version differs from the running host binary's, provoking exactly the stamp refusal the load boundary exists to catch; a path dep on the host binary's own engine root makes the C13 same-toolchain/same-core stamp match hold by construction, and the cycle-0102 fixture (the template) already builds this way. A stale baked default fails loud (refuse + --engine-path hint), never silent. - **Fork: namespace derivation** → default namespace = the project name with dashes mapped to underscores (a valid Rust-identifier-ish prefix for the `ns::Type` charter), overridable via --namespace. Basis: derived — predictable one-to-one mapping from the one argument the user already supplies, mirroring cargo's crate-name normalization; the charter validates it at load anyway. Minor shapes going straight into the spec (cargo-new-mirror conventions, not preference forks): refusal on an existing target directory (runtime refusal, exit 1), best-effort git init, no cargo build inside the scaffolder (the author builds — the cycle-0102 decision that aura only loads).
Author
Owner

Spec auto-sign (cycle 0103)

The cycle-0103 spec (docs/specs/0103-aura-new-scaffolder.md — the aura new scaffolder: one command emits a buildable, runnable project crate parameterized from the cycle-0102 fixture; path-dep engine wiring per the reconciliation comment above in this thread, dated 2026-07-02; a load-bypass so scaffolding works inside unbuilt trees) is signed. The signature is a grounding-check PASS: 8 load-bearing current-behaviour assumptions, each ratified by a named currently-green test. No human signed; the sign is vetoable and reverts forward (the spec commit is unpushed).

## Spec auto-sign (cycle 0103) The cycle-0103 spec (docs/specs/0103-aura-new-scaffolder.md — the aura new scaffolder: one command emits a buildable, runnable project crate parameterized from the cycle-0102 fixture; path-dep engine wiring per the reconciliation comment above in this thread, dated 2026-07-02; a load-bypass so scaffolding works inside unbuilt trees) is signed. The signature is a grounding-check PASS: 8 load-bearing current-behaviour assumptions, each ratified by a named currently-green test. No human signed; the sign is vetoable and reverts forward (the spec commit is unpushed).
Author
Owner

Auto-sign: spec 0104 — topology-identity hash (#171)

Cycle 0104's spec (docs/specs/0104-topology-identity-hash.md, committed b3a2e9c) was signed autonomously via a grounding-check PASS (independent fresh-context agent), per the /boss auto-sign protocol. A vetoable notify was sent.

What the spec covers: an additive identity hash — two blueprints expressing the same topology (op-script-built vs Rust-builder-built, or twins differing only in debug names) get the same id via aura graph introspect --identity-id. The identity projection blanks every non-load-bearing debug symbol (composite name, instance names, bound-param names, role names, output names) while keeping everything load-bearing (type ids, node order, edges, role targets+order, output pairs+order, bound positions/kinds/values — so param openness stays identity-bearing). topology_hash and all three of its roles (introspect content id, reproduction-store key, reproduce fetch anchor) stay byte-for-byte untouched; no manifest field and no store keyed by the identity hash this cycle (deferred until a consumer exists). Design basis: the cycle-0104 reconciliation comment on #171 (the refuted "redefine topology_hash" shape → sibling id).

Grounding evidence (all five current-behaviour assumptions ratified by named green tests):

  1. Byte-canonical golden pin — signal_serializes_to_canonical_golden (aura-engine blueprint_serde).
  2. --content-id contract incl. bad-doc refusal — graph_introspect_content_id_is_deterministic_and_distinguishes (+ ..._rejects_a_bad_document).
  3. The three topology_hash roles — topology_hash_is_the_content_id_of_the_canonical_form, blueprint_store_round_trips_by_content_id, aura_reproduce_re_derives_a_persisted_sweep_family, plus content_id_is_stable_across_the_store_round_trip.
  4. Existing distinguishing property (bound I64:4 vs 5 → different id) — same introspect test, line 254.
  5. Openness textually encoded via the bound array (bound slot present, open slot absent) — the golden test's fast-bound / slow-open shape.

Reviewer notes carried into planning (non-blocking):

  • Allowing --content-id --identity-id together relaxes the current exactly-one flag dispatch (graph_construct.rs, count!=1 → exit 2). The usage tests must be adjusted deliberately.
  • The "reproduce recovers params by name" statement is design rationale for the sibling-id choice, ratified indirectly by the reproduce e2e — not a precondition of the additive feature.

Status: spec signed and committed; the cycle is ready for planning and implementation.

## Auto-sign: spec 0104 — topology-identity hash (#171) Cycle 0104's spec (`docs/specs/0104-topology-identity-hash.md`, committed `b3a2e9c`) was signed autonomously via a grounding-check PASS (independent fresh-context agent), per the /boss auto-sign protocol. A vetoable notify was sent. **What the spec covers:** an additive identity hash — two blueprints expressing the same topology (op-script-built vs Rust-builder-built, or twins differing only in debug names) get the same id via `aura graph introspect --identity-id`. The identity projection blanks every non-load-bearing debug symbol (composite name, instance names, bound-param names, role names, output names) while keeping everything load-bearing (type ids, node order, edges, role targets+order, output pairs+order, bound positions/kinds/values — so param openness stays identity-bearing). `topology_hash` and all three of its roles (introspect content id, reproduction-store key, reproduce fetch anchor) stay byte-for-byte untouched; no manifest field and no store keyed by the identity hash this cycle (deferred until a consumer exists). Design basis: the cycle-0104 reconciliation comment on #171 (the refuted "redefine topology_hash" shape → sibling id). **Grounding evidence (all five current-behaviour assumptions ratified by named green tests):** 1. Byte-canonical golden pin — `signal_serializes_to_canonical_golden` (aura-engine blueprint_serde). 2. `--content-id` contract incl. bad-doc refusal — `graph_introspect_content_id_is_deterministic_and_distinguishes` (+ `..._rejects_a_bad_document`). 3. The three `topology_hash` roles — `topology_hash_is_the_content_id_of_the_canonical_form`, `blueprint_store_round_trips_by_content_id`, `aura_reproduce_re_derives_a_persisted_sweep_family`, plus `content_id_is_stable_across_the_store_round_trip`. 4. Existing distinguishing property (bound I64:4 vs 5 → different id) — same introspect test, line 254. 5. Openness textually encoded via the `bound` array (bound slot present, open slot absent) — the golden test's `fast`-bound / `slow`-open shape. **Reviewer notes carried into planning (non-blocking):** - Allowing `--content-id --identity-id` together *relaxes* the current exactly-one flag dispatch (graph_construct.rs, count!=1 → exit 2). The usage tests must be adjusted deliberately. - The "reproduce recovers params by name" statement is design rationale for the sibling-id choice, ratified indirectly by the reproduce e2e — not a precondition of the additive feature. Status: spec signed and committed; the cycle is ready for planning and implementation.
Author
Owner

Cycle 0104 closed — topology-identity hash landed (#171)

Commits b3a2e9c (spec, boss-signed) → 39cbd44 (plan) → 45fb06d (implementation, closes #171 on push) → 7b429f9 (audit close, drift-clean). Suite 884 passed / 0 failed (873 baseline + 11 new); clippy and doc build clean; every existing pin (canonical golden, --content-id, topology_hash, store round-trip, reproduce e2e) green unchanged.

What shipped: blueprint_identity_json (aura-engine; canonical form with all non-load-bearing debug symbols blanked, C23/invariant 11) + aura graph introspect --identity-id beside --content-id, sharing the one content_id SHA-256 primitive. Same topology → same identity id across authoring paths (op-script vs Rust builder, renamed twins), proven by a cross-path twin test and e2e. The introspect dispatch was deliberately relaxed: the two id flags form one group and may combine (one build, both ids, one per line, content id first) — with a new usage string and a test on the previously uncovered count!=1 exit-2 path.

Derived decisions this iteration (orchestrator, recorded for audit):

  • Two extra engine property tests kept. The implementation loop added nested_composite_interior_names_are_identity_blind and renamed_role_and_output_share_identity_json_not_canonical_json beyond the plan's four. Derived: kept — they differentially cover the recursion arm and the role/output strip arms, which the planned tests never exercised; the architect confirmed them as genuinely distinct, non-redundant coverage.
  • Verification-task block resolved by hand-run gates. The loop's final task (full regression) blocked on spec-compliance because the plan pinned test counts that under-counted pre-existing tests (6 vs 7 in the serde module) and could not anticipate the two extra tests (expected 882 vs actual 884). Derived: a plan-byte counting defect, not a code defect — all four gates were re-run by hand and are green; no re-dispatch needed for a verification-only task.
  • Glossary record-reality entries. content id, identity id (Avoid: identity hash, topology-identity hash), and topology hash added to docs/glossary.md — the terms are now user-facing CLI surface; README and ledger aligned to the canonical term.

Audit drift review: three doc-mirror items (two stale #171-deferral passages in the design ledger, the README introspect table, the glossary gap), all resolved inline in the audit-close commit. Whole-harness / structural-axis content-addressing remains deferred; the identity id stays introspection-only (no manifest field, no store key) until a dedup consumer exists — the deferral recorded on #171.

Status: cycle closed drift-clean; milestone queue continues with the vocabulary three-copy guard (#160).

## Cycle 0104 closed — topology-identity hash landed (#171) Commits `b3a2e9c` (spec, boss-signed) → `39cbd44` (plan) → `45fb06d` (implementation, `closes #171` on push) → `7b429f9` (audit close, drift-clean). Suite 884 passed / 0 failed (873 baseline + 11 new); clippy and doc build clean; every existing pin (canonical golden, `--content-id`, `topology_hash`, store round-trip, reproduce e2e) green unchanged. **What shipped:** `blueprint_identity_json` (aura-engine; canonical form with all non-load-bearing debug symbols blanked, C23/invariant 11) + `aura graph introspect --identity-id` beside `--content-id`, sharing the one `content_id` SHA-256 primitive. Same topology → same identity id across authoring paths (op-script vs Rust builder, renamed twins), proven by a cross-path twin test and e2e. The introspect dispatch was deliberately relaxed: the two id flags form one group and may combine (one build, both ids, one per line, content id first) — with a new usage string and a test on the previously uncovered count!=1 exit-2 path. **Derived decisions this iteration (orchestrator, recorded for audit):** - **Two extra engine property tests kept.** The implementation loop added `nested_composite_interior_names_are_identity_blind` and `renamed_role_and_output_share_identity_json_not_canonical_json` beyond the plan's four. Derived: kept — they differentially cover the recursion arm and the role/output strip arms, which the planned tests never exercised; the architect confirmed them as genuinely distinct, non-redundant coverage. - **Verification-task block resolved by hand-run gates.** The loop's final task (full regression) blocked on spec-compliance because the plan pinned test counts that under-counted pre-existing tests (6 vs 7 in the serde module) and could not anticipate the two extra tests (expected 882 vs actual 884). Derived: a plan-byte counting defect, not a code defect — all four gates were re-run by hand and are green; no re-dispatch needed for a verification-only task. - **Glossary record-reality entries.** `content id`, `identity id` (Avoid: identity hash, topology-identity hash), and `topology hash` added to docs/glossary.md — the terms are now user-facing CLI surface; README and ledger aligned to the canonical term. Audit drift review: three doc-mirror items (two stale #171-deferral passages in the design ledger, the README introspect table, the glossary gap), all resolved inline in the audit-close commit. Whole-harness / structural-axis content-addressing remains deferred; the identity id stays introspection-only (no manifest field, no store key) until a dedup consumer exists — the deferral recorded on #171. Status: cycle closed drift-clean; milestone queue continues with the vocabulary three-copy guard (#160).
Author
Owner

Auto-sign: spec 0105 — std-vocabulary roster macro (#160)

Cycle 0105's spec (docs/specs/0105-std-vocabulary-roster-macro.md, committed 103a82d) was signed autonomously via a grounding-check PASS (independent fresh-context agent), per the /boss auto-sign protocol. A vetoable notify was sent.

What the spec covers: the three hand-kept copies of the std-vocabulary roster in crates/aura-std/src/vocabulary.rs (the std_vocabulary match arms, the std_vocabulary_types() list, the test's inline 22-key list) collapse into one declarative-macro source (std_vocabulary_roster!, invoked once with the "TypeId" => Type pairs). Byte-preserving: both fn signatures, the 22 ids, and their order unchanged; every consumer untouched; the vocabulary stays a closed compiled-in set (invariant 9 / C24 — compile-time expansion, no registry). Adding a zero-arg node becomes one roster line plus a conscious count-pin bump. Accepted residual per the #160 reconciliation: a node never rostered at all stays unguarded (no zero-arg-builder enumeration exists) and fails safe in both directions.

Grounding evidence (all seven current-behaviour assumptions ratified by named green tests): the two vocabulary unit tests (std_vocabulary_resolves_known_and_rejects_unknown, std_vocabulary_types_lists_exactly_the_resolvable_keys), the PrimitiveBuilder::label() oracle (asserted inside the first), and the consumer pins graph_introspect_vocabulary_lists_the_node_types, unknown_node_type_fails_named, the tests/project_load.rs merged-vocabulary suite (introspect_vocabulary_lists_project_types, vocabulary_charter_violation_refuses_end_to_end), and signal_serializes_to_canonical_golden. Reviewer note: no consumer test pins the list order — the spec commits to preserving it anyway (trivially held by the macro's literal expansion).

Status: spec signed and committed; the cycle is ready for planning and implementation.

## Auto-sign: spec 0105 — std-vocabulary roster macro (#160) Cycle 0105's spec (`docs/specs/0105-std-vocabulary-roster-macro.md`, committed `103a82d`) was signed autonomously via a grounding-check PASS (independent fresh-context agent), per the /boss auto-sign protocol. A vetoable notify was sent. **What the spec covers:** the three hand-kept copies of the std-vocabulary roster in `crates/aura-std/src/vocabulary.rs` (the `std_vocabulary` match arms, the `std_vocabulary_types()` list, the test's inline 22-key list) collapse into one declarative-macro source (`std_vocabulary_roster!`, invoked once with the `"TypeId" => Type` pairs). Byte-preserving: both fn signatures, the 22 ids, and their order unchanged; every consumer untouched; the vocabulary stays a closed compiled-in set (invariant 9 / C24 — compile-time expansion, no registry). Adding a zero-arg node becomes one roster line plus a conscious count-pin bump. Accepted residual per the #160 reconciliation: a node never rostered at all stays unguarded (no zero-arg-builder enumeration exists) and fails safe in both directions. **Grounding evidence (all seven current-behaviour assumptions ratified by named green tests):** the two vocabulary unit tests (`std_vocabulary_resolves_known_and_rejects_unknown`, `std_vocabulary_types_lists_exactly_the_resolvable_keys`), the `PrimitiveBuilder::label()` oracle (asserted inside the first), and the consumer pins `graph_introspect_vocabulary_lists_the_node_types`, `unknown_node_type_fails_named`, the `tests/project_load.rs` merged-vocabulary suite (`introspect_vocabulary_lists_project_types`, `vocabulary_charter_violation_refuses_end_to_end`), and `signal_serializes_to_canonical_golden`. Reviewer note: no consumer test pins the list *order* — the spec commits to preserving it anyway (trivially held by the macro's literal expansion). Status: spec signed and committed; the cycle is ready for planning and implementation.
Author
Owner

Cycle 0105 closed — std-vocabulary roster macro landed (#160)

Commits 103a82d (spec, boss-signed) → e0c745a (plan) → 57f401f (implementation, closes #160 on push) → bd32c4f (audit close, drift-clean). Suite 885 passed / 0 failed (884 baseline + 1 new e2e); clippy and doc build clean; every consumer pin green unchanged.

What shipped: the three hand-kept copies of the 22-key zero-arg roster in crates/aura-std/src/vocabulary.rs (resolver match arms, std_vocabulary_types() list, test inline array) collapsed into one private std_vocabulary_roster! macro invoked once — resolver and enumerable list now agree by construction, closing the #160 drift mode. Byte-preserving (same signatures, keys, order; lib.rs and every consumer untouched); the vocabulary stays a closed compiled-in set (invariant 9 / C24, compile-time expansion, no registry). Adding a zero-arg node is one roster line plus the conscious count-pin bumps.

Derived decisions this iteration (orchestrator, recorded for audit):

  • Extra e2e count pin kept. The implementation loop added graph_introspect_vocabulary_lists_exactly_the_closed_roster_count beyond the plan (which predicted "no new test, 884 unchanged"). Derived: kept — it pins the roster count through Env::type_ids() and the CLI print loop across the real process boundary, a plumbing path no roster-internal test can see; the plan's acceptance line was consciously superseded and disclosed in the iter commit body.
  • Audit close-fixes. The roster-site doc comment now names both count pins a node addition trips (the second lives in aura-cli, invisible from the roster site — the singular phrasing understated the cross-crate friction); the C24 enforcement-shift passage in the design ledger gained the 0105 delivery note (resolver-vs-list drift closed by construction; the un-rostered-node residual stays fail-safe, per the deferral recorded on this milestone's #160 reconciliation).

Status: cycle closed drift-clean. Milestone queue: #181 (template↔fixture lockstep, needs a design pass) and the milestone fieldtest remain.

## Cycle 0105 closed — std-vocabulary roster macro landed (#160) Commits `103a82d` (spec, boss-signed) → `e0c745a` (plan) → `57f401f` (implementation, `closes #160` on push) → `bd32c4f` (audit close, drift-clean). Suite 885 passed / 0 failed (884 baseline + 1 new e2e); clippy and doc build clean; every consumer pin green unchanged. **What shipped:** the three hand-kept copies of the 22-key zero-arg roster in `crates/aura-std/src/vocabulary.rs` (resolver match arms, `std_vocabulary_types()` list, test inline array) collapsed into one private `std_vocabulary_roster!` macro invoked once — resolver and enumerable list now agree by construction, closing the #160 drift mode. Byte-preserving (same signatures, keys, order; `lib.rs` and every consumer untouched); the vocabulary stays a closed compiled-in set (invariant 9 / C24, compile-time expansion, no registry). Adding a zero-arg node is one roster line plus the conscious count-pin bumps. **Derived decisions this iteration (orchestrator, recorded for audit):** - **Extra e2e count pin kept.** The implementation loop added `graph_introspect_vocabulary_lists_exactly_the_closed_roster_count` beyond the plan (which predicted "no new test, 884 unchanged"). Derived: kept — it pins the roster count through `Env::type_ids()` and the CLI print loop across the real process boundary, a plumbing path no roster-internal test can see; the plan's acceptance line was consciously superseded and disclosed in the iter commit body. - **Audit close-fixes.** The roster-site doc comment now names both count pins a node addition trips (the second lives in aura-cli, invisible from the roster site — the singular phrasing understated the cross-crate friction); the C24 enforcement-shift passage in the design ledger gained the 0105 delivery note (resolver-vs-list drift closed by construction; the un-rostered-node residual stays fail-safe, per the deferral recorded on this milestone's #160 reconciliation). Status: cycle closed drift-clean. Milestone queue: #181 (template↔fixture lockstep, needs a design pass) and the milestone fieldtest remain.
Author
Owner

Decision log: #181 resolved by ledger declaration (2026-07-02)

The template-vs-fixture lockstep question (#181) is resolved via its option (c): the aura-new templates are declared the canonical project shape, the 0102 demo-project fixture an intentionally frozen known-good twin — no equality test, no fixture regeneration. Full options/rationale (incl. the skeptic-pass correction of an over-claimed guard rationale) are reproduced self-contained in issues/181#issuecomment — see the resolution comment on #181 dated 2026-07-02. Ledger note landed in docs/design/INDEX.md (commit 81ac6fd, closes #181 on push).

Status: the milestone's substantive work items (#171, #160, #181) are all resolved in local history; the milestone fieldtest is the remaining close gate.

## Decision log: #181 resolved by ledger declaration (2026-07-02) The template-vs-fixture lockstep question (#181) is resolved via its option (c): the aura-new templates are declared the canonical project shape, the 0102 demo-project fixture an intentionally frozen known-good twin — no equality test, no fixture regeneration. Full options/rationale (incl. the skeptic-pass correction of an over-claimed guard rationale) are reproduced self-contained in issues/181#issuecomment — see the resolution comment on #181 dated 2026-07-02. Ledger note landed in docs/design/INDEX.md (commit 81ac6fd, closes #181 on push). Status: the milestone's substantive work items (#171, #160, #181) are all resolved in local history; the milestone fieldtest is the remaining close gate.
Author
Owner

Milestone fieldtest GREEN — close gate satisfied (2026-07-02)

The end-to-end milestone fieldtest ran as a downstream consumer from the public interface only (no engine source, no engine tests) and returned GREEN with 0 bugs: scaffold -> build -> deterministic run with project provenance; a genuinely authored node through rebuild -> op-script build -> run (provenance tracking the fresh dylib); renamed-twin id semantics (content ids differ, identity ids equal, combinable output); misuse paths refused with named causes. Evidence corpus committed at fieldtests/milestone-project-environment/ (commit ad83a4b).

Findings triage: F3/F6 (doc-gaps) fixed inline (commit 6915624); F1 (nested git init gitlink) -> #182; F2 (parameterized starter node, highest-value gap) -> #183; F4 (loader UnknownNodeType Debug-leak on the run path) -> #184; F5 (missing-Aura.toml hint) -> #185. None blocks the milestone.

Status: every milestone work item (#171, #160, #181) is resolved in local history (commits close them on push), audit-closed drift-clean, suite 885/0, and the milestone fieldtest is green. The formal milestone close and the push are user-reserved acts; #182-#185 are post-milestone polish awaiting triage.

## Milestone fieldtest GREEN — close gate satisfied (2026-07-02) The end-to-end milestone fieldtest ran as a downstream consumer from the public interface only (no engine source, no engine tests) and returned GREEN with 0 bugs: scaffold -> build -> deterministic run with project provenance; a genuinely authored node through rebuild -> op-script build -> run (provenance tracking the fresh dylib); renamed-twin id semantics (content ids differ, identity ids equal, combinable output); misuse paths refused with named causes. Evidence corpus committed at fieldtests/milestone-project-environment/ (commit ad83a4b). Findings triage: F3/F6 (doc-gaps) fixed inline (commit 6915624); F1 (nested git init gitlink) -> #182; F2 (parameterized starter node, highest-value gap) -> #183; F4 (loader UnknownNodeType Debug-leak on the run path) -> #184; F5 (missing-Aura.toml hint) -> #185. None blocks the milestone. Status: every milestone work item (#171, #160, #181) is resolved in local history (commits close them on push), audit-closed drift-clean, suite 885/0, and the milestone fieldtest is green. The formal milestone close and the push are user-reserved acts; #182-#185 are post-milestone polish awaiting triage.
Author
Owner

Milestone formally closed (2026-07-04)

All milestone work items (#171, #160, #181) shipped and auto-closed on the
2026-07-03 push (d7c935d..6915624); the close gate was satisfied by the green
milestone fieldtest (evidence corpus committed at
fieldtests/milestone-project-environment/, commit ad83a4b, 0 bugs).

Post-milestone polish triage since: #182 closed 2026-07-04 as resolved by the
shipped #204 fix (aura new skips git init inside an existing work tree —
the fix matches the shape this milestone's fieldtest finding F1 proposed);
#183 (parameterized starter node), #184 (loader prose), #185 (missing-Aura.toml
hint) remain open as detached polish.

The Gitea milestone container "Project environment — the project-as-crate
authoring loop" is closed together with this reference issue.

## Milestone formally closed (2026-07-04) All milestone work items (#171, #160, #181) shipped and auto-closed on the 2026-07-03 push (d7c935d..6915624); the close gate was satisfied by the green milestone fieldtest (evidence corpus committed at fieldtests/milestone-project-environment/, commit ad83a4b, 0 bugs). Post-milestone polish triage since: #182 closed 2026-07-04 as resolved by the shipped #204 fix (aura new skips git init inside an existing work tree — the fix matches the shape this milestone's fieldtest finding F1 proposed); #183 (parameterized starter node), #184 (loader prose), #185 (missing-Aura.toml hint) remain open as detached polish. The Gitea milestone container "Project environment — the project-as-crate authoring loop" is closed together with this reference issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#180