Commit Graph

10 Commits

Author SHA1 Message Date
claude b39fd63396 refactor: split the aura-std roster into C28 layer crates
Phase 4 of the Stratification milestone. aura-std held four C28 ladder
layers in one roster; this cuts them into layer-aligned, aura-core-only
node crates so the import direction is enforced by the crate graph:

- aura-std        — engine nodes only (arithmetic/logic/rolling + sinks)
- aura-market     — session, resample
- aura-strategy   — bias, stops, sizer, cost-model machinery
- aura-backtest   — sim_broker, position_management
- aura-vocabulary — the relocated closed std_vocabulary roster

Node modules move verbatim (byte-identical renames); consumers are
rewired by import path only. A new structural test
(aura-vocabulary/tests/c28_layering.rs) asserts each node crate's
[dependencies] stay within its C28-permitted inner set, catching the
acyclic-but-outward violation the compiler misses.

Behaviour byte-identical: full workspace suite green (1448 tests), no
golden edited, clippy -D warnings clean. C28 Status block updated.

closes #288
2026-07-19 20:28:20 +02:00
claude 1ccce9ad32 fix(test): anchor all test sandboxes on reclaimable pid-free names
Every hand-rolled test-sandbox helper keyed its directory on
std::process::id() under env::temp_dir(), so the pre-create wipe never
matched a prior run's path: one directory stranded per helper site per
test-binary invocation, >50k dirs / 15.5 GiB on the 16 GiB tmpfs by
2026-07-13.

The remedy extends commit 84e1075's knob-lab pattern to every site:
fixed, tag-keyed, PID-FREE names under the build-tree tmp anchor, each
site keeping its pre-create remove_dir_all — which now genuinely
reclaims the previous run. Integration/bench targets use
env!("CARGO_TARGET_TMPDIR"); src-internal unit-test helpers (cargo sets
that var only for integration/bench targets) derive the same anchor
from env!("CARGO_MANIFEST_DIR") + ../../target/tmp. Residue is bounded
to one directory per site, on disk instead of the tmpfs, per checkout.

One deliberate exception: project_new.rs's tmp() stays under
env::temp_dir() because two of its tests (new_outside_a_work_tree_*)
need a base genuinely detached from any git work tree, and target/
lives inside the checkout's work tree. Its name carries a per-checkout
hash discriminator instead, so concurrently running checkouts (which
share /tmp) cannot race on the fixed name while each run still
reclaims its predecessor.

