diff --git a/.gitattributes b/.gitattributes index dd0629ddc1d..a02eeb1768e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,6 +20,12 @@ .gitignore merge=generated-artifact DESIGN.md merge=generated-artifact ROADMAP.md merge=generated-artifact +dag/examples/js_site/generated/about.html merge=generated-artifact +dag/examples/js_site/generated/about.tsx merge=generated-artifact +dag/examples/js_site/generated/browse.html merge=generated-artifact +dag/examples/js_site/generated/browse.tsx merge=generated-artifact +dag/examples/js_site/generated/home.html merge=generated-artifact +dag/examples/js_site/generated/home.tsx merge=generated-artifact dag/gunbc/stage0/stage0_crate_layout_generated.dag merge=generated-artifact dag/gunbc/stage0/stage0_crate_partition_generated.dag merge=generated-artifact docs/plans/budget-tree.md merge=generated-artifact diff --git a/.gitignore b/.gitignore index c582c2fa7af..542bf990355 100644 --- a/.gitignore +++ b/.gitignore @@ -1,135 +1,157 @@ -# gunbc .gitignore — generated from dag/gunbc/gitignore_authority.dag — do not hand-edit. +# gunbc .gitignore — generated from gunbc.repo_workspace via gunbc.gitignore_emit — do not hand-edit. # -# Rule: Ignore anything that is (a) reproducible from committed source-of-truth files, or (b) environment-specific and not shared across developers. +# Every pattern is declared by its producer (an extdeps product's workspace footprint, or a repo tool's own declaration) with its meaning and a typed ignore reason; the trailing section is derived from gunbc.generated_artifact commit policy. -# --- Cargo build artifacts (from cargo) --- -# Reproducible from source via cargo build +# --- Cargo build artifacts [cited: doc.rust-lang.org/cargo/] --- +# regenerable from committed source — cargo build output tree (compiled artifacts, incremental state) /target/ +# regenerable from committed source — cargo build output tree (compiled artifacts, incremental state) /target-codex/ - -# --- Cargo cache (local CARGO_HOME) (from tool/rust) --- -# Local Cargo cache may include git checkouts; not project state +# local cache; not project state — CARGO_HOME registry/cache; may include git checkouts /.cargo-home/ -# --- Codegen bin symlink (from codegen) --- -# Symlink to target/release created by codegen -/bin/ - -# --- Coverage reports (from cargo-tarpaulin) --- -# Generated, often large, reproducible +# --- Coverage reports (cargo-tarpaulin) [cited: github.com/xd009642/tarpaulin] --- +# regenerable from committed source — HTML coverage report (--out Html) tarpaulin-report.html +# regenerable from committed source — JSON coverage report (--out Json) tarpaulin-report.json +# regenerable from committed source — Cobertura XML coverage report (--out Xml) cobertura.xml +# regenerable from committed source — LCOV coverage report (--out Lcov) lcov.info +# regenerable from committed source — repo-chosen coverage output directory /coverage/ # --- JetBrains IDE project state [cited: jetbrains.com/idea] --- -# Per-developer configuration, not project state +# per-developer state; not shared — per-project IDE workspace configuration .idea/ # --- VS Code workspace state [cited: code.visualstudio.com] --- -# Per-developer configuration, not project state +# per-developer state; not shared — per-folder workspace settings .vscode/ # --- Vim editor state [cited: vim.org] --- -# Per-developer configuration, not project state +# per-developer state; not shared — swap file for an open buffer *.swp +# per-developer state; not shared — secondary swap file *.swo # --- Emacs backup convention [cited: gnu.org/software/emacs] --- -# Per-developer configuration, not project state +# per-developer state; not shared — backup of an edited file *~ -# --- Generic editor backup files [cited: cross-editor backup convention] --- -# Per-developer configuration, not project state -*.bak - # --- macOS Finder metadata [cited: developer.apple.com (Finder metadata)] --- -# OS-generated, not project state +# host OS metadata; not project state — Finder folder-view metadata .DS_Store # --- Windows Explorer cache [cited: microsoft.com (Explorer thumbnail cache)] --- -# OS-generated, not project state +# host OS metadata; not project state — Explorer thumbnail cache Thumbs.db -# --- tmux terminal multiplexer logs [cited: github.com/tmux/tmux (pipe-pane log naming)] --- -# Session log; not project state +# --- tmux pipe-pane session logs [cited: github.com/tmux/tmux (pipe-pane)] --- +# session/runtime state; not source-of-truth — captured pane output from a local session tmux-*.log # --- Secrets and local config [cited: github.com/motdotla/dotenv] --- -# Environment-specific, may contain secrets +# may contain secrets; never committed — environment-specific configuration, commonly secrets .env +# may contain secrets; never committed — local override of .env .env.local +# may contain secrets; never committed — per-environment local overrides .env.*.local -# --- Generator stamp files (from generators) --- -# Producer-centric model stamps +# --- npm installed dependency tree [cited: docs.npmjs.com/cli/configuring-npm/folders] --- +# regenerable from committed source — installed packages materialized from the lockfile +node_modules/ + +# --- CPython bytecode cache [cited: python.org/peps/pep-3147] --- +# regenerable from committed source — PEP 3147 per-directory bytecode cache +__pycache__/ +# regenerable from committed source — compiled bytecode (legacy layout) +*.pyc + +# --- Codegen bin symlink [owner: gunbc.repo_workspace] --- +# regenerable from committed source — symlink to target/release created by codegen +/bin/ + +# --- Generator stamp files [owner: gunbc.generated_artifact] --- +# regenerable from committed source — producer-centric generator stamps .*-stamp -# --- Workflow runtime state (from workflow) --- -# Local execution ledger and config; not source-of-truth +# --- Workflow runtime state [owner: v2.workflow.required_floor] --- +# session/runtime state; not source-of-truth — local execution ledger and config /.gunbc/ -# --- testgen outputs (from testgen) --- -# Generated by testgen; not source-of-truth +# --- testgen outputs [owner: v1.10_test] --- +# regenerable from committed source — tests generated by testgen; not source-of-truth src/v1/10_test/generated-tests/src/generated/ -# --- Node.js [cited: github/gitignore/Node.gitignore] --- -# Not part of this project -node_modules/ - -# --- Claude Code session state --- +# --- Claude Code session state [cited: code.claude.com] --- +# session/runtime state; not source-of-truth — per-clone agent session state .claude/ -# --- Stage0 regeneration temp dirs --- +# --- Stage0 regeneration temp dirs [owner: v1_compiler.required_regen_host] --- +# regenerable from committed source — regen input snapshot .regen-sources/ +# regenerable from committed source — regen emitted candidate .regen-output/ +# regenerable from committed source — regen generated source root .regen-generated-source-root/ +# regenerable from committed source — staleness-check scratch tree .freshness-check/ -# --- Interactive auth/session transcripts --- -# Should never be committed; may contain OAuth URLs or session state +# --- Interactive auth/session transcripts [owner: gunbc.auth.credentials] --- +# may contain secrets; never committed — interactive auth transcript; may contain OAuth URLs or session state out.txt -# --- OpenClaw workspace artifacts --- -# The OpenClaw control plane lives in ~/ctrl, not in this repo +# --- OpenClaw workspace artifacts [owner: gunbc.repo_workspace] --- +# session/runtime state; not source-of-truth — OpenClaw control dir; the control plane lives in ~/ctrl, not this repo /.openclaw/ +# session/runtime state; not source-of-truth — OpenClaw agent roster projection /AGENTS.md +# session/runtime state; not source-of-truth — OpenClaw heartbeat projection /HEARTBEAT.md +# session/runtime state; not source-of-truth — OpenClaw identity projection /IDENTITY.md +# session/runtime state; not source-of-truth — OpenClaw soul projection /SOUL.md +# session/runtime state; not source-of-truth — OpenClaw tools projection /TOOLS.md +# session/runtime state; not source-of-truth — OpenClaw user projection /USER.md +# session/runtime state; not source-of-truth — OpenClaw workboard projection /WORKBOARD.md +# session/runtime state; not source-of-truth — OpenClaw-managed scripts dir /scripts/openclaw/ + +# --- v2 compiler inspect output [owner: gunbc.repo_workspace] --- +# session/runtime state; not source-of-truth — v2 compiler inspect output .v2-inspect +# session/runtime state; not source-of-truth — v2 compiler inspect error output .v2-inspect-errors.txt -# --- GitHub CLI local cache (dashboard / gh API) --- +# --- GitHub CLI local cache [owner: gunbc.repo_workspace] --- +# local cache; not project state — local gh API response cache (dashboard tooling) .gh-cache/ -# --- Python local dev scripts --- -# Python is used only for local dev tooling; never committed to the .dag/.rs substrate +# --- Python local dev scripts [owner: gunbc.repo_workspace] --- +# outside the committed substrate — local dev tooling only; never committed to the .dag/.rs substrate *.py -!docs/plans/witness-subject-execution-audit.py -!docs/probes/e0369_b1_operator_classify.py -!docs/probes/floor_cut_name_resolution_partition.py -!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/summarize.py -!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/adjudicate.py -!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/join_board.py -!docs/probes/e0308_classify_sites.py - -# --- CPython bytecode cache (PEP 3147) [cited: python.org/peps/pep-3147] --- -__pycache__/ -*.pyc -# --- claim-corpus execution-map output --- +# --- Generic editor backup files [cited: cross-editor backup convention] --- +# per-developer state; not shared — editor backup copy +*.bak + +# --- claim-corpus execution-map output [owner: v1_compiler.cli_run] --- +# regenerable from committed source — claim execution map output .claim-map/ +# session/runtime state; not source-of-truth — scratch probe written by manual claim runs src/v2/test/claim/manual/sg2_scratch_probe.dag -# --- Superseded planning scratch directories (canonical home: docs/plans/ or DESIGN.md) --- -# Superseded by docs/plans/ (generated PlanArtifact) and DESIGN.md/ROADMAP.md as canonical authorities +# --- Superseded planning scratch directories [owner: gunbc.plan] --- +# superseded; canonical home: docs/plans/ (generated PlanArtifact) and DESIGN.md — pre-plan-carrier planning scratch /gunbc-planning/ +# superseded; canonical home: docs/plans/ (generated PlanArtifact) and DESIGN.md — pre-plan-carrier fixture scratch /scripts/fixtures/ # --- Generated artifacts (gitignored-by-default, derived from generated_artifact_registry) --- diff --git a/dag/config/codegen_paths.dag b/dag/config/codegen_paths.dag deleted file mode 100644 index 7a9378bebbd..00000000000 --- a/dag/config/codegen_paths.dag +++ /dev/null @@ -1,19 +0,0 @@ -module config.codegen_paths - -data codegen_out_dir: String = "target/codegen" -data bin_dir: String = "target/codegen/bin" -data lib_dir: String = "target/codegen/lib" -data stamp_file: String = "target/codegen/.codegen-stamp" - -data generated_roots: List = [ - "core/ir/src", - "core/exec/src", - "gunbc-app/src", - "generated" -] - -data path_templates: List = [ - "target/codegen/\{module\}.json", - "target/codegen/\{module\}.lock", - "target/codegen/\{module\}.status" -] diff --git a/dag/extdeps/bmc/pid_control_program.dag b/dag/extdeps/bmc/pid_control_program.dag index 0cb361be56d..a4553a32022 100644 --- a/dag/extdeps/bmc/pid_control_program.dag +++ b/dag/extdeps/bmc/pid_control_program.dag @@ -319,5 +319,5 @@ fn decimal_measures_agree(a: Measure, b: Measure Bool { a.index == b.index && decimal_measures_agree(a: a.reading, b: b.reading) - && decimal_measures_agree(a: a.output, b: b.output) + && exact_decimal_equal(a: a.output.magnitude, b: b.output.magnitude) } diff --git a/dag/extdeps/dotenv.dag b/dag/extdeps/dotenv.dag new file mode 100644 index 00000000000..4f1c01fdcce --- /dev/null +++ b/dag/extdeps/dotenv.dag @@ -0,0 +1,26 @@ +module extdeps.dotenv + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, MayContainSecrets } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "github.com/motdotla/dotenv" + } +} + +// WORKSPACE FOOTPRINT. The dotenv convention stores environment-specific configuration — +// commonly credentials — in .env files that must never be committed. +fn dotenv_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Secrets and local config", upstream: "github.com/motdotla/dotenv" }, + artifacts: [ + WorkspaceArtifact { pattern: ".env", meaning: "environment-specific configuration, commonly secrets", reason: MayContainSecrets }, + WorkspaceArtifact { pattern: ".env.local", meaning: "local override of .env", reason: MayContainSecrets }, + WorkspaceArtifact { pattern: ".env.*.local", meaning: "per-environment local overrides", reason: MayContainSecrets } + ] + } +} diff --git a/dag/extdeps/editor/gnu_emacs.dag b/dag/extdeps/editor/gnu_emacs.dag new file mode 100644 index 00000000000..2da790285f2 --- /dev/null +++ b/dag/extdeps/editor/gnu_emacs.dag @@ -0,0 +1,23 @@ +module extdeps.editor.gnu_emacs + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, PerDeveloperState } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "gnu.org/software/emacs" + } +} + +// WORKSPACE FOOTPRINT. Emacs writes backup files beside edited files. +fn emacs_backup_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Emacs backup convention", upstream: "gnu.org/software/emacs" }, + artifacts: [ + WorkspaceArtifact { pattern: "*~", meaning: "backup of an edited file", reason: PerDeveloperState } + ] + } +} diff --git a/dag/extdeps/editor/jetbrains_ide.dag b/dag/extdeps/editor/jetbrains_ide.dag new file mode 100644 index 00000000000..9946d98b09a --- /dev/null +++ b/dag/extdeps/editor/jetbrains_ide.dag @@ -0,0 +1,23 @@ +module extdeps.editor.jetbrains_ide + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, PerDeveloperState } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "jetbrains.com/idea" + } +} + +// WORKSPACE FOOTPRINT. JetBrains IDEs keep per-project workspace state in .idea/. +fn jetbrains_workspace_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "JetBrains IDE project state", upstream: "jetbrains.com/idea" }, + artifacts: [ + WorkspaceArtifact { pattern: ".idea/", meaning: "per-project IDE workspace configuration", reason: PerDeveloperState } + ] + } +} diff --git a/dag/extdeps/editor/vim.dag b/dag/extdeps/editor/vim.dag new file mode 100644 index 00000000000..df6c186bc87 --- /dev/null +++ b/dag/extdeps/editor/vim.dag @@ -0,0 +1,24 @@ +module extdeps.editor.vim + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, PerDeveloperState } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "vim.org" + } +} + +// WORKSPACE FOOTPRINT. Vim writes swap files beside edited files. +fn vim_swap_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Vim editor state", upstream: "vim.org" }, + artifacts: [ + WorkspaceArtifact { pattern: "*.swp", meaning: "swap file for an open buffer", reason: PerDeveloperState }, + WorkspaceArtifact { pattern: "*.swo", meaning: "secondary swap file", reason: PerDeveloperState } + ] + } +} diff --git a/dag/extdeps/editor/visual_studio_code.dag b/dag/extdeps/editor/visual_studio_code.dag new file mode 100644 index 00000000000..570a936490e --- /dev/null +++ b/dag/extdeps/editor/visual_studio_code.dag @@ -0,0 +1,23 @@ +module extdeps.editor.visual_studio_code + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, PerDeveloperState } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "code.visualstudio.com" + } +} + +// WORKSPACE FOOTPRINT. VS Code keeps per-folder workspace settings in .vscode/. +fn vscode_workspace_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "VS Code workspace state", upstream: "code.visualstudio.com" }, + artifacts: [ + WorkspaceArtifact { pattern: ".vscode/", meaning: "per-folder workspace settings", reason: PerDeveloperState } + ] + } +} diff --git a/dag/extdeps/npm.dag b/dag/extdeps/npm.dag index 18a7f4c98d6..c6cf4d378d3 100644 --- a/dag/extdeps/npm.dag +++ b/dag/extdeps/npm.dag @@ -1,6 +1,7 @@ module extdeps.npm import std.types { NonEmptyStr, String, Bool, List, Int } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, RegenerableFromSource } import std.integer { UInt8 } import std.encoding { base64_decode, base64_encode, Standard } import std.content_hash { @@ -944,3 +945,14 @@ fn npm_decode_package_lock_text(text: String) -> NpmPackageLockParse { } } } + +// WORKSPACE FOOTPRINT. npm install materializes the dependency tree under node_modules/; +// it is a projection of the committed lockfile, never source. +fn node_modules_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "npm installed dependency tree", upstream: "docs.npmjs.com/cli/configuring-npm/folders" }, + artifacts: [ + WorkspaceArtifact { pattern: "node_modules/", meaning: "installed packages materialized from the lockfile", reason: RegenerableFromSource } + ] + } +} diff --git a/dag/extdeps/os/macos.dag b/dag/extdeps/os/macos.dag index 8d1373e291e..8f6b4e0b9fc 100644 --- a/dag/extdeps/os/macos.dag +++ b/dag/extdeps/os/macos.dag @@ -9,6 +9,8 @@ import std.os.types { } import extdeps.external_authority { ExternalAuthority } +import std.types { String, List } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, HostOsMetadata } import extdeps.uri { Uri, Https } data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { @@ -35,3 +37,13 @@ fn macos_distribution_catalog_row(distro: MacosDistribution) -> MacosDistributio Sequoia15 => sequoia_15_catalog } } + +// WORKSPACE FOOTPRINT. Finder writes per-directory metadata into any tree it browses. +fn finder_metadata_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "macOS Finder metadata", upstream: "developer.apple.com (Finder metadata)" }, + artifacts: [ + WorkspaceArtifact { pattern: ".DS_Store", meaning: "Finder folder-view metadata", reason: HostOsMetadata } + ] + } +} diff --git a/dag/extdeps/os/windows.dag b/dag/extdeps/os/windows.dag index 80f9e497317..9da8416f263 100644 --- a/dag/extdeps/os/windows.dag +++ b/dag/extdeps/os/windows.dag @@ -9,6 +9,8 @@ import std.os.types { } import extdeps.external_authority { ExternalAuthority } +import std.types { String, List } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, HostOsMetadata } import extdeps.uri { Uri, Https } data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { @@ -33,3 +35,13 @@ fn windows_distribution_catalog_row(distro: WindowsDistribution) -> WindowsDistr Windows1124H2Build26100 => windows_11_24h2_catalog } } + +// WORKSPACE FOOTPRINT. Explorer writes thumbnail caches into browsed directories. +fn explorer_thumbnail_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Windows Explorer cache", upstream: "microsoft.com (Explorer thumbnail cache)" }, + artifacts: [ + WorkspaceArtifact { pattern: "Thumbs.db", meaning: "Explorer thumbnail cache", reason: HostOsMetadata } + ] + } +} diff --git a/dag/extdeps/python/python.dag b/dag/extdeps/python/python.dag index e4720250af3..1aae1863b6d 100644 --- a/dag/extdeps/python/python.dag +++ b/dag/extdeps/python/python.dag @@ -1,6 +1,7 @@ module extdeps.python -import std.types { FilePath } +import std.types { FilePath, String, List } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, RegenerableFromSource } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -27,3 +28,16 @@ service python.Interpreter { } } } + +// WORKSPACE FOOTPRINT. Running any Python script leaves CPython's bytecode cache in the +// tree (PEP 3147 __pycache__ directories, plus legacy .pyc). A fact about the interpreter, +// not about any script. +fn cpython_bytecode_footprint() -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "CPython bytecode cache", upstream: "python.org/peps/pep-3147" }, + artifacts: [ + WorkspaceArtifact { pattern: "__pycache__/", meaning: "PEP 3147 per-directory bytecode cache", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: "*.pyc", meaning: "compiled bytecode (legacy layout)", reason: RegenerableFromSource } + ] + } +} diff --git a/dag/extdeps/rust/cargo.dag b/dag/extdeps/rust/cargo.dag index 6c68d1f6666..8d2ce1c4f2b 100644 --- a/dag/extdeps/rust/cargo.dag +++ b/dag/extdeps/rust/cargo.dag @@ -1,7 +1,8 @@ module extdeps.cargo import extdeps.cargo_version { CargoPackageVersion, CargoVersionRequirement, CargoToolVersionFloor } -import std.types { FilePathParts, NonEmptyStr } +import std.types { FilePathParts, NonEmptyStr, String, List } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, FootprintProvenance, CitedUpstream, RegenerableFromSource, LocalCacheState } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -130,3 +131,26 @@ fn cargo_environment_variable_name(variable: CargoEnvironmentVariable) -> NonEmp RustcWrapperEnv => "RUSTC_WRAPPER" } } + +// WORKSPACE FOOTPRINT. Cargo introduces a build output tree (the target directory, +// doc.rust-lang.org/cargo/reference/build-cache.html) and a registry/cache home +// (CARGO_HOME, doc.rust-lang.org/cargo/guide/cargo-home.html). WHERE those live in a +// given repository is that repository's policy — the location patterns are parameters — +// but WHAT they are and why they are never tracked is a fact about cargo, declared here. +fn cargo_workspace_footprint(target_dir_patterns: List, cargo_home_pattern: String) -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Cargo build artifacts", upstream: "doc.rust-lang.org/cargo/" }, + artifacts: concat( + map(target_dir_patterns, p => WorkspaceArtifact { + pattern: p, + meaning: "cargo build output tree (compiled artifacts, incremental state)", + reason: RegenerableFromSource + }), + [WorkspaceArtifact { + pattern: cargo_home_pattern, + meaning: "CARGO_HOME registry/cache; may include git checkouts", + reason: LocalCacheState + }] + ) + } +} diff --git a/dag/extdeps/rust/cargo_tarpaulin.dag b/dag/extdeps/rust/cargo_tarpaulin.dag new file mode 100644 index 00000000000..3287d5199f1 --- /dev/null +++ b/dag/extdeps/rust/cargo_tarpaulin.dag @@ -0,0 +1,29 @@ +module extdeps.cargo_tarpaulin + +import std.types { String, List } +import extdeps.external_authority { ExternalAuthority } +import extdeps.uri { Uri, Https } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, RegenerableFromSource } + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "github.com/xd009642/tarpaulin" + } +} + +// WORKSPACE FOOTPRINT. cargo-tarpaulin writes coverage reports into the working tree in the +// formats requested (--out Html/Json/Xml/Lcov). WHERE aggregated output is collected is the +// invoking repository's policy, so that directory pattern is a parameter. +fn tarpaulin_report_footprint(coverage_output_dir_pattern: String) -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "Coverage reports (cargo-tarpaulin)", upstream: "github.com/xd009642/tarpaulin" }, + artifacts: [ + WorkspaceArtifact { pattern: "tarpaulin-report.html", meaning: "HTML coverage report (--out Html)", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: "tarpaulin-report.json", meaning: "JSON coverage report (--out Json)", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: "cobertura.xml", meaning: "Cobertura XML coverage report (--out Xml)", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: "lcov.info", meaning: "LCOV coverage report (--out Lcov)", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: coverage_output_dir_pattern, meaning: "repo-chosen coverage output directory", reason: RegenerableFromSource } + ] + } +} diff --git a/dag/extdeps/tmux/tmux.dag b/dag/extdeps/tmux/tmux.dag index 96ef63698c8..8ec7f6f807a 100644 --- a/dag/extdeps/tmux/tmux.dag +++ b/dag/extdeps/tmux/tmux.dag @@ -3,6 +3,7 @@ module extdeps.tmux import std.algebra { trim } import std.types { List, String, NonEmptyStr, Int, Bool, RenderedTerminalText } +import std.workspace_artifact { WorkspaceFootprint, WorkspaceArtifact, CitedUpstream, SessionRuntimeState } import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -574,3 +575,15 @@ service tmux.Session { } } } + +// WORKSPACE FOOTPRINT. tmux pipe-pane streams a pane's output wherever the invoker points +// it; the log NAMING is the invoking repository's policy, so the pattern is a parameter, +// while what such a file is — a session transcript, never source — is a fact about tmux. +fn pipe_pane_log_footprint(log_pattern: String) -> WorkspaceFootprint { + WorkspaceFootprint { + provenance: CitedUpstream { display: "tmux pipe-pane session logs", upstream: "github.com/tmux/tmux (pipe-pane)" }, + artifacts: [ + WorkspaceArtifact { pattern: log_pattern, meaning: "captured pane output from a local session", reason: SessionRuntimeState } + ] + } +} diff --git a/dag/gunbc/generated_artifact.dag b/dag/gunbc/generated_artifact.dag index 561eee281d7..2e2756a92ed 100644 --- a/dag/gunbc/generated_artifact.dag +++ b/dag/gunbc/generated_artifact.dag @@ -5,6 +5,8 @@ import gunbc.os_install { HostAutoinstall, fleet_autoinstall_specs, InstallServe import gunbc.plan { Plan, plan_doc_directory, plan_doc_name, PlanProjectsCommittedMarkdown, PlanIsAuthorityOnly } import gunbc.plan_registry { all_plans } import gunbc.generated_artifact_merge_driver { generated_artifact_merge_driver_script_directory, generated_artifact_merge_driver_script_name } +import examples.js_site { JsSitePageId, Home, Browse, About } +import examples.js_site_emit { js_site_generated_dir, js_site_page_basename } type GeneratedArtifact = WitnessFloorYamlArtifact @@ -25,6 +27,9 @@ type GeneratedArtifact | AutoinstallUserDataArtifact { spec: HostAutoinstall } | ProxyDhcpDnsmasqArtifact { spec: InstallServerSpec } | PlanArtifact { plan: Plan } + | JsSitePageArtifact { page_id: JsSitePageId, form: JsSiteArtifactForm } + +type JsSiteArtifactForm = JsSiteHtml | JsSiteTsx data generated_artifact_registry: List = concat( concat( @@ -34,7 +39,13 @@ data generated_artifact_registry: List = concat( ), map(fleet_install_server_specs, s => ProxyDhcpDnsmasqArtifact { spec: s }) ), - map(all_plans, pl => PlanArtifact { plan: pl }) + concat( + map(all_plans, pl => PlanArtifact { plan: pl }), + flat_map([Home {}, Browse {}, About {}], id => [ + JsSitePageArtifact { page_id: id, form: JsSiteHtml }, + JsSitePageArtifact { page_id: id, form: JsSiteTsx } + ]) + ) ) type RepoConsumer @@ -81,6 +92,11 @@ fn artifact_location(a: GeneratedArtifact) -> ArtifactLocation { ArtifactLocation { directory: concat("provisioning/", spec.host), name: "dnsmasq.conf" } PlanArtifact { plan } => ArtifactLocation { directory: plan_doc_directory, name: plan_doc_name(slug: plan.slug) } + JsSitePageArtifact { page_id, form } => + ArtifactLocation { + directory: js_site_generated_dir(), + name: concat(js_site_page_basename(id: page_id), match form { JsSiteHtml => ".html" JsSiteTsx => ".tsx" }) + } } } @@ -124,6 +140,7 @@ fn artifact_commit_policy(a: GeneratedArtifact) -> CommitPolicy { Stage0CrateLayoutGeneratedRsArtifact => CommitRequired { consumer: GitProtocol } Stage0CratePartitionGeneratedDagArtifact => CommitRequired { consumer: GitProtocol } V1InterpreterDispatchGeneratedRsArtifact => CommitRequired { consumer: GitProtocol } + JsSitePageArtifact { page_id: _, form: _ } => CommitRequired { consumer: ProjectDocumentation } AutoinstallUserDataArtifact { spec: _ } => NotCommitted ProxyDhcpDnsmasqArtifact { spec: _ } => NotCommitted } @@ -166,9 +183,29 @@ fn artifact_eq(a: GeneratedArtifact, b: GeneratedArtifact) -> Bool { AutoinstallUserDataArtifact { spec } => match b { AutoinstallUserDataArtifact { spec: spec2 } => spec.host == spec2.host _ => false } ProxyDhcpDnsmasqArtifact { spec } => match b { ProxyDhcpDnsmasqArtifact { spec: spec2 } => spec.host == spec2.host _ => false } PlanArtifact { plan } => match b { PlanArtifact { plan: plan2 } => plan.slug == plan2.slug _ => false } + JsSitePageArtifact { page_id, form } => match b { + JsSitePageArtifact { page_id: page_id2, form: form2 } => + js_site_page_id_eq(a: page_id, b: page_id2) && js_site_artifact_form_eq(a: form, b: form2) + _ => false + } } } fn registry_contains(a: GeneratedArtifact) -> Bool { any(generated_artifact_registry, x => artifact_eq(a: x, b: a)) } + +fn js_site_page_id_eq(a: JsSitePageId, b: JsSitePageId) -> Bool { + match a { + Home => match b { Home => true _ => false } + Browse => match b { Browse => true _ => false } + About => match b { About => true _ => false } + } +} + +fn js_site_artifact_form_eq(a: JsSiteArtifactForm, b: JsSiteArtifactForm) -> Bool { + match a { + JsSiteHtml => match b { JsSiteHtml => true JsSiteTsx => false } + JsSiteTsx => match b { JsSiteTsx => true JsSiteHtml => false } + } +} diff --git a/dag/gunbc/generated_artifact_emit.dag b/dag/gunbc/generated_artifact_emit.dag index d6277c2012d..d26c8fecf06 100644 --- a/dag/gunbc/generated_artifact_emit.dag +++ b/dag/gunbc/generated_artifact_emit.dag @@ -4,6 +4,7 @@ module gunbc.generated_artifact_emit import gunbc.generated_artifact { GeneratedArtifact, WitnessFloorYamlArtifact, FleetConvergeYamlArtifact, FleetDesiredAdmissionYamlArtifact, GitignoreArtifact, GitattributesArtifact, RoadmapArtifact, DesignArtifact, + JsSitePageArtifact, JsSiteArtifactForm, JsSiteHtml, JsSiteTsx, js_site_page_id_eq, RunnerDeployArtifact, GithooksPrePushArtifact, GithooksPreCommitArtifact, GeneratedArtifactMergeDriverArtifact, AutoinstallUserDataArtifact, ProxyDhcpDnsmasqArtifact, PlanArtifact, Stage0CrateLayoutGeneratedDagArtifact, Stage0CrateLayoutGeneratedRsArtifact, @@ -28,6 +29,8 @@ import gunbc.ci_spec { ci_heal_author_commit_regen_command } import gunbc.os_install_emit { autoinstall_user_data } import gunbc.install_server_emit { install_server_dnsmasq_conf } import gunbc.plan { expected_plan_md } +import examples.js_site { JsSitePage, JsSitePageId, js_site_pages } +import examples.js_site_emit { js_site_page_html, js_site_page_tsx } import gunbc.stage0_crate_layout_emit { expected_stage0_crate_layout_generated_dag, expected_stage0_crate_layout_generated_rs @@ -85,9 +88,20 @@ fn artifact_generate(a: GeneratedArtifact) -> ArtifactGenerationOutcome { AutoinstallUserDataArtifact { spec } => artifact_generated(content: autoinstall_user_data(payload: spec.payload)) ProxyDhcpDnsmasqArtifact { spec } => artifact_generated(content: install_server_dnsmasq_conf(spec: spec)) PlanArtifact { plan } => artifact_generated(content: expected_plan_md(p: plan)) + JsSitePageArtifact { page_id, form } => match js_site_page_for_id(id: page_id) { + Present { value: page } => artifact_generated(content: match form { + JsSiteHtml => js_site_page_html(page: page) + JsSiteTsx => js_site_page_tsx(page: page) + }) + Absent => ArtifactGenerationRefused { reason: "js_site page roster carries no page for this id" } + } } } +fn js_site_page_for_id(id: JsSitePageId) -> JsSitePage? { + js_site_pages() |> filter(p => js_site_page_id_eq(a: p.id, b: id)) |> first +} + data artifact_extra_valid_note: String = "P0 (operator-directed, 2026-08-05; loyal-ram-550 review of #7823): takes the ALREADY-COMPUTED generation outcome rather than calling artifact_generate itself. The two variants whose extra check depends on generation success (Stage0EmitPlanGeneratedDagArtifact, V1InterpreterDispatchGeneratedRsArtifact) used to call artifact_generate(a: a) a second time here, discarding the content and keeping only success/failure — one Filesystem.Read, but TWO artifact_generate calls per artifact for those two variants, contradicting gunbc.generated_artifact_observation's 'one artifact_generate per artifact' claim. Every caller now supplies the outcome it already produced (observe_generated_artifact reuses its own match result); no second entry point to generation remains." fn artifact_extra_valid(a: GeneratedArtifact, generated: ArtifactGenerationOutcome) -> Bool { @@ -97,6 +111,7 @@ fn artifact_extra_valid(a: GeneratedArtifact, generated: ArtifactGenerationOutco FleetDesiredAdmissionYamlArtifact => ci_yml_parses(path: artifact_path(a: a)) GitignoreArtifact => true GitattributesArtifact => true + JsSitePageArtifact { page_id: _, form: _ } => true RoadmapArtifact => true DesignArtifact => true GithooksPrePushArtifact => true diff --git a/dag/gunbc/gitignore_authority.dag b/dag/gunbc/gitignore_authority.dag deleted file mode 100644 index 25c5c4d0675..00000000000 --- a/dag/gunbc/gitignore_authority.dag +++ /dev/null @@ -1,155 +0,0 @@ -module gunbc.gitignore_authority - -import gunbc.gitignore_model { - IgnoreGroup, Producer, - DerivableProducerKind, CitedProducerKind, - CargoArtifacts, CargoCacheLocal, CodegenSymlink, CoverageReport, - GeneratorStamp, WorkflowRuntime, TestgenOutput, RegenTempDir, - ClaudeCodeSession, ClaimMapOutput, OpenClawArtifact, GithubCLICache, - AuthSessionTranscript, PythonLocalDevScript, SupersededPlanningDir, - JetBrainsIDE, VSCodeIDE, VimEditor, EmacsEditor, GenericEditorBackup, - MacOSFinder, WindowsExplorer, Tmux, NodeJS, SecretsConvention, CPythonInterpreter, - Derivable, Cited, - CargoTargetDir, CargoTargetCodexDir, LocalCargoHome, CodegenBinSymlink, - TarpaulinHtmlReport, TarpaulinJsonReport, CoberturaReport, LcovReport, CoverageOutputDir, - JetBrainsProjectDir, VSCodeWorkspaceDir, - VimSwapFile, VimSwapFileAlt, EmacsBackupFile, GenericBackupFile, - MacOSFinderMetadata, WindowsThumbnailCache, TmuxLogFile, - DotEnvFile, DotEnvLocalFile, DotEnvLocalWildcard, - GeneratorStampFile, GunbcWorkflowDir, TestgenOutputDir, NodeModulesDir, - ClaudeSessionDir, RegenSourcesDir, RegenOutputDir, RegenGeneratedSourceRootDir, - FreshnessCheckDir, AuthTranscriptFile, - OpenClawControlDir, OpenClawAgentsFile, OpenClawHeartbeatFile, OpenClawIdentityFile, - OpenClawSoulFile, OpenClawToolsFile, OpenClawUserFile, OpenClawWorkboardFile, - OpenClawScriptsDir, V2InspectFile, V2InspectErrorsFile, GithubCLICacheDir, - PythonLocalDevScriptFile, PythonAuditScriptAllowlisted, - PythonProbeScriptAllowlisted, - FloorCutNameResolutionPartitionScriptAllowlisted, - ShadowDirectCallArgConformanceSummarizeScriptAllowlisted, - ShadowDirectCallArgConformanceAdjudicateScriptAllowlisted, - ShadowDirectCallArgConformanceJoinBoardScriptAllowlisted, - E0308ClassifySitesScriptAllowlisted, - PythonBytecodeCacheDir, PythonCompiledBytecode, - ClaimMapDir, ScratchProbeFile, - GunbcPlanningDir, ScriptsFixturesDir -} - -data gitignore_authority: List = [ - IgnoreGroup { - producer: Derivable { kind: CargoArtifacts }, - artifacts: [CargoTargetDir, CargoTargetCodexDir] - }, - IgnoreGroup { - producer: Derivable { kind: CargoCacheLocal }, - artifacts: [LocalCargoHome] - }, - IgnoreGroup { - producer: Derivable { kind: CodegenSymlink }, - artifacts: [CodegenBinSymlink] - }, - IgnoreGroup { - producer: Derivable { kind: CoverageReport }, - artifacts: [TarpaulinHtmlReport, TarpaulinJsonReport, CoberturaReport, LcovReport, CoverageOutputDir] - }, - IgnoreGroup { - producer: Cited { kind: JetBrainsIDE, upstream: "jetbrains.com/idea" }, - artifacts: [JetBrainsProjectDir] - }, - IgnoreGroup { - producer: Cited { kind: VSCodeIDE, upstream: "code.visualstudio.com" }, - artifacts: [VSCodeWorkspaceDir] - }, - IgnoreGroup { - producer: Cited { kind: VimEditor, upstream: "vim.org" }, - artifacts: [VimSwapFile, VimSwapFileAlt] - }, - IgnoreGroup { - producer: Cited { kind: EmacsEditor, upstream: "gnu.org/software/emacs" }, - artifacts: [EmacsBackupFile] - }, - IgnoreGroup { - producer: Cited { kind: GenericEditorBackup, upstream: "cross-editor backup convention" }, - artifacts: [GenericBackupFile] - }, - IgnoreGroup { - producer: Cited { kind: MacOSFinder, upstream: "developer.apple.com (Finder metadata)" }, - artifacts: [MacOSFinderMetadata] - }, - IgnoreGroup { - producer: Cited { kind: WindowsExplorer, upstream: "microsoft.com (Explorer thumbnail cache)" }, - artifacts: [WindowsThumbnailCache] - }, - IgnoreGroup { - producer: Cited { kind: Tmux, upstream: "github.com/tmux/tmux (pipe-pane log naming)" }, - artifacts: [TmuxLogFile] - }, - IgnoreGroup { - producer: Cited { kind: SecretsConvention, upstream: "github.com/motdotla/dotenv" }, - artifacts: [DotEnvFile, DotEnvLocalFile, DotEnvLocalWildcard] - }, - IgnoreGroup { - producer: Derivable { kind: GeneratorStamp }, - artifacts: [GeneratorStampFile] - }, - IgnoreGroup { - producer: Derivable { kind: WorkflowRuntime }, - artifacts: [GunbcWorkflowDir] - }, - IgnoreGroup { - producer: Derivable { kind: TestgenOutput }, - artifacts: [TestgenOutputDir] - }, - IgnoreGroup { - producer: Cited { kind: NodeJS, upstream: "github/gitignore/Node.gitignore" }, - artifacts: [NodeModulesDir] - }, - IgnoreGroup { - producer: Derivable { kind: ClaudeCodeSession }, - artifacts: [ClaudeSessionDir] - }, - IgnoreGroup { - producer: Derivable { kind: RegenTempDir }, - artifacts: [RegenSourcesDir, RegenOutputDir, RegenGeneratedSourceRootDir, FreshnessCheckDir] - }, - IgnoreGroup { - producer: Derivable { kind: AuthSessionTranscript }, - artifacts: [AuthTranscriptFile] - }, - IgnoreGroup { - producer: Derivable { kind: OpenClawArtifact }, - artifacts: [ - OpenClawControlDir, OpenClawAgentsFile, OpenClawHeartbeatFile, OpenClawIdentityFile, - OpenClawSoulFile, OpenClawToolsFile, OpenClawUserFile, OpenClawWorkboardFile, - OpenClawScriptsDir, V2InspectFile, V2InspectErrorsFile - ] - }, - IgnoreGroup { - producer: Derivable { kind: GithubCLICache }, - artifacts: [GithubCLICacheDir] - }, - IgnoreGroup { - producer: Derivable { kind: PythonLocalDevScript }, - artifacts: [ - PythonLocalDevScriptFile, - PythonAuditScriptAllowlisted, - PythonProbeScriptAllowlisted, - FloorCutNameResolutionPartitionScriptAllowlisted, - ShadowDirectCallArgConformanceSummarizeScriptAllowlisted, - ShadowDirectCallArgConformanceAdjudicateScriptAllowlisted, - ShadowDirectCallArgConformanceJoinBoardScriptAllowlisted, - E0308ClassifySitesScriptAllowlisted, - ] - }, - IgnoreGroup { - producer: Cited { kind: CPythonInterpreter, upstream: "python.org/peps/pep-3147" }, - artifacts: [PythonBytecodeCacheDir, PythonCompiledBytecode] - }, - IgnoreGroup { - producer: Derivable { kind: ClaimMapOutput }, - artifacts: [ClaimMapDir, ScratchProbeFile] - }, - IgnoreGroup { - producer: Derivable { kind: SupersededPlanningDir }, - artifacts: [GunbcPlanningDir, ScriptsFixturesDir] - } -] diff --git a/dag/gunbc/gitignore_emit.dag b/dag/gunbc/gitignore_emit.dag index 3747dcab1f4..53f1a95cd7c 100644 --- a/dag/gunbc/gitignore_emit.dag +++ b/dag/gunbc/gitignore_emit.dag @@ -1,41 +1,14 @@ module gunbc.gitignore_emit -import gunbc.gitignore_model { - Producer, IgnoreGroup, IgnoreArtifact, - CargoArtifacts, CargoCacheLocal, CodegenSymlink, CoverageReport, - GeneratorStamp, WorkflowRuntime, TestgenOutput, RegenTempDir, - ClaudeCodeSession, ClaimMapOutput, OpenClawArtifact, GithubCLICache, - AuthSessionTranscript, PythonLocalDevScript, SupersededPlanningDir, - JetBrainsIDE, VSCodeIDE, VimEditor, EmacsEditor, GenericEditorBackup, - MacOSFinder, WindowsExplorer, Tmux, NodeJS, SecretsConvention, CPythonInterpreter, - Derivable, Cited, - CargoTargetDir, CargoTargetCodexDir, LocalCargoHome, CodegenBinSymlink, - TarpaulinHtmlReport, TarpaulinJsonReport, CoberturaReport, LcovReport, CoverageOutputDir, - JetBrainsProjectDir, VSCodeWorkspaceDir, - VimSwapFile, VimSwapFileAlt, EmacsBackupFile, GenericBackupFile, - MacOSFinderMetadata, WindowsThumbnailCache, TmuxLogFile, - DotEnvFile, DotEnvLocalFile, DotEnvLocalWildcard, - GeneratorStampFile, GunbcWorkflowDir, TestgenOutputDir, NodeModulesDir, - ClaudeSessionDir, RegenSourcesDir, RegenOutputDir, RegenGeneratedSourceRootDir, - FreshnessCheckDir, AuthTranscriptFile, - OpenClawControlDir, OpenClawAgentsFile, OpenClawHeartbeatFile, OpenClawIdentityFile, - OpenClawSoulFile, OpenClawToolsFile, OpenClawUserFile, OpenClawWorkboardFile, - OpenClawScriptsDir, V2InspectFile, V2InspectErrorsFile, GithubCLICacheDir, - PythonLocalDevScriptFile, PythonAuditScriptAllowlisted, - PythonProbeScriptAllowlisted, - FloorCutNameResolutionPartitionScriptAllowlisted, - ShadowDirectCallArgConformanceSummarizeScriptAllowlisted, - ShadowDirectCallArgConformanceAdjudicateScriptAllowlisted, - ShadowDirectCallArgConformanceJoinBoardScriptAllowlisted, - E0308ClassifySitesScriptAllowlisted, - PythonBytecodeCacheDir, PythonCompiledBytecode, - ClaimMapDir, ScratchProbeFile, - GunbcPlanningDir, ScriptsFixturesDir +import std.types { String, List, Bool } +import std.workspace_artifact { + WorkspaceFootprint, WorkspaceArtifact, FootprintProvenance, + footprint_display, ignore_reason_label } +import gunbc.repo_workspace { repo_workspace_footprints } import gunbc.generated_artifact { GeneratedArtifact, generated_artifact_registry, artifact_is_committed, artifact_path } -import gunbc.gitignore_authority { gitignore_authority } import std.languages { gitignore_format } import std.layout { Doc, DocEmpty, DocConcat, @@ -45,129 +18,11 @@ import std.layout { } import std.render { config_comment_prefix } -fn artifact_pattern(a: IgnoreArtifact) -> String { - match a { - CargoTargetDir => "/target/" - CargoTargetCodexDir => "/target-codex/" - LocalCargoHome => "/.cargo-home/" - CodegenBinSymlink => "/bin/" - TarpaulinHtmlReport => "tarpaulin-report.html" - TarpaulinJsonReport => "tarpaulin-report.json" - CoberturaReport => "cobertura.xml" - LcovReport => "lcov.info" - CoverageOutputDir => "/coverage/" - JetBrainsProjectDir => ".idea/" - VSCodeWorkspaceDir => ".vscode/" - VimSwapFile => "*.swp" - VimSwapFileAlt => "*.swo" - EmacsBackupFile => "*~" - GenericBackupFile => "*.bak" - MacOSFinderMetadata => ".DS_Store" - WindowsThumbnailCache => "Thumbs.db" - TmuxLogFile => "tmux-*.log" - DotEnvFile => ".env" - DotEnvLocalFile => ".env.local" - DotEnvLocalWildcard => ".env.*.local" - GeneratorStampFile => ".*-stamp" - GunbcWorkflowDir => "/.gunbc/" - TestgenOutputDir => "src/v1/10_test/generated-tests/src/generated/" - NodeModulesDir => "node_modules/" - ClaudeSessionDir => ".claude/" - RegenSourcesDir => ".regen-sources/" - RegenOutputDir => ".regen-output/" - RegenGeneratedSourceRootDir => ".regen-generated-source-root/" - FreshnessCheckDir => ".freshness-check/" - AuthTranscriptFile => "out.txt" - OpenClawControlDir => "/.openclaw/" - OpenClawAgentsFile => "/AGENTS.md" - OpenClawHeartbeatFile => "/HEARTBEAT.md" - OpenClawIdentityFile => "/IDENTITY.md" - OpenClawSoulFile => "/SOUL.md" - OpenClawToolsFile => "/TOOLS.md" - OpenClawUserFile => "/USER.md" - OpenClawWorkboardFile => "/WORKBOARD.md" - OpenClawScriptsDir => "/scripts/openclaw/" - V2InspectFile => ".v2-inspect" - V2InspectErrorsFile => ".v2-inspect-errors.txt" - GithubCLICacheDir => ".gh-cache/" - PythonLocalDevScriptFile => "*.py" - PythonAuditScriptAllowlisted => "!docs/plans/witness-subject-execution-audit.py" - PythonProbeScriptAllowlisted => "!docs/probes/e0369_b1_operator_classify.py" - FloorCutNameResolutionPartitionScriptAllowlisted => "!docs/probes/floor_cut_name_resolution_partition.py" - ShadowDirectCallArgConformanceSummarizeScriptAllowlisted => "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/summarize.py" - ShadowDirectCallArgConformanceAdjudicateScriptAllowlisted => "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/adjudicate.py" - ShadowDirectCallArgConformanceJoinBoardScriptAllowlisted => "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/join_board.py" - E0308ClassifySitesScriptAllowlisted => "!docs/probes/e0308_classify_sites.py" - PythonBytecodeCacheDir => "__pycache__/" - PythonCompiledBytecode => "*.pyc" - ClaimMapDir => ".claim-map/" - ScratchProbeFile => "src/v2/test/claim/manual/sg2_scratch_probe.dag" - GunbcPlanningDir => "/gunbc-planning/" - ScriptsFixturesDir => "/scripts/fixtures/" - } -} - -fn producer_display(p: Producer) -> String { - match p { - Derivable { kind: CargoArtifacts } => "Cargo build artifacts (from cargo)" - Derivable { kind: CargoCacheLocal } => "Cargo cache (local CARGO_HOME) (from tool/rust)" - Derivable { kind: CodegenSymlink } => "Codegen bin symlink (from codegen)" - Derivable { kind: CoverageReport } => "Coverage reports (from cargo-tarpaulin)" - Derivable { kind: GeneratorStamp } => "Generator stamp files (from generators)" - Derivable { kind: WorkflowRuntime } => "Workflow runtime state (from workflow)" - Derivable { kind: TestgenOutput } => "testgen outputs (from testgen)" - Derivable { kind: RegenTempDir } => "Stage0 regeneration temp dirs" - Derivable { kind: ClaudeCodeSession } => "Claude Code session state" - Derivable { kind: ClaimMapOutput } => "claim-corpus execution-map output" - Derivable { kind: OpenClawArtifact } => "OpenClaw workspace artifacts" - Derivable { kind: GithubCLICache } => "GitHub CLI local cache (dashboard / gh API)" - Derivable { kind: AuthSessionTranscript } => "Interactive auth/session transcripts" - Derivable { kind: PythonLocalDevScript } => "Python local dev scripts" - Derivable { kind: SupersededPlanningDir } => "Superseded planning scratch directories (canonical home: docs/plans/ or DESIGN.md)" - Cited { kind: JetBrainsIDE, upstream: u } => concat("JetBrains IDE project state [cited: ", concat(u, "]")) - Cited { kind: VSCodeIDE, upstream: u } => concat("VS Code workspace state [cited: ", concat(u, "]")) - Cited { kind: VimEditor, upstream: u } => concat("Vim editor state [cited: ", concat(u, "]")) - Cited { kind: EmacsEditor, upstream: u } => concat("Emacs backup convention [cited: ", concat(u, "]")) - Cited { kind: GenericEditorBackup, upstream: u } => concat("Generic editor backup files [cited: ", concat(u, "]")) - Cited { kind: MacOSFinder, upstream: u } => concat("macOS Finder metadata [cited: ", concat(u, "]")) - Cited { kind: WindowsExplorer, upstream: u } => concat("Windows Explorer cache [cited: ", concat(u, "]")) - Cited { kind: Tmux, upstream: u } => concat("tmux terminal multiplexer logs [cited: ", concat(u, "]")) - Cited { kind: NodeJS, upstream: u } => concat("Node.js [cited: ", concat(u, "]")) - Cited { kind: SecretsConvention, upstream: u } => concat("Secrets and local config [cited: ", concat(u, "]")) - Cited { kind: CPythonInterpreter, upstream: u } => concat("CPython bytecode cache (PEP 3147) [cited: ", concat(u, "]")) - } -} - -fn producer_rationale_line(p: Producer) -> String { - match p { - Derivable { kind: CargoArtifacts } => "Reproducible from source via cargo build" - Derivable { kind: CargoCacheLocal } => "Local Cargo cache may include git checkouts; not project state" - Derivable { kind: CodegenSymlink } => "Symlink to target/release created by codegen" - Derivable { kind: CoverageReport } => "Generated, often large, reproducible" - Derivable { kind: GeneratorStamp } => "Producer-centric model stamps" - Derivable { kind: WorkflowRuntime } => "Local execution ledger and config; not source-of-truth" - Derivable { kind: TestgenOutput } => "Generated by testgen; not source-of-truth" - Derivable { kind: RegenTempDir } => "" - Derivable { kind: ClaudeCodeSession } => "" - Derivable { kind: ClaimMapOutput } => "" - Derivable { kind: OpenClawArtifact } => "The OpenClaw control plane lives in ~/ctrl, not in this repo" - Derivable { kind: GithubCLICache } => "" - Derivable { kind: AuthSessionTranscript } => "Should never be committed; may contain OAuth URLs or session state" - Derivable { kind: PythonLocalDevScript } => "Python is used only for local dev tooling; never committed to the .dag/.rs substrate" - Derivable { kind: SupersededPlanningDir } => "Superseded by docs/plans/ (generated PlanArtifact) and DESIGN.md/ROADMAP.md as canonical authorities" - Cited { kind: JetBrainsIDE, upstream: _ } => "Per-developer configuration, not project state" - Cited { kind: VSCodeIDE, upstream: _ } => "Per-developer configuration, not project state" - Cited { kind: VimEditor, upstream: _ } => "Per-developer configuration, not project state" - Cited { kind: EmacsEditor, upstream: _ } => "Per-developer configuration, not project state" - Cited { kind: GenericEditorBackup, upstream: _ } => "Per-developer configuration, not project state" - Cited { kind: MacOSFinder, upstream: _ } => "OS-generated, not project state" - Cited { kind: WindowsExplorer, upstream: _ } => "OS-generated, not project state" - Cited { kind: Tmux, upstream: _ } => "Session log; not project state" - Cited { kind: NodeJS, upstream: _ } => "Not part of this project" - Cited { kind: SecretsConvention, upstream: _ } => "Environment-specific, may contain secrets" - Cited { kind: CPythonInterpreter, upstream: _ } => "" - } -} +// THE committed byte projection of gunbc.repo_workspace (tool footprints, each artifact +// carrying its meaning and typed ignore reason) joined with the generated-artifact arm +// derived from gunbc.generated_artifact commit policy. This module is a renderer only: +// it declares no pattern of its own — a pattern with no declaring producer has no +// spelling here, which is what retired the hand-coproduct model this replaced. data gitignore_protocol: LayoutProtocol = LayoutProtocol { indent_unit: "" } @@ -181,48 +36,55 @@ fn gitignore_section_header(title: String) -> Doc { gitignore_comment_line(text: concat("--- ", concat(title, " ---"))) } -fn group_doc(g: IgnoreGroup) -> Doc { - let header = gitignore_section_header(title: producer_display(p: g.producer)) - let rationale = producer_rationale_line(p: g.producer) - let rat_doc = if rationale == "" { DocEmpty } else { gitignore_comment_line(text: rationale) } - let pattern_docs = map(g.artifacts, a => doc_line_of(text: artifact_pattern(a: a))) - doc_concat(parts: append([header, rat_doc], items: pattern_docs)) +fn artifact_doc(a: WorkspaceArtifact) -> Doc { + let annotation = concat(ignore_reason_label(r: a.reason), concat(" — ", a.meaning)) + doc_concat(parts: [ + gitignore_comment_line(text: annotation), + doc_line_of(text: a.pattern) + ]) +} + +fn footprint_doc(f: WorkspaceFootprint) -> Doc { + let header = gitignore_section_header(title: footprint_display(p: f.provenance)) + doc_concat(parts: append([header], items: map(f.artifacts, a => artifact_doc(a: a)))) } fn gitignore_header_doc() -> Doc { doc_concat(parts: [ - gitignore_comment_line(text: "gunbc .gitignore — generated from dag/gunbc/gitignore_authority.dag — do not hand-edit."), + gitignore_comment_line(text: "gunbc .gitignore — generated from gunbc.repo_workspace via gunbc.gitignore_emit — do not hand-edit."), gitignore_comment_line(text: ""), - gitignore_comment_line(text: "Rule: Ignore anything that is (a) reproducible from committed source-of-truth files, or (b) environment-specific and not shared across developers."), + gitignore_comment_line(text: "Every pattern is declared by its producer (an extdeps product's workspace footprint, or a repo tool's own declaration) with its meaning and a typed ignore reason; the trailing section is derived from gunbc.generated_artifact commit policy."), doc_blank() ]) } -fn groups_doc(groups: List) -> Doc { - doc_concat(parts: fold(groups, init: [], f: fn(acc, g) { - let gd = group_doc(g: g) - if count(acc) == 0 { [gd] } else { append(acc, items: [doc_blank(), gd]) } +fn footprints_doc(footprints: List) -> Doc { + doc_concat(parts: fold(footprints, init: [], f: fn(acc, f) { + let fd = footprint_doc(f: f) + if count(acc) == 0 { [fd] } else { append(acc, items: [doc_blank(), fd]) } })) } -fn project_gitignore_to_doc(groups: List) -> Doc { - doc_concat(parts: [gitignore_header_doc(), groups_doc(groups: groups), doc_blank(), generated_artifacts_section_doc()]) -} - fn expected_gitignore() -> String { - render(doc: project_gitignore_to_doc(groups: gitignore_authority), proto: gitignore_protocol) + let body = doc_concat(parts: [ + gitignore_header_doc(), + footprints_doc(footprints: repo_workspace_footprints()), + doc_blank(), + generated_artifacts_section_doc() + ]) + render(doc: body, proto: gitignore_protocol) } fn gitignore_drifted(committed: String) -> Bool { !(committed == expected_gitignore()) } -fn group_patterns(g: IgnoreGroup) -> List { - fold(g.artifacts, init: [], f: fn(acc, a) { concat(acc, [artifact_pattern(a: a)]) }) +fn footprint_patterns(f: WorkspaceFootprint) -> List { + map(f.artifacts, a => a.pattern) } fn ignore_patterns() -> List { - let tool_patterns = fold(gitignore_authority, init: [], f: fn(acc, g) { concat(acc, group_patterns(g: g)) }) + let tool_patterns = fold(repo_workspace_footprints(), init: [], f: fn(acc, f) { concat(acc, footprint_patterns(f: f)) }) concat(tool_patterns, map(non_committed_artifacts(), a => generated_artifact_ignore_pattern(a: a))) } diff --git a/dag/gunbc/gitignore_model.dag b/dag/gunbc/gitignore_model.dag deleted file mode 100644 index 15fddc70541..00000000000 --- a/dag/gunbc/gitignore_model.dag +++ /dev/null @@ -1,99 +0,0 @@ -module gunbc.gitignore_model - -type DerivableProducerKind - = CargoArtifacts - | CargoCacheLocal - | CodegenSymlink - | CoverageReport - | GeneratorStamp - | WorkflowRuntime - | TestgenOutput - | RegenTempDir - | ClaudeCodeSession - | ClaimMapOutput - | OpenClawArtifact - | GithubCLICache - | AuthSessionTranscript - | PythonLocalDevScript - | SupersededPlanningDir - -type CitedProducerKind - = JetBrainsIDE - | VSCodeIDE - | VimEditor - | EmacsEditor - | GenericEditorBackup - | MacOSFinder - | WindowsExplorer - | Tmux - | NodeJS - | SecretsConvention - | CPythonInterpreter - -type Producer - = Derivable { kind: DerivableProducerKind } - | Cited { kind: CitedProducerKind, upstream: String } - -type IgnoreArtifact - = CargoTargetDir - | CargoTargetCodexDir - | LocalCargoHome - | CodegenBinSymlink - | TarpaulinHtmlReport - | TarpaulinJsonReport - | CoberturaReport - | LcovReport - | CoverageOutputDir - | JetBrainsProjectDir - | VSCodeWorkspaceDir - | VimSwapFile - | VimSwapFileAlt - | EmacsBackupFile - | GenericBackupFile - | MacOSFinderMetadata - | WindowsThumbnailCache - | TmuxLogFile - | DotEnvFile - | DotEnvLocalFile - | DotEnvLocalWildcard - | GeneratorStampFile - | GunbcWorkflowDir - | TestgenOutputDir - | NodeModulesDir - | ClaudeSessionDir - | RegenSourcesDir - | RegenOutputDir - | RegenGeneratedSourceRootDir - | FreshnessCheckDir - | AuthTranscriptFile - | OpenClawControlDir - | OpenClawAgentsFile - | OpenClawHeartbeatFile - | OpenClawIdentityFile - | OpenClawSoulFile - | OpenClawToolsFile - | OpenClawUserFile - | OpenClawWorkboardFile - | OpenClawScriptsDir - | V2InspectFile - | V2InspectErrorsFile - | GithubCLICacheDir - | PythonLocalDevScriptFile - | PythonAuditScriptAllowlisted - | PythonProbeScriptAllowlisted - | FloorCutNameResolutionPartitionScriptAllowlisted - | ShadowDirectCallArgConformanceSummarizeScriptAllowlisted - | ShadowDirectCallArgConformanceAdjudicateScriptAllowlisted - | ShadowDirectCallArgConformanceJoinBoardScriptAllowlisted - | E0308ClassifySitesScriptAllowlisted - | PythonBytecodeCacheDir - | PythonCompiledBytecode - | ClaimMapDir - | ScratchProbeFile - | GunbcPlanningDir - | ScriptsFixturesDir - -type IgnoreGroup { - producer: Producer - artifacts: List -} diff --git a/dag/gunbc/repo_workspace.dag b/dag/gunbc/repo_workspace.dag new file mode 100644 index 00000000000..5000160b061 --- /dev/null +++ b/dag/gunbc/repo_workspace.dag @@ -0,0 +1,157 @@ +module gunbc.repo_workspace + +import std.types { String, List } +import std.workspace_artifact { + WorkspaceFootprint, WorkspaceArtifact, FootprintProvenance, + CitedUpstream, RepoTool, + RegenerableFromSource, LocalCacheState, PerDeveloperState, HostOsMetadata, + SessionRuntimeState, MayContainSecrets, OutsideSubstrate, SupersededAuthority +} +import extdeps.cargo { cargo_workspace_footprint } +import extdeps.cargo_tarpaulin { tarpaulin_report_footprint } +import extdeps.python { cpython_bytecode_footprint } +import extdeps.npm { node_modules_footprint } +import extdeps.tmux { pipe_pane_log_footprint } +import extdeps.os.macos { finder_metadata_footprint } +import extdeps.os.windows { explorer_thumbnail_footprint } +import extdeps.editor.jetbrains_ide { jetbrains_workspace_footprint } +import extdeps.editor.visual_studio_code { vscode_workspace_footprint } +import extdeps.editor.vim { vim_swap_footprint } +import extdeps.editor.gnu_emacs { emacs_backup_footprint } +import extdeps.dotenv { dotenv_footprint } + +// THE JOIN OF THIS REPOSITORY'S WORKSPACE FOOTPRINTS. Replaced gunbc.gitignore_model + +// gunbc.gitignore_authority (one nullary variant per path, patterns restated in a central +// emit match — the shape that let seven dead allowlist rows emit for weeks, because no +// producer owned them). Here every entry is either an extdeps product's own declaration — +// onboarding a tool includes declaring what files it introduces, what they mean, and why +// they are untracked — with repo-chosen LOCATIONS passed as parameters (policy stays a +// workflow fact, §3), or a repo tool's declaration carrying its owner module by name. +// The .gitignore byte projection is derived in gunbc.gitignore_emit; the generated-artifact +// rows are a separate arm derived from gunbc.generated_artifact commit policy. + +fn own_tool_footprints() -> List { + [ + WorkspaceFootprint { + provenance: RepoTool { display: "Codegen bin symlink", owner_module: "gunbc.repo_workspace" }, + artifacts: [ + WorkspaceArtifact { pattern: "/bin/", meaning: "symlink to target/release created by codegen", reason: RegenerableFromSource } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Generator stamp files", owner_module: "gunbc.generated_artifact" }, + artifacts: [ + WorkspaceArtifact { pattern: ".*-stamp", meaning: "producer-centric generator stamps", reason: RegenerableFromSource } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Workflow runtime state", owner_module: "v2.workflow.required_floor" }, + artifacts: [ + WorkspaceArtifact { pattern: "/.gunbc/", meaning: "local execution ledger and config", reason: SessionRuntimeState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "testgen outputs", owner_module: "v1.10_test" }, + artifacts: [ + WorkspaceArtifact { pattern: "src/v1/10_test/generated-tests/src/generated/", meaning: "tests generated by testgen; not source-of-truth", reason: RegenerableFromSource } + ] + }, + WorkspaceFootprint { + provenance: CitedUpstream { display: "Claude Code session state", upstream: "code.claude.com" }, + artifacts: [ + WorkspaceArtifact { pattern: ".claude/", meaning: "per-clone agent session state", reason: SessionRuntimeState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Stage0 regeneration temp dirs", owner_module: "v1_compiler.required_regen_host" }, + artifacts: [ + WorkspaceArtifact { pattern: ".regen-sources/", meaning: "regen input snapshot", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: ".regen-output/", meaning: "regen emitted candidate", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: ".regen-generated-source-root/", meaning: "regen generated source root", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: ".freshness-check/", meaning: "staleness-check scratch tree", reason: RegenerableFromSource } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Interactive auth/session transcripts", owner_module: "gunbc.auth.credentials" }, + artifacts: [ + WorkspaceArtifact { pattern: "out.txt", meaning: "interactive auth transcript; may contain OAuth URLs or session state", reason: MayContainSecrets } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "OpenClaw workspace artifacts", owner_module: "gunbc.repo_workspace" }, + artifacts: [ + WorkspaceArtifact { pattern: "/.openclaw/", meaning: "OpenClaw control dir; the control plane lives in ~/ctrl, not this repo", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/AGENTS.md", meaning: "OpenClaw agent roster projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/HEARTBEAT.md", meaning: "OpenClaw heartbeat projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/IDENTITY.md", meaning: "OpenClaw identity projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/SOUL.md", meaning: "OpenClaw soul projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/TOOLS.md", meaning: "OpenClaw tools projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/USER.md", meaning: "OpenClaw user projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/WORKBOARD.md", meaning: "OpenClaw workboard projection", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: "/scripts/openclaw/", meaning: "OpenClaw-managed scripts dir", reason: SessionRuntimeState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "v2 compiler inspect output", owner_module: "gunbc.repo_workspace" }, + artifacts: [ + WorkspaceArtifact { pattern: ".v2-inspect", meaning: "v2 compiler inspect output", reason: SessionRuntimeState }, + WorkspaceArtifact { pattern: ".v2-inspect-errors.txt", meaning: "v2 compiler inspect error output", reason: SessionRuntimeState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "GitHub CLI local cache", owner_module: "gunbc.repo_workspace" }, + artifacts: [ + WorkspaceArtifact { pattern: ".gh-cache/", meaning: "local gh API response cache (dashboard tooling)", reason: LocalCacheState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Python local dev scripts", owner_module: "gunbc.repo_workspace" }, + artifacts: [ + WorkspaceArtifact { pattern: "*.py", meaning: "local dev tooling only; never committed to the .dag/.rs substrate", reason: OutsideSubstrate } + ] + }, + WorkspaceFootprint { + provenance: CitedUpstream { display: "Generic editor backup files", upstream: "cross-editor backup convention" }, + artifacts: [ + WorkspaceArtifact { pattern: "*.bak", meaning: "editor backup copy", reason: PerDeveloperState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "claim-corpus execution-map output", owner_module: "v1_compiler.cli_run" }, + artifacts: [ + WorkspaceArtifact { pattern: ".claim-map/", meaning: "claim execution map output", reason: RegenerableFromSource }, + WorkspaceArtifact { pattern: "src/v2/test/claim/manual/sg2_scratch_probe.dag", meaning: "scratch probe written by manual claim runs", reason: SessionRuntimeState } + ] + }, + WorkspaceFootprint { + provenance: RepoTool { display: "Superseded planning scratch directories", owner_module: "gunbc.plan" }, + artifacts: [ + WorkspaceArtifact { pattern: "/gunbc-planning/", meaning: "pre-plan-carrier planning scratch", reason: SupersededAuthority { canonical: "docs/plans/ (generated PlanArtifact) and DESIGN.md" } }, + WorkspaceArtifact { pattern: "/scripts/fixtures/", meaning: "pre-plan-carrier fixture scratch", reason: SupersededAuthority { canonical: "docs/plans/ (generated PlanArtifact) and DESIGN.md" } } + ] + } + ] +} + +// Repo policy bound to extdeps concepts: WHERE cargo's target trees and CARGO_HOME live, +// where coverage aggregates, how tmux pane logs are named — locations are this module's +// facts, the concepts are the cited modules'. +fn repo_workspace_footprints() -> List { + concat( + [ + cargo_workspace_footprint(target_dir_patterns: ["/target/", "/target-codex/"], cargo_home_pattern: "/.cargo-home/"), + tarpaulin_report_footprint(coverage_output_dir_pattern: "/coverage/"), + jetbrains_workspace_footprint(), + vscode_workspace_footprint(), + vim_swap_footprint(), + emacs_backup_footprint(), + finder_metadata_footprint(), + explorer_thumbnail_footprint(), + pipe_pane_log_footprint(log_pattern: "tmux-*.log"), + dotenv_footprint(), + node_modules_footprint(), + cpython_bytecode_footprint() + ], + own_tool_footprints() + ) +} diff --git a/dag/gunbc/source_integration_landing_spine.dag b/dag/gunbc/source_integration_landing_spine.dag index 9cfe503e05e..460dd0677a7 100644 --- a/dag/gunbc/source_integration_landing_spine.dag +++ b/dag/gunbc/source_integration_landing_spine.dag @@ -535,10 +535,13 @@ fn landing_alternative_for_choice( NativeScmSecondContinuationOption => Present { value: options.second_option.alternative } NativeScmAdditionalContinuationOption { index } => - list_at_optional( + match list_at_optional( xs: options.additional_options, index: index, - ) |> map(option => option.alternative) + ) { + Present { value: option } => Present { value: option.alternative } + Absent => Absent {} + } } } diff --git a/dag/std/workspace_artifact.dag b/dag/std/workspace_artifact.dag new file mode 100644 index 00000000000..16a4c0e1155 --- /dev/null +++ b/dag/std/workspace_artifact.dag @@ -0,0 +1,69 @@ +module std.workspace_artifact + +import std.types { String, List } + +// THE SHAPE OF A TOOL'S FILESYSTEM FOOTPRINT, agnostic over which tool. +// +// Onboarding a concept (an extdeps product, a repo tool) includes declaring what files and +// directories it introduces into a working tree, what each one means, and the REASON the +// repository does or does not track it. The declarations live with their producers — an +// extdeps module declares its own product's footprint beside its citation, a repo tool +// declares its own outputs — and consumers (the .gitignore projection, deploy scoping, +// hygiene lenses) fold over the join. This module owns only the shape; it enumerates no +// concrete product (extdeps hub rule: agnostic shapes only). + +// WHY a path is untracked — the fact the old model kept only as per-group prose. A closed +// vocabulary so a census over reasons is a fold, not a text scan. SupersededAuthority names +// the canonical home that replaced the ignored path, so "this directory is dead, its facts +// live at X" is data rather than a comment. +type IgnoreReason + = RegenerableFromSource + | LocalCacheState + | PerDeveloperState + | HostOsMetadata + | SessionRuntimeState + | MayContainSecrets + | OutsideSubstrate + | SupersededAuthority { canonical: String } + +fn ignore_reason_label(r: IgnoreReason) -> String { + match r { + RegenerableFromSource => "regenerable from committed source" + LocalCacheState => "local cache; not project state" + PerDeveloperState => "per-developer state; not shared" + HostOsMetadata => "host OS metadata; not project state" + SessionRuntimeState => "session/runtime state; not source-of-truth" + MayContainSecrets => "may contain secrets; never committed" + OutsideSubstrate => "outside the committed substrate" + SupersededAuthority { canonical: c } => concat("superseded; canonical home: ", c) + } +} + +// One file, directory, or glob a producer introduces. `pattern` is gitignore-grammar for now +// (trailing `/` = directory, leading `/` = repo-root anchor, `*` = glob); decomposing the +// pattern grammar into typed grain/anchor is a later step against extdeps.git.gitignore. +// `meaning` says what the path IS — the "what does this X introduce" half of onboarding. +type WorkspaceArtifact { + pattern: String + meaning: String + reason: IgnoreReason +} + +// Who introduces the artifacts: a cited upstream product (the extdeps module that declares +// the footprint carries the real citation anchor; `upstream` here is the rendered pointer), +// or a tool of the repository itself, named by the module that owns it. +type FootprintProvenance + = CitedUpstream { display: String, upstream: String } + | RepoTool { display: String, owner_module: String } + +type WorkspaceFootprint { + provenance: FootprintProvenance + artifacts: List +} + +fn footprint_display(p: FootprintProvenance) -> String { + match p { + CitedUpstream { display: d, upstream: u } => concat(d, concat(" [cited: ", concat(u, "]"))) + RepoTool { display: d, owner_module: m } => concat(d, concat(" [owner: ", concat(m, "]"))) + } +} diff --git a/dag/test/claim/gitignore_gate_test.dag b/dag/test/claim/gitignore_gate_test.dag index 7df7c899721..215da915d73 100644 --- a/dag/test/claim/gitignore_gate_test.dag +++ b/dag/test/claim/gitignore_gate_test.dag @@ -17,20 +17,10 @@ test fn witness_has_editor_and_os_patterns() -> Bool { test fn witness_has_header() -> Bool { let eg = expected_gitignore() - string_contains(s: eg, pattern: "generated from dag/gunbc/gitignore_authority.dag") + string_contains(s: eg, pattern: "generated from gunbc.repo_workspace via gunbc.gitignore_emit") && string_contains(s: eg, pattern: "do not hand-edit") } -test fn witness_has_probe_script_allowlists() -> Bool { - let eg = expected_gitignore() - string_contains(s: eg, pattern: "!docs/probes/e0369_b1_operator_classify.py") - && string_contains(s: eg, pattern: "!docs/probes/floor_cut_name_resolution_partition.py") - && string_contains(s: eg, pattern: "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/summarize.py") - && string_contains(s: eg, pattern: "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/adjudicate.py") - && string_contains(s: eg, pattern: "!docs/probes/shadow_direct_call_arg_conformance_2026-08-22/join_board.py") - && string_contains(s: eg, pattern: "!docs/probes/e0308_classify_sites.py") -} - test fn witness_clean_does_not_drift() -> Bool { !(gitignore_drifted(committed: expected_gitignore())) } diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 75253d07903..f12ac6130be 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -4029,14 +4029,6 @@ fn unresolved_method_frontier() -> List { cause: "receiver is an Optional produced by `|> last`, and the optional functor is being mapped over. It arrives as the INNER product because the optional cardinality is dropped before method lookup, so Optional's own surface is never consulted.", dissolution: unbound_dissolution(description: "reconciling the two optionality representations (cardinality-marked node vs the nominal Optional coproduct) so an optional receiver keeps its optional surface at method lookup") }, - { - module_name: "gunbc.source_integration_landing_spine", - method: "map", - occurrences: 1, - receiver_shape: "Node(Optional)", - cause: "same optional-functor class as the v1.compiler.trace row, in its OTHER surface form: here the Optional survives as a named node rather than collapsing to its inner product, and neither form carries a method surface. Two shapes for one concept is itself the defect the trigger names.", - dissolution: unbound_dissolution(description: "reconciling the two optionality representations so an optional receiver keeps its optional surface at method lookup") - }, { module_name: "test.claim.sccache_local_content_verified_on_read", method: "contains", diff --git a/src/v1/runtime_rust.dag b/src/v1/runtime_rust.dag index 053b18aa797..db4279d885b 100644 --- a/src/v1/runtime_rust.dag +++ b/src/v1/runtime_rust.dag @@ -669,7 +669,7 @@ fn rt_hash_ops() -> String { "/// the interpreter arm in `v1_interpreter.rs` when realization_measurement_loop **Phase 0**\n", "/// (`docs/plans/realization-measurement-loop.md`) lands a `.dag` `PerformanceReceipt`\n", "/// per-stage carrier that a floor witness consumes by execution (the same retirement event\n", - "/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `docs/plans/ci-floor-fractal-gantt.md`\n", + "/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `ci-floor-fractal-gantt (plan doc deleted 2026-08-28)`\n", "/// § dissolution). Receipt = that witness green with these marks deleted and stage walls\n", "/// still attributable from the model path.\n", "pub fn trace_mark(label: String) \{\n", diff --git a/src/v1/stage0/src/emitted_population.rs b/src/v1/stage0/src/emitted_population.rs index f88af3b3c86..10c05ec7d3b 100644 --- a/src/v1/stage0/src/emitted_population.rs +++ b/src/v1/stage0/src/emitted_population.rs @@ -79,6 +79,7 @@ // src/std_types.rs // src/std_unicode_types.rs // src/std_witness_admission.rs +// src/std_workspace_artifact.rs // src/v1_compiler_annotation_bind.rs // src/v1_compiler_artifact.rs // src/v1_compiler_closure_stub_v2_std_integer_rust.rs diff --git a/src/v1/stage0/src/extdeps_cargo.rs b/src/v1/stage0/src/extdeps_cargo.rs index e33d4666cfb..ac6b547cab0 100644 --- a/src/v1/stage0/src/extdeps_cargo.rs +++ b/src/v1/stage0/src/extdeps_cargo.rs @@ -12,7 +12,12 @@ pub use crate::extdeps_cargo_version::{ pub use crate::extdeps_external_authority::ExternalAuthority; use crate::extdeps_uri::UriScheme::Https; pub use crate::extdeps_uri::{Uri, UriScheme}; -pub use crate::std_types::{FilePathParts, NonEmptyStr}; +pub use crate::std_types::{FilePathParts, List, NonEmptyStr}; +use crate::std_workspace_artifact::FootprintProvenance::CitedUpstream; +use crate::std_workspace_artifact::IgnoreReason::{LocalCacheState, RegenerableFromSource}; +pub use crate::std_workspace_artifact::{ + FootprintProvenance, IgnoreReason, WorkspaceArtifact, WorkspaceFootprint, +}; use crate::v1_rt; use crate::v1_rt::{VecCompat, VecJoin}; use crate::NonEmptyBTreeSet; @@ -247,6 +252,37 @@ pub fn cargo_environment_variable_name(variable: CargoEnvironmentVariable) -> St } } +pub fn cargo_workspace_footprint( + target_dir_patterns: Rc>, + cargo_home_pattern: String, +) -> Rc { + Rc::new(WorkspaceFootprint { + provenance: Rc::new(FootprintProvenance::CitedUpstream { + display: "Cargo build artifacts".to_string(), + upstream: "doc.rust-lang.org/cargo/".to_string(), + }), + artifacts: v1_rt::concat( + Rc::new({ + let mut __result = Vec::new(); + for p in target_dir_patterns.iter().cloned() { + __result.push(Rc::new(WorkspaceArtifact { + pattern: p.clone(), + meaning: "cargo build output tree (compiled artifacts, incremental state)" + .to_string(), + reason: Rc::new(IgnoreReason::RegenerableFromSource), + })); + } + __result + }), + Rc::new(vec![Rc::new(WorkspaceArtifact { + pattern: cargo_home_pattern.clone(), + meaning: "CARGO_HOME registry/cache; may include git checkouts".to_string(), + reason: Rc::new(IgnoreReason::LocalCacheState), + })]), + ), + }) +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Edition2015; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] diff --git a/src/v1/stage0/src/lib.rs b/src/v1/stage0/src/lib.rs index 705736572ed..0cd72f8c030 100644 --- a/src/v1/stage0/src/lib.rs +++ b/src/v1/stage0/src/lib.rs @@ -91,6 +91,7 @@ pub mod std_trait_derive_shape; pub mod std_types; pub mod std_unicode_types; pub mod std_witness_admission; +pub mod std_workspace_artifact; pub mod v1_compiler_annotation_bind; pub mod v1_compiler_artifact; pub mod v1_compiler_closure_stub_v2_std_integer_rust; diff --git a/src/v1/stage0/src/std_workspace_artifact.rs b/src/v1/stage0/src/std_workspace_artifact.rs new file mode 100644 index 00000000000..a52dba1bd99 --- /dev/null +++ b/src/v1/stage0/src/std_workspace_artifact.rs @@ -0,0 +1,119 @@ +// Generated by v1 compiler -- do not edit. +// Source module: std.workspace_artifact + +use self::FootprintProvenance::*; +use self::IgnoreReason::*; +pub use crate::std_types::List; +use crate::v1_rt; +use crate::v1_rt::{VecCompat, VecJoin}; +use crate::NonEmptyBTreeSet; +use crate::NonEmptyVec; +use im::{vector as vec, HashMap, OrdSet as BTreeSet, Vector as Vec}; +use std::rc::Rc; + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum IgnoreReason { + RegenerableFromSource, + LocalCacheState, + PerDeveloperState, + HostOsMetadata, + SessionRuntimeState, + MayContainSecrets, + OutsideSubstrate, + SupersededAuthority { canonical: String }, +} +impl IgnoreReason { + pub fn canonical(&self) -> String { + match self { + IgnoreReason::RegenerableFromSource => panic!("no canonical on unit variant"), + IgnoreReason::LocalCacheState => panic!("no canonical on unit variant"), + IgnoreReason::PerDeveloperState => panic!("no canonical on unit variant"), + IgnoreReason::HostOsMetadata => panic!("no canonical on unit variant"), + IgnoreReason::SessionRuntimeState => panic!("no canonical on unit variant"), + IgnoreReason::MayContainSecrets => panic!("no canonical on unit variant"), + IgnoreReason::OutsideSubstrate => panic!("no canonical on unit variant"), + IgnoreReason::SupersededAuthority { + canonical: __val, .. + } => __val.clone(), + } + } +} + +pub fn ignore_reason_label(r: Rc) -> String { + match (*r.clone()).clone() { + IgnoreReason::RegenerableFromSource => "regenerable from committed source".to_string(), + IgnoreReason::LocalCacheState => "local cache; not project state".to_string(), + IgnoreReason::PerDeveloperState => "per-developer state; not shared".to_string(), + IgnoreReason::HostOsMetadata => "host OS metadata; not project state".to_string(), + IgnoreReason::SessionRuntimeState => { + "session/runtime state; not source-of-truth".to_string() + } + IgnoreReason::MayContainSecrets => "may contain secrets; never committed".to_string(), + IgnoreReason::OutsideSubstrate => "outside the committed substrate".to_string(), + IgnoreReason::SupersededAuthority { canonical: c, .. } => { + v1_rt::concat("superseded; canonical home: ".to_string(), c.clone()) + } + } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct WorkspaceArtifact { + pub pattern: String, + pub meaning: String, + pub reason: Rc, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum FootprintProvenance { + CitedUpstream { + display: String, + upstream: String, + }, + RepoTool { + display: String, + owner_module: String, + }, +} +impl FootprintProvenance { + pub fn display(&self) -> String { + match self { + FootprintProvenance::CitedUpstream { display: __val, .. } => __val.clone(), + FootprintProvenance::RepoTool { display: __val, .. } => __val.clone(), + } + } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct WorkspaceFootprint { + pub provenance: Rc, + pub artifacts: Rc>>, +} + +pub fn footprint_display(p: Rc) -> String { + match (*p.clone()).clone() { + FootprintProvenance::CitedUpstream { + display: d, + upstream: u, + .. + } => v1_rt::concat( + d.clone(), + v1_rt::concat( + " [cited: ".to_string(), + v1_rt::concat(u.clone(), "]".to_string()), + ), + ), + FootprintProvenance::RepoTool { + display: d, + owner_module: m, + .. + } => v1_rt::concat( + d.clone(), + v1_rt::concat( + " [owner: ".to_string(), + v1_rt::concat(m.clone(), "]".to_string()), + ), + ), + } +} diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 6067f83bbf0..7031b6e1a70 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -6236,13 +6236,6 @@ pub fn unresolved_method_frontier() -> Rc>> receiver_shape: "Product(SpanMapping)".to_string(), cause: "receiver is an Optional produced by `|> last`, and the optional functor is being mapped over. It arrives as the INNER product because the optional cardinality is dropped before method lookup, so Optional's own surface is never consulted.".to_string(), dissolution: crate::std_dissolution::unbound_dissolution("reconciling the two optionality representations (cardinality-marked node vs the nominal Optional coproduct) so an optional receiver keeps its optional surface at method lookup".to_string()), -}), Rc::new(UnresolvedMethodFrontierRow { - module_name: "gunbc.source_integration_landing_spine".to_string(), - method: "map".to_string(), - occurrences: 1, - receiver_shape: "Node(Optional)".to_string(), - cause: "same optional-functor class as the v1.compiler.trace row, in its OTHER surface form: here the Optional survives as a named node rather than collapsing to its inner product, and neither form carries a method surface. Two shapes for one concept is itself the defect the trigger names.".to_string(), - dissolution: crate::std_dissolution::unbound_dissolution("reconciling the two optionality representations so an optional receiver keeps its optional surface at method lookup".to_string()), }), Rc::new(UnresolvedMethodFrontierRow { module_name: "test.claim.sccache_local_content_verified_on_read".to_string(), method: "contains".to_string(), diff --git a/src/v1/stage0/src/v1_compiler_runtime_rust.rs b/src/v1/stage0/src/v1_compiler_runtime_rust.rs index 341171beb24..7711aa64f38 100644 --- a/src/v1/stage0/src/v1_compiler_runtime_rust.rs +++ b/src/v1/stage0/src/v1_compiler_runtime_rust.rs @@ -94,7 +94,7 @@ pub fn rt_filesystem() -> String { } pub fn rt_hash_ops() -> String { - v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat("const FNV1A64_OFFSET: u64 = 0xcbf29ce484222325;\n".to_string(), "const FNV1A64_PRIME: u64 = 0x100000001b3;\n".to_string()), "\n".to_string()), "fn fnv1a64(bytes: &[u8]) -> u64 {\n".to_string()), " let mut hash = FNV1A64_OFFSET;\n".to_string()), " for b in bytes {\n".to_string()), " hash ^= *b as u64;\n".to_string()), " hash = hash.wrapping_mul(FNV1A64_PRIME);\n".to_string()), " }\n".to_string()), " hash\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub type Hash = String;\n".to_string()), "\n".to_string()), "const HASH_DIGEST_LEN: usize = 16;\n".to_string()), "\n".to_string()), "pub fn is_hash_digest(s: &str) -> bool {\n".to_string()), " s.len() == HASH_DIGEST_LEN && s.bytes().all(|b| b.is_ascii_hexdigit())\n".to_string()), "}\n".to_string()), "\n".to_string()), "fn expect_hash_digest(s: &str, arg: &str) {\n".to_string()), " if !is_hash_digest(s) {\n".to_string()), " panic!(\"{} must be a 16-char hex Hash digest\", arg);\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Kept so `gunbc.observation_emit_census` roster hygiene cannot go stale after the\n".to_string()), "/// raw gantt key=value shape (process-absolute millis and rss-mib fields) dissolves into the observation projection.\n".to_string()), "#[allow(dead_code)]\n".to_string()), "pub const GANTT_CENSUS_MARKER: &str = \"[gantt]\";\n".to_string()), "\n".to_string()), "/// Mirror of `gunbc.observation_ci_render.ci_minute_switch_seconds`.\n".to_string()), "const OBS_MINUTE_SWITCH_SECONDS: u64 = 90;\n".to_string()), "\n".to_string()), "pub fn obs_human_duration(ms: u64) -> String {\n".to_string()), " if ms < 1_000 {\n".to_string()), " format!(\"{ms}ms\")\n".to_string()), " } else if ms < OBS_MINUTE_SWITCH_SECONDS * 1_000 {\n".to_string()), " format!(\"{} seconds\", ms / 1_000)\n".to_string()), " } else {\n".to_string()), " format!(\"{} minutes\", ms / 60_000)\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Mirror of `gunbc.observation_ci_render.ci_human_elapsed`.\n".to_string()), "pub fn obs_human_elapsed(wall_nanos: u128) -> String {\n".to_string()), " if wall_nanos < 1_000_000 {\n".to_string()), " format!(\"{wall_nanos}ns\")\n".to_string()), " } else {\n".to_string()), " obs_human_duration((wall_nanos / 1_000_000) as u64)\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "fn obs_phase_emoji() -> bool {\n".to_string()), " std::env::var(\"GITHUB_ACTIONS\").as_deref() == Ok(\"true\")\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Pure Rust mirror of `gunbc.observation_seed_render.phase_begin_line` —\n".to_string()), "/// `ci_event_line(Begin) ∘ ci_render_line`. Justified divergence from the\n".to_string()), "/// interpreter seed boundary used by floor prelude marks: `trace_mark` runs\n".to_string()), "/// inside compile itself (hand-synced path and interpreter intrinsic), and\n".to_string()), "/// calling back into the interpreter to render would recurse. Proven\n".to_string()), "/// byte-equal to the `.dag` oracle by the seed RED.\n".to_string()), "pub fn render_phase_begin_line_mirror(phase: &str, emoji: bool) -> String {\n".to_string()), " let glyph = if emoji { \"🔄\" } else { \"◐\" };\n".to_string()), " format!(\"{glyph} started {phase}\")\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Pure Rust mirror of `gunbc.observation_seed_render.phase_concluded_line` —\n".to_string()), "/// `ci_event_line(Concluded{Done}) ∘ ci_render_line`. Same justified-divergence\n".to_string()), "/// note as `render_phase_begin_line_mirror`.\n".to_string()), "pub fn render_phase_concluded_line_mirror(phase: &str, elapsed_ms: u64, emoji: bool) -> String {\n".to_string()), " let glyph = if emoji { \"✅\" } else { \"✓\" };\n".to_string()), " format!(\"{glyph} {phase} done in {}\", obs_human_duration(elapsed_ms))\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Stage-boundary trace mark — the v1-seed interim realization of the v2 per-RealizedStep\n".to_string()), "/// CostAccount (std.realization_measurement). Wired (gantt flip): projects Begin/Concluded\n".to_string()), "/// on a PhaseSegment via the observation mirrors of `ci_event_line`. Segment wall on\n".to_string()), "/// Concluded (matched `.begin`→`.done`, else delta since last mark) — never the old\n".to_string()), "/// process-absolute millis field. RSS stays on heartbeat/measurement (`ci_event_line` does\n".to_string()), "/// not project `event.rss` — explicit divergence from the deleted rss-mib field).\n".to_string()), "///\n".to_string()), "/// **Dissolution trigger (DESIGN §6):** delete this fn, the `trace_mark` registry row in\n".to_string()), "/// `04_method.dag` (+ hand-synced twin `v1_compiler_infer_method.rs`), the nine\n".to_string()), "/// `trace_mark(...)` marks in `compile.dag` (+ hand-synced `v1_compiler_compile.rs`), and\n".to_string()), "/// the interpreter arm in `v1_interpreter.rs` when realization_measurement_loop **Phase 0**\n".to_string()), "/// (`docs/plans/realization-measurement-loop.md`) lands a `.dag` `PerformanceReceipt`\n".to_string()), "/// per-stage carrier that a floor witness consumes by execution (the same retirement event\n".to_string()), "/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `docs/plans/ci-floor-fractal-gantt.md`\n".to_string()), "/// § dissolution). Receipt = that witness green with these marks deleted and stage walls\n".to_string()), "/// still attributable from the model path.\n".to_string()), "pub fn trace_mark(label: String) {\n".to_string()), " use std::sync::{Mutex, OnceLock};\n".to_string()), " use std::time::Instant;\n".to_string()), " static TRACE_T0: OnceLock = OnceLock::new();\n".to_string()), " static LAST_MARK: OnceLock> = OnceLock::new();\n".to_string()), " static OPENS: OnceLock>> = OnceLock::new();\n".to_string()), " let t0 = TRACE_T0.get_or_init(Instant::now);\n".to_string()), " let last = LAST_MARK.get_or_init(|| Mutex::new(*t0));\n".to_string()), " let opens = OPENS.get_or_init(|| Mutex::new(std::collections::HashMap::new()));\n".to_string()), " let emoji = obs_phase_emoji();\n".to_string()), " let now = Instant::now();\n".to_string()), " let _ = GANTT_CENSUS_MARKER;\n".to_string()), " if let Some(phase) = label.strip_suffix(\".begin\") {\n".to_string()), " if let Ok(mut map) = opens.lock() {\n".to_string()), " map.insert(phase.to_string(), now);\n".to_string()), " }\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\"{}\", render_phase_begin_line_mirror(phase, emoji));\n".to_string()), " } else if let Some(phase) = label.strip_suffix(\".done\") {\n".to_string()), " let elapsed_ms = {\n".to_string()), " let started = opens.lock().ok().and_then(|mut m| m.remove(phase));\n".to_string()), " match started {\n".to_string()), " Some(t) => now.saturating_duration_since(t).as_millis() as u64,\n".to_string()), " None => {\n".to_string()), " let prev = last.lock().map(|l| *l).unwrap_or(*t0);\n".to_string()), " now.saturating_duration_since(prev).as_millis() as u64\n".to_string()), " }\n".to_string()), " }\n".to_string()), " };\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\n".to_string()), " \"{}\",\n".to_string()), " render_phase_concluded_line_mirror(phase, elapsed_ms, emoji)\n".to_string()), " );\n".to_string()), " } else {\n".to_string()), " let prev = last.lock().map(|l| *l).unwrap_or(*t0);\n".to_string()), " let elapsed_ms = now.saturating_duration_since(prev).as_millis() as u64;\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\n".to_string()), " \"{}\",\n".to_string()), " render_phase_concluded_line_mirror(&label, elapsed_ms, emoji)\n".to_string()), " );\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Content hash over raw bytes — the byte-level single authority. `atom_identity_hash`\n".to_string()), "/// is the `String` projection of this. Use this directly for arbitrary binary content\n".to_string()), "/// (e.g. an executable or serialized payload): routing bytes through `String`/\n".to_string()), "/// `from_utf8_lossy` first collapses every invalid UTF-8 sequence to U+FFFD, so distinct\n".to_string()), "/// byte sequences would hash equal — a §5 silent-collision fail-open for content-addressing.\n".to_string()), "pub fn bytes_identity_hash(bytes: &[u8]) -> Hash {\n".to_string()), " format!(\"{:016x}\", fnv1a64(bytes))\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub fn atom_identity_hash(s: String) -> Hash {\n".to_string()), " bytes_identity_hash(s.as_bytes())\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub fn hash_combine(a: Hash, b: Hash) -> Hash {\n".to_string()), " expect_hash_digest(&a, \"a\");\n".to_string()), " expect_hash_digest(&b, \"b\");\n".to_string()), " let mut bytes = a.into_bytes();\n".to_string()), " bytes.push(0);\n".to_string()), " bytes.extend_from_slice(b.as_bytes());\n".to_string()), " format!(\"{:016x}\", fnv1a64(&bytes))\n".to_string()), "}\n".to_string()), "\n".to_string()) + v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat("const FNV1A64_OFFSET: u64 = 0xcbf29ce484222325;\n".to_string(), "const FNV1A64_PRIME: u64 = 0x100000001b3;\n".to_string()), "\n".to_string()), "fn fnv1a64(bytes: &[u8]) -> u64 {\n".to_string()), " let mut hash = FNV1A64_OFFSET;\n".to_string()), " for b in bytes {\n".to_string()), " hash ^= *b as u64;\n".to_string()), " hash = hash.wrapping_mul(FNV1A64_PRIME);\n".to_string()), " }\n".to_string()), " hash\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub type Hash = String;\n".to_string()), "\n".to_string()), "const HASH_DIGEST_LEN: usize = 16;\n".to_string()), "\n".to_string()), "pub fn is_hash_digest(s: &str) -> bool {\n".to_string()), " s.len() == HASH_DIGEST_LEN && s.bytes().all(|b| b.is_ascii_hexdigit())\n".to_string()), "}\n".to_string()), "\n".to_string()), "fn expect_hash_digest(s: &str, arg: &str) {\n".to_string()), " if !is_hash_digest(s) {\n".to_string()), " panic!(\"{} must be a 16-char hex Hash digest\", arg);\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Kept so `gunbc.observation_emit_census` roster hygiene cannot go stale after the\n".to_string()), "/// raw gantt key=value shape (process-absolute millis and rss-mib fields) dissolves into the observation projection.\n".to_string()), "#[allow(dead_code)]\n".to_string()), "pub const GANTT_CENSUS_MARKER: &str = \"[gantt]\";\n".to_string()), "\n".to_string()), "/// Mirror of `gunbc.observation_ci_render.ci_minute_switch_seconds`.\n".to_string()), "const OBS_MINUTE_SWITCH_SECONDS: u64 = 90;\n".to_string()), "\n".to_string()), "pub fn obs_human_duration(ms: u64) -> String {\n".to_string()), " if ms < 1_000 {\n".to_string()), " format!(\"{ms}ms\")\n".to_string()), " } else if ms < OBS_MINUTE_SWITCH_SECONDS * 1_000 {\n".to_string()), " format!(\"{} seconds\", ms / 1_000)\n".to_string()), " } else {\n".to_string()), " format!(\"{} minutes\", ms / 60_000)\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Mirror of `gunbc.observation_ci_render.ci_human_elapsed`.\n".to_string()), "pub fn obs_human_elapsed(wall_nanos: u128) -> String {\n".to_string()), " if wall_nanos < 1_000_000 {\n".to_string()), " format!(\"{wall_nanos}ns\")\n".to_string()), " } else {\n".to_string()), " obs_human_duration((wall_nanos / 1_000_000) as u64)\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "fn obs_phase_emoji() -> bool {\n".to_string()), " std::env::var(\"GITHUB_ACTIONS\").as_deref() == Ok(\"true\")\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Pure Rust mirror of `gunbc.observation_seed_render.phase_begin_line` —\n".to_string()), "/// `ci_event_line(Begin) ∘ ci_render_line`. Justified divergence from the\n".to_string()), "/// interpreter seed boundary used by floor prelude marks: `trace_mark` runs\n".to_string()), "/// inside compile itself (hand-synced path and interpreter intrinsic), and\n".to_string()), "/// calling back into the interpreter to render would recurse. Proven\n".to_string()), "/// byte-equal to the `.dag` oracle by the seed RED.\n".to_string()), "pub fn render_phase_begin_line_mirror(phase: &str, emoji: bool) -> String {\n".to_string()), " let glyph = if emoji { \"🔄\" } else { \"◐\" };\n".to_string()), " format!(\"{glyph} started {phase}\")\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Pure Rust mirror of `gunbc.observation_seed_render.phase_concluded_line` —\n".to_string()), "/// `ci_event_line(Concluded{Done}) ∘ ci_render_line`. Same justified-divergence\n".to_string()), "/// note as `render_phase_begin_line_mirror`.\n".to_string()), "pub fn render_phase_concluded_line_mirror(phase: &str, elapsed_ms: u64, emoji: bool) -> String {\n".to_string()), " let glyph = if emoji { \"✅\" } else { \"✓\" };\n".to_string()), " format!(\"{glyph} {phase} done in {}\", obs_human_duration(elapsed_ms))\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Stage-boundary trace mark — the v1-seed interim realization of the v2 per-RealizedStep\n".to_string()), "/// CostAccount (std.realization_measurement). Wired (gantt flip): projects Begin/Concluded\n".to_string()), "/// on a PhaseSegment via the observation mirrors of `ci_event_line`. Segment wall on\n".to_string()), "/// Concluded (matched `.begin`→`.done`, else delta since last mark) — never the old\n".to_string()), "/// process-absolute millis field. RSS stays on heartbeat/measurement (`ci_event_line` does\n".to_string()), "/// not project `event.rss` — explicit divergence from the deleted rss-mib field).\n".to_string()), "///\n".to_string()), "/// **Dissolution trigger (DESIGN §6):** delete this fn, the `trace_mark` registry row in\n".to_string()), "/// `04_method.dag` (+ hand-synced twin `v1_compiler_infer_method.rs`), the nine\n".to_string()), "/// `trace_mark(...)` marks in `compile.dag` (+ hand-synced `v1_compiler_compile.rs`), and\n".to_string()), "/// the interpreter arm in `v1_interpreter.rs` when realization_measurement_loop **Phase 0**\n".to_string()), "/// (`docs/plans/realization-measurement-loop.md`) lands a `.dag` `PerformanceReceipt`\n".to_string()), "/// per-stage carrier that a floor witness consumes by execution (the same retirement event\n".to_string()), "/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `ci-floor-fractal-gantt (plan doc deleted 2026-08-28)`\n".to_string()), "/// § dissolution). Receipt = that witness green with these marks deleted and stage walls\n".to_string()), "/// still attributable from the model path.\n".to_string()), "pub fn trace_mark(label: String) {\n".to_string()), " use std::sync::{Mutex, OnceLock};\n".to_string()), " use std::time::Instant;\n".to_string()), " static TRACE_T0: OnceLock = OnceLock::new();\n".to_string()), " static LAST_MARK: OnceLock> = OnceLock::new();\n".to_string()), " static OPENS: OnceLock>> = OnceLock::new();\n".to_string()), " let t0 = TRACE_T0.get_or_init(Instant::now);\n".to_string()), " let last = LAST_MARK.get_or_init(|| Mutex::new(*t0));\n".to_string()), " let opens = OPENS.get_or_init(|| Mutex::new(std::collections::HashMap::new()));\n".to_string()), " let emoji = obs_phase_emoji();\n".to_string()), " let now = Instant::now();\n".to_string()), " let _ = GANTT_CENSUS_MARKER;\n".to_string()), " if let Some(phase) = label.strip_suffix(\".begin\") {\n".to_string()), " if let Ok(mut map) = opens.lock() {\n".to_string()), " map.insert(phase.to_string(), now);\n".to_string()), " }\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\"{}\", render_phase_begin_line_mirror(phase, emoji));\n".to_string()), " } else if let Some(phase) = label.strip_suffix(\".done\") {\n".to_string()), " let elapsed_ms = {\n".to_string()), " let started = opens.lock().ok().and_then(|mut m| m.remove(phase));\n".to_string()), " match started {\n".to_string()), " Some(t) => now.saturating_duration_since(t).as_millis() as u64,\n".to_string()), " None => {\n".to_string()), " let prev = last.lock().map(|l| *l).unwrap_or(*t0);\n".to_string()), " now.saturating_duration_since(prev).as_millis() as u64\n".to_string()), " }\n".to_string()), " }\n".to_string()), " };\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\n".to_string()), " \"{}\",\n".to_string()), " render_phase_concluded_line_mirror(phase, elapsed_ms, emoji)\n".to_string()), " );\n".to_string()), " } else {\n".to_string()), " let prev = last.lock().map(|l| *l).unwrap_or(*t0);\n".to_string()), " let elapsed_ms = now.saturating_duration_since(prev).as_millis() as u64;\n".to_string()), " if let Ok(mut l) = last.lock() {\n".to_string()), " *l = now;\n".to_string()), " }\n".to_string()), " eprintln!(\n".to_string()), " \"{}\",\n".to_string()), " render_phase_concluded_line_mirror(&label, elapsed_ms, emoji)\n".to_string()), " );\n".to_string()), " }\n".to_string()), "}\n".to_string()), "\n".to_string()), "/// Content hash over raw bytes — the byte-level single authority. `atom_identity_hash`\n".to_string()), "/// is the `String` projection of this. Use this directly for arbitrary binary content\n".to_string()), "/// (e.g. an executable or serialized payload): routing bytes through `String`/\n".to_string()), "/// `from_utf8_lossy` first collapses every invalid UTF-8 sequence to U+FFFD, so distinct\n".to_string()), "/// byte sequences would hash equal — a §5 silent-collision fail-open for content-addressing.\n".to_string()), "pub fn bytes_identity_hash(bytes: &[u8]) -> Hash {\n".to_string()), " format!(\"{:016x}\", fnv1a64(bytes))\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub fn atom_identity_hash(s: String) -> Hash {\n".to_string()), " bytes_identity_hash(s.as_bytes())\n".to_string()), "}\n".to_string()), "\n".to_string()), "pub fn hash_combine(a: Hash, b: Hash) -> Hash {\n".to_string()), " expect_hash_digest(&a, \"a\");\n".to_string()), " expect_hash_digest(&b, \"b\");\n".to_string()), " let mut bytes = a.into_bytes();\n".to_string()), " bytes.push(0);\n".to_string()), " bytes.extend_from_slice(b.as_bytes());\n".to_string()), " format!(\"{:016x}\", fnv1a64(&bytes))\n".to_string()), "}\n".to_string()), "\n".to_string()) } pub fn rt_resolution_silent_pick_telemetry() -> String { diff --git a/src/v1/stage0/src/v1_rt.rs b/src/v1/stage0/src/v1_rt.rs index 610fb995379..97af46d127e 100644 --- a/src/v1/stage0/src/v1_rt.rs +++ b/src/v1/stage0/src/v1_rt.rs @@ -1005,7 +1005,7 @@ pub fn render_phase_concluded_line_mirror(phase: &str, elapsed_ms: u64, emoji: b /// the interpreter arm in `v1_interpreter.rs` when realization_measurement_loop **Phase 0** /// (`docs/plans/realization-measurement-loop.md`) lands a `.dag` `PerformanceReceipt` /// per-stage carrier that a floor witness consumes by execution (the same retirement event -/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `docs/plans/ci-floor-fractal-gantt.md` +/// as `phase_profile.rs` / `GUNBC_FLOOR_GANTT`, per `ci-floor-fractal-gantt (plan doc deleted 2026-08-28)` /// § dissolution). Receipt = that witness green with these marks deleted and stage walls /// still attributable from the model path. pub fn trace_mark(label: String) {