tempfile-RAII was considered and rejected (issue #258 decision log):
it cannot cover the process-lifetime OnceLock scaffolds (statics never
drop), adds a dependency, and still strands kill-leftovers on the
tmpfs.

Verified: full workspace suite green (incl. the new RED regression
test temp_cwd_sandbox_does_not_leak_under_env_temp_dir), clippy clean,
sandboxes observed under target/tmp with stable names across runs.
Stale pre-fix PID-keyed dirs in /tmp are not swept by this change and
age out only by manual cleanup.

closes #258
2026-07-13 20:15:31 +02:00
claude a04fda3a4c fix(cli): resolve a relative paths.data against the project root
Env::data_path() handed paths.data to the data layer verbatim, so a
relative value resolved against the invoking process's cwd — aura run
from a project subdirectory silently read a different archive location
than from the root, while runs/ stayed anchored. Relative values now
join onto the project root, matching runs_root() and the [nodes]
pointer resolution; absolute values and the no-project default pass
through unchanged. RED-first unit test pins the root-anchored
resolution.

closes #254
2026-07-13 16:44:28 +02:00
claude d79d5af036 fix(cli): a missing [nodes] directory refuses with a clean message
An existence pre-check on the [nodes] pointer target fires before the
crate pipeline: the refusal names the absent directory and keeps the
[nodes] context, instead of leaking cargo metadata's os-error wrap.
Existing-but-broken crates keep the ArtifactMissing/CargoMetadata
errors under the pointer prefix.

closes #245
2026-07-12 19:52:01 +02:00
claude c3b5099014 test(cli): RED — a missing [nodes] dir leaks the cargo metadata error (#245)
RED pin: a_missing_nodes_pointer_dir_refuses_without_the_cargo_metadata_leak
(project.rs unit tests) — the refusal must name the absent directory and
keep the [nodes] context, with no cargo-metadata wrap.

refs #245
2026-07-12 19:33:43 +02:00
claude 0170ec277f docs: two-tier project model — layout, guide, glossary, ledger, invariant 9 (#241 T7)
- CLAUDE.md invariant 9 amended end to end: a project is a directory
  anchored by a static Aura.toml, data-only by default; native node
  logic lives in attached node crates (the nodes/ antecedent removed —
  user decision 2026-07-12, re-opened by the role model's diagnosis).
- docs/project-layout.md reworked to the two tiers (data-only default
  tree + sibling node crate, workspace note under the crate half); the
  day-in-the-life walkthrough now attaches the project's node crate
  once and wires the namespace the shown command actually produces.
- docs/authoring-guide.md: data-only quickstart (closed run target,
  open sweep target) + `aura nodes new` as the native entry; section
  cross-reference updated.
- docs/glossary.md: new "data-only project" and "node crate" entries;
  Aura.toml and manifest entries carry the tier split.
- docs/design/INDEX.md: realization note (wiring-only tier, #241) in
  the project-environment section.
- rustdoc: `[nodes]` intra-doc-link escapes in project.rs/main.rs.

Full gates green: workspace suite (all binaries), clippy -D warnings,
doc build without new warnings.

closes #241
2026-07-12 17:45:59 +02:00
claude 23bb978bf2 feat(cli): aura nodes new — node-crate scaffold + attach (#241 T5-T6)
- New clap family `aura nodes new <name> [--engine-path] [--namespace]`:
  scaffolds a node crate as a SIBLING of the project root (Cargo.toml
  with the aura-core path-dep, the parameterized Scale starter node,
  roster macro, crate-scoped .gitignore + CLAUDE.md, own git repo) and
  appends the `[nodes] crates = ["../<name>"]` pointer to the project's
  Aura.toml. Refuses outside a project, on any existing [nodes] section
  (incl. an empty crates array), and on an existing destination; joins
  the load-phase bypass beside `aura new` (a scaffolder must work in an
  unbuilt tree).
- The old single-tier scaffold() is gone; the crate templates live on
  in scaffold_node_crate; dead-code bridges removed with their callers.
- tests/project_nodes.rs: attach + refusals + namespace override + the
  full role-2 loop (scaffold, cargo build, vocabulary resolves
  <ns>::Scale end to end).
- tests/project_sweep_campaign.rs fixture reworked to the two-tier
  shape (aura new + aura nodes new --namespace knob_lab); the two
  campaign acceptance tests are byte-unchanged and green.

refs #241
2026-07-12 17:08:47 +02:00
claude 1f6b55a8e1 feat(cli,engine): data-only project tier at the load boundary (#241 T1-T2)
- ProjectProvenance namespace/dylib_sha256 widen to Option (Tier-1
  additive serde): a data-only run stamps commit-only provenance; old
  string-field manifests keep parsing.
- The load boundary tier-selects: a [nodes] pointer list in Aura.toml
  (one entry honored; MultiCrate / pointer-context refusals) loads the
  pointed-at crate; a root Cargo.toml stays the pre-#241 native project,
  unchanged; neither means data-only (std vocabulary, project-local
  runs/, both-tier provenance).
- ProjectEnv splits into directory facts + Option<NativeEnv>; the crate
  pipeline (metadata -> artifact -> staleness -> ABI -> charter)
  relocates byte-identical into load_crate.
- e2e fixtures: dataonly-project, multicrate-project,
  nested-nodes-project (a pointer crate resolves and stamps its
  namespace end to end).

refs #241
2026-07-12 14:42:57 +02:00
Brummel e44b0cbb3e feat(cli): warn when the loaded project dylib is stale against the source tree
Editing a project's src/ without cargo build silently ran the previous
dylib with plausible stale numbers — the role-2 authoring-loop footgun.
The loader now compares the newest mtime under src/ + Cargo.toml against
the dylib's mtime right after the ArtifactMissing check and prints one
stderr warning naming both timestamps (hand-rolled Hinnant
civil_from_days render, no new dependency), then proceeds unchanged:
warn, never refuse — a stale run is still deterministic and
manifest-stamped. Every I/O failure in the scan degrades to
skip-and-continue; staleness can never become a refusal. Fresh builds
stay silent (inverse unit-pinned).

Verified: headline e2e green, project_load 8/8, full workspace suite
green, clippy -D warnings clean; independent quality review approved.

closes #237
2026-07-10 21:04:00 +02:00
Brummel 4928e289f7 feat(project): the project-as-crate load boundary (cycle 0102)
A research project is now a loadable external cdylib crate. Inside a
directory whose ancestry holds an Aura.toml, aura discovers the project
root cargo-style, locates the compiled dylib via cargo metadata (debug
default, --release opt-in), loads it load-and-hold, and refuses
mismatches before trusting anything: the AURA_PROJECT descriptor
(aura-core::project, #[repr(C)]) carries a C-ABI stamp prefix (rustc +
aura-core version, baked per consuming build by the new aura-core
build.rs) validated before any Rust-ABI field is read. The vocabulary
charter gates the merged resolution: project type ids are ::-namespaced
(std stays bare), duplicates refuse, and the enumerable type-id list
must agree with the resolver, so introspection can never silently omit
a project type.

All blueprint verbs resolve through the merged project + std vocabulary
via a per-invocation Env threaded through the dispatch chains;
registry, trace-store, and data paths anchor at the project runs root
(Aura.toml [paths], paths-only by design — instrument geometry stays
the recorded sidecar, C15). RunManifest gains the Tier-1 project
provenance field (namespace + dylib sha256 + best-effort commit),
stamped beside topology_hash on the blueprint-run paths; pre-0102
registry lines load unchanged. Default node names strip the namespace,
so :: never reaches the param-path address space.

Proven by the demo-project fixture (built by the e2e via cargo,
path-dep on this workspace): run twice bit-identical, provenance
recorded, introspection lists demo::* beside std, registry anchors at
the discovered root from a subdirectory; the badcharter fixture proves
the charter refusal through the real libloading path; a never-built
project refuses with a cargo-build hint. Outside a project every path
collapses to the previous literals — goldens and manifest pins
byte-identical.

Verification: cargo build --workspace clean; cargo test --workspace 862
passed / 0 failed (incl. 7 project_load e2e); clippy -D warnings clean
(one precedent-matching allow(too_many_arguments) on run_oos_blueprint,
whose arity the Env threading raised to 8); doc build unchanged.
Docs/ledger aligned: Aura.toml field lists are paths-only in
project-layout.md, glossary, C16/C17; new C13 realization note records
the per-invocation-reload reading and the load-and-hold one-shot scope
boundary.

New deps, per-case review (aura-cli leaf binary only, never the frozen
artifact): libloading, toml.

refs #180
2026-07-02 18:13:37 +02:00