Repository navigation
Remove hollow Url=String alias (§3); ground RestTransportConfig.base_url as Uri - #5818
Conversation
…ri.dag model Removes the hollow alias `type Url = String` from std/types.dag (a §2 violation — the alias named a concept without grounding it to the extdeps.uri model). Migrates all 20 call sites: - API wire response fields (html_url, documentation_url) → NonEmptyStr (honest: GitHub returns these as strings, not structured URIs) - Service-endpoint data constants (default_api_base, sts_endpoint) → NonEmptyStr (used as string values in service config blocks) - Git remote URL (GitRemote.url) → NonEmptyStr (git remote URLs include non-standard formats like git@github.com: that are not covered by the UriScheme enum) - REST transport base URL (RestTransportConfig.base_url) → Uri (we always construct this with a known scheme; makes the scheme queryable and untyped strings unwritable) - Internal URL string fields (AttachedUrl, TrackedIssue, PipelineArtifact, LaunchConfig) → NonEmptyStr Adds uri_grounding_witness_test.dag proving RestTransportConfig.base_url requires a typed Uri construction and that uri_wire round-trips correctly. Updates affected test witnesses (code_change_workflow, string_family_cast, extdeps_github_errors_url_grounding) to remove the now-deleted Url type.
…d inert carrier) RestTransportConfig has zero real consumers outside its declaring file. My test was the first to import it in a *_test.dag, making it self-tested+unconsumed and triggering inert_carrier_no_unrostered_or_stale. The Uri construction wall is proven by the rest.dag type change; the test just needs to demonstrate the Uri model directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thank you for the thorough review. Two things to address: Finding 2 (errors.dag:15 Finding 1 (title overpromises / Construction sites — values we control at authoring time — should use Wire-ingestion sites — values that arrive as JSON strings from the GitHub REST API ( Service endpoint constants (
The PR title was imprecise. The scope is: remove the hollow — sent from bold-dove-644 |
|
Finding 1 — The The Finding 2 — dissolve-on markers for remaining Agreed on the debt. .dag has no comment syntax (parse error since #5579), so in-file markers aren't possible. The PR body already carries the dissolution trigger: "dissolve-on: uri_parse(String)->Uri? lands with DecodeFidelity boundary" — that's the named follow-up scoping when the wire-field migration becomes unblocked. — sent from bold-dove-644 |
|
Acknowledged on — sent from bold-dove-644 |
…5819) Operator ruled Path B for the #5864 parser seed-cement: v1_compiler_parse.rs moves to HAND_MAINTAINED_STAGE0_FILES (copy-preserved, so #5864's O(N) cursor optimization survives the regen instead of being reverted to the O(N^2) baseline that 02_parse.dag still models). Named dissolution trigger marked on the carrier. Re-regenerated the two-generation cutover against fresh main (incl #5865 casing, #5818 Uri grounding, #5819 ci.yml thin-shim). regen_stage0 --verify exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…oint The full-workspace build (the broadened oracle CI rust_tests uses) exposed two more pre-existing main non-fixed-points that the cutover surfaces: 1. stage0_core E0432/E0433: the faithful regen emits use crate::extdeps_uri / extdeps_external_authority in the extdeps_languages_* modules and use crate::std_realization_schedule/std_decl_ref in std_effects/std_emit_model, but stage0_crates.dag's CoreCrate modules list omitted them. Added the full transitive closure (9 modules: extdeps_external_authority, extdeps_uri, std_decl_ref, std_lens_verdict, std_magnitude, std_measure, std_nat, std_pareto, std_realization_schedule) so stage0_core is closed under crate:: deps. 2. effects.rs (hand-test) imported parse_path_template/PathTemplateParseResult from std_http_path, but #5818 moved them to extdeps_uri_path in the authority (main never regenerated, so its stale seed + test still pointed at std_http_path). Repointed the imports to the fixed-point location. regen_stage0 --verify exit 0; cargo build --workspace --all-targets -D warnings 0/0; parse.rs still byte-identical to origin/main (#5864 preserved). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…g (unblocks v1 Rust PRs) contracts_sidecar_wired_into_emit_scope fails on origin/main (verified on a clean #5818 checkout) — main's CI stays green only because affected-test scoping skips it; any PR touching v1-compiler Rust triggers the full suite and surfaces it. Root cause: the anthropic module was split into anthropic / anthropic_errors / anthropic_rest. The test's `.find(|f| f.path.contains("extdeps_llm_anthropic") && !_contracts)` now matches the split-out siblings too, and .find() grabbed anthropic_errors.rs (no AnthropicChatMessage, no `tag = "role"`). The contract merges correctly into extdeps_llm_anthropic.rs (verified: has_role_tag=true there). Fix: match the declaring module's file exactly (ends_with extdeps_llm_anthropic.rs). Emit/contracts behavior unchanged — test-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….dag updated but .rs missed) interp_string_family_cast_test::string_family_alias_casts_are_identity_at_runtime fails on origin/main: #5818 removed `type Url = String` from std.types and updated the .dag witnesses, but missed this Rust test's inline `import std.types { ... Url }` + `string_to_url`, so the embedded module no longer resolves. Surfaced (like the contracts test) only because this PR triggers the full v1-compiler-tests suite. Fix mirrors #5818's .dag witness edits: drop Url from the import and the string_to_url cast/assertion. Test-only; the remaining Secret/NonEmptyStr/SecretValue casts are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1. find_struct_name_by_fields (emit_rust.rs): candidates Vec came from HashMap iteration (map_values), making .first() non-deterministic when multiple record types share the same field names. Sort candidates by name before selecting first. This fixes emit alternating between AnthropicModelSpec vs OpenAiModelSpec (same field names, different model-field types) and PosixSubject vs FileOwnership (identical field sets uid/gid). 2. interp_string_family_cast_test (test update): #5818 removed the hollow Url=String alias from std.types (§3 violation). Update the Rust unit test to match string_family_cast_witness_test.dag — remove the Url import and string_to_url fn; Uri is a struct and does not participate in the string-cast family. Oracle after all fixes: double-emit of 609 dsl modules → EMPTY diff. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rolled Rust boxes (#5874) * Render CI timing histogram through .dag (std.render Frame); fix dormant std display-width Redo of this PR's box-width slice the principled way (the prior version hand-rolled the boxes in Rust — a parallel re-implementation of std.render.Viewport + extdeps/render/terminal::constrain_frame, flagged in review). The histogram boxes were Rust with fixed ~78-col borders under ~95-col content — too short in wide viewers (GHA), wrapping in narrow ones (dashboard chat). Now: - extdeps/render/terminal.dag gains serialize_frame (Frame -> String, color-gated by RenderCapability via ansi_code + resolve_symbol) — the one missing primitive. - dsl/gunbc/ci_render.dag builds each percentile box as a std.render Frame, bordered + padded to a width PARAMETER (the medium's Viewport.width); every line is uniformly that width. Single authority for box width. - claim_executor evaluates render_percentile_box via run_in_context_with_args (the seam eval_spawn_width already uses) — a real consumer, green by execution. The seed supplies only measured percentiles + the host viewport width (COLUMNS, else 88, clamped); all layout/formatting lives in .dag. - cli_run.rs drops the Rust box renderer + format_nanos, keeping only compute_histogram_data (the measurement the evaluator can't get otherwise). Review fixes (§3 single authority): - consume std.render.repeat_string (deleted the local repeat_str fork). - consume std.unicode.string_display_width + std.width.truncate_text — and FIX them: both were dormant-broken (chars yields Char = `Int where unicode_scalar`, but char_display_width called code_point(c) which wants a String, and truncate_text did concat(String, Char)). Now char_display_width reads the scalar directly and truncate_text rebuilds via from_code_point — string_display_width works for the first time (correct CJK/combining width via its block tables). - box borders source glyphs from the registry (extdeps/render/glyphs.resolve_symbol with a Tier) instead of hardcoded "┌─│┘" literals: 6 new Box* SymbolIds with single-column ASCII fallbacks, so a non-Unicode tier yields a "+--+"/"|" box automatically (no §5 mojibake fail-open). Witness ci_render_histogram_width_test: every box line == requested width at two widths (rules out a constant), exact Unicode 3-line output, ASCII-tier width holds, and tier swaps glyphs. cargo build / fmt --all --check / clippy --all-targets clean; full v1-compiler test suite green. Render failure is fail-visible but non-fatal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix pre-existing contracts_sidecar_wired_into_emit_scope test-glob bug (unblocks v1 Rust PRs) contracts_sidecar_wired_into_emit_scope fails on origin/main (verified on a clean #5818 checkout) — main's CI stays green only because affected-test scoping skips it; any PR touching v1-compiler Rust triggers the full suite and surfaces it. Root cause: the anthropic module was split into anthropic / anthropic_errors / anthropic_rest. The test's `.find(|f| f.path.contains("extdeps_llm_anthropic") && !_contracts)` now matches the split-out siblings too, and .find() grabbed anthropic_errors.rs (no AnthropicChatMessage, no `tag = "role"`). The contract merges correctly into extdeps_llm_anthropic.rs (verified: has_role_tag=true there). Fix: match the declaring module's file exactly (ends_with extdeps_llm_anthropic.rs). Emit/contracts behavior unchanged — test-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix pre-existing string_family_cast Rust test (Url removed by #5818, .dag updated but .rs missed) interp_string_family_cast_test::string_family_alias_casts_are_identity_at_runtime fails on origin/main: #5818 removed `type Url = String` from std.types and updated the .dag witnesses, but missed this Rust test's inline `import std.types { ... Url }` + `string_to_url`, so the embedded module no longer resolves. Surfaced (like the contracts test) only because this PR triggers the full v1-compiler-tests suite. Fix mirrors #5818's .dag witness edits: drop Url from the import and the string_to_url cast/assertion. Test-only; the remaining Secret/NonEmptyStr/SecretValue casts are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Model histogram durations as std.measure.Nanosecond, not bare Int (unit-modeling hard-block) Per the standing unit-modeling rule (§3 single authority / consume-never-fork) and review: the percentiles are nanosecond durations — a unit-bearing physical quantity — so the .dag API now lands on std.measure.Nanosecond (Measure<Time, Nano, Nat>) instead of flat Int. - format_duration / timing_cell / percentile_row / percentile_box_frame all take Nanosecond. - nanosecond(count:) / nanosecond_count(n:) from std.measure are consumed (no local unit type). - The seed<->.dag boundary stays Int (claim_executor passes raw measured nanos via clamp_nanos_to_i64); percentiles_box_frame_ns wraps those into Nanosecond immediately, so the unit-bearing type is the authority everywhere downstream. Witness updated to the Nanosecond boundary; still green (exact box, width invariants, tier swap). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rt import keys (#5879) * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * Make Rust emitter deterministic: sort variant_to_enum owner selection variant_fold in build_module_context iterated env.bindings (HashMap<i64,TypeBinding>) via map_values(), producing non-deterministic ordering. When multiple coproducts share a variant, the first-processed wins; HashMap iteration order varies per process, so 37 files diffed between two runs of the same corpus. Sort bindings by binding.name before folding so the alphabetically-first type name always wins — stable across runs. Also removes debug eprintln! instrumentation added during diagnosis (v1_compiler_emit_rust.rs effective_variant_parent and v1_compiler_infer_emit_info.rs derive_variant_to_enum). Oracle: two corpus emits produce empty diff. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * Make Rust emitter deterministic: correct variant owner-selection + sort emit imports - v1_compiler_infer.rs: replace dead imported_enum_names (per-binding) with imported_variants (per-child) disambiguation. Looks up variant→parent enum in the SOURCE module (parent_index), not the current module's transitive env. ApiKey in std.cache_interface is unambiguously AuthScope (not AuthScheme which transits in from std.types). writeThenCommit is ambiguous (both AtomicityModel and CacheWriteSemantics define it) → falls back to alpha sort. Sort is kept for determinism on ambiguous cases. - v1_compiler_emit_rust.rs: sort map_keys outputs at 3 export_sets call sites (wildcard_reexport_surface_names, wildcard_import_pool_surface_names, reexport_parents) to make pub use ordering deterministic. Residue (noted): WriteThenCommit owner-selection is correct-by-alpha-accident (AtomicityModel < CacheWriteSemantics alphabetically, which is the intended field type). This is a latent §3 collision; the imported_variants map returns None for it (ambiguous in source module) and alpha tie-break happens to win. * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * Fix two more non-determinism sites after merge with main 1. find_struct_name_by_fields (emit_rust.rs): candidates Vec came from HashMap iteration (map_values), making .first() non-deterministic when multiple record types share the same field names. Sort candidates by name before selecting first. This fixes emit alternating between AnthropicModelSpec vs OpenAiModelSpec (same field names, different model-field types) and PosixSubject vs FileOwnership (identical field sets uid/gid). 2. interp_string_family_cast_test (test update): #5818 removed the hollow Url=String alias from std.types (§3 violation). Update the Rust unit test to match string_family_cast_witness_test.dag — remove the Url import and string_to_url fn; Uri is a struct and does not participate in the string-cast family. Oracle after all fixes: double-emit of 609 dsl modules → EMPTY diff. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * WIP: Make the Rust emitter deterministic (variant_to_enum HashMap owner-selec * fix find_struct_name_by_fields: disambiguate by field types when multiple struct candidates share the same field names AnthropicModelSpec and OpenAiModelSpec have identical field names but different field types (model: AnthropicModel vs model: OpenAiModel). The previous sort-by-name fix was deterministic but wrong — it always picked AnthropicModelSpec for both modules, emitting invalid Rust (wrong constructor name). Now passes field_type_hints (field_name → inferred value type) from the call site; the function filters candidates by type compatibility before falling back to alpha sort. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
… into executable RegenVerifyGate (cargo-green self-host fixed point, ONE PR) (#5873) * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * Part B: dissolve parked regen_verify_gate plan into executable RegenVerifyGate Adds RegenVerifyGate to the CI floor (ci_spec type Gate + gunbc_ci_floor_gates), wires all exhaustive Gate matches (ci_floor_plan gate_node/gate_runnable/ gate_is_heavy_resolve/gate_spawns_host_compiler, ci_gates.run_spec_gate, floor_effect_gate_witness). New dsl/tools/regen_verify_{gate,transport}.dag run regen_stage0 --verify (the §7 self-host fixed-point wall) via a new ensure_regen_stage0_built host-prelude helper. Deletes the parked plan, its empty plan_registry_batch_a, the generated required-facts md, and repoints the roadmap carrier. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * Part A: two-generation cutover regen to the cargo-green self-host fixed point Applies #5865's casing fix (05_emit_rust.dag) and runs the 2-pass cutover regen: pass-1 advances the self-host blob + emitter (gen-1 drops v1_rt starts_with/ ends_with/trim, the one-generation-ahead seed-cement), rebuild, pass-2 re-emits them fresh (PascalCase). regen_stage0 --verify now exits 0 (a 3rd pass is byte-identical = THE fixed point). Registers extdeps_uri_path.rs in GENERATED_STAGE0_FILES (the legit unregistered-emit gap). Regenerates ROADMAP.md. Drift checks: cargo-header reproduced via emit_cargo_toml, wire_value_serialize.rs unchanged (hand-maintained, copy-preserved), v1_rt.rs emitted-fresh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * Path B: parse.rs hand-maintained + re-regen against fresh main (#5818/#5819) Operator ruled Path B for the #5864 parser seed-cement: v1_compiler_parse.rs moves to HAND_MAINTAINED_STAGE0_FILES (copy-preserved, so #5864's O(N) cursor optimization survives the regen instead of being reverted to the O(N^2) baseline that 02_parse.dag still models). Named dissolution trigger marked on the carrier. Re-regenerated the two-generation cutover against fresh main (incl #5865 casing, #5818 Uri grounding, #5819 ci.yml thin-shim). regen_stage0 --verify exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * Fix stage0_core crate membership + hand-test for the faithful fixed point The full-workspace build (the broadened oracle CI rust_tests uses) exposed two more pre-existing main non-fixed-points that the cutover surfaces: 1. stage0_core E0432/E0433: the faithful regen emits use crate::extdeps_uri / extdeps_external_authority in the extdeps_languages_* modules and use crate::std_realization_schedule/std_decl_ref in std_effects/std_emit_model, but stage0_crates.dag's CoreCrate modules list omitted them. Added the full transitive closure (9 modules: extdeps_external_authority, extdeps_uri, std_decl_ref, std_lens_verdict, std_magnitude, std_measure, std_nat, std_pareto, std_realization_schedule) so stage0_core is closed under crate:: deps. 2. effects.rs (hand-test) imported parse_path_template/PathTemplateParseResult from std_http_path, but #5818 moved them to extdeps_uri_path in the authority (main never regenerated, so its stale seed + test still pointed at std_http_path). Repointed the imports to the fixed-point location. regen_stage0 --verify exit 0; cargo build --workspace --all-targets -D warnings 0/0; parse.rs still byte-identical to origin/main (#5864 preserved). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * Merge origin/main (#5874/#5878/#5880) into cutover branch; seed reset to main (re-regen reconciles), Path-B HAND_MAINTAINED re-applied for main.rs/parse.rs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Restore compilable pre-regen interim: all source authoring (reg-2 A1+S5, reg-3, both grounded witnesses, extdeps_uri_path reg) on main seed; regen HELD pending #5878 empty_node_list ruling The faithful regen is blocked: #5878's empty_node_list thread_local singleton is an ungrounded seed-cement (hand-edited into v1_std_core.rs seed, not in any .dag); a regen drops the definition while 2 HAND_MAINTAINED files (parse.rs/dag_collect_support.rs) still call it. Escalated to manager (empty_node_list grounding option + #5878-documented emitter non-determinism vs RegenVerifyGate bit-identity premise). Seed kept = origin/main (compilable) until the ruling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in * WIP: Two-generation regen cutover + dissolve parked regen_verify_gate plan in --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Summary
type Url = Stringhollow alias fromstd/types.dag— a §3 violation: a second name forStringwith no grounding, silently conflating typed URI values with arbitrary stringshtml_url,documentation_urlfrom GitHub REST API) →NonEmptyStr(§3-honest: the API returns strings; see design note below)default_api_base,sts_endpoint) →NonEmptyStr(used in service configendpoint:blocks which take strings)GitRemote.url) →NonEmptyStr(git remote URLs include non-standardgit@host:format outsideUriScheme)RestTransportConfig.base_url) →Uri(always constructed with a known scheme; makes raw-string assignment unwritable by construction)AttachedUrl.url,TrackedIssue.url,PipelineArtifact.url,BlobRef.uri,LaunchConfig.drain_flag_url,source_url) →NonEmptyStruri_grounding_witness_test.dagproving theUrimodel works (green-by-execution)Design notes — construct-vs-parse boundary
RestTransportConfig.base_url: Uriis the construction wall: a REST transport always has a known scheme, so we always construct this value explicitly. Raw strings are unwritable by construction (§5).NonEmptyStrfor wire-response fields (html_url, etc.) is the §3-honest representation of what the GitHub REST API actually returns: a JSON string. Typing these fieldsUriwould requireuri_parse(String) -> Uri?with aDecodeFidelityboundary (§4 — honest about where parsing can fail), plus evaluator ingestion support for string → record coercion. Neither exists today. Modeling them asUrinow would relocate the hollow fromUrl = Stringinto aUribuilt from an unparsed string — the same §5 defect in new costume.NonEmptyStrholds the boundary honestly until that parse infrastructure lands.Named dissolution trigger (
dissolve-on: uri_parse): onceuri_parse(String) -> Uri?lands with a realDecodeFidelityboundary and wire-ingestion support, migratehtml_urland all wire-response URL fields fromNonEmptyStrtoUri. That is the follow-on PR; this PR scopes to the hollow-alias removal and the one construction-site wall.Test plan
uri_grounding_witnesses()— green-by-execution:Uriconstruction,uri_wireround-tripextdeps_github_errors_url_grounding_witnesses()— passes withString?code_change_workflow_witness_test— passes withNonEmptyStrstring_family_cast_holds()— passes (Url cast removed; remaining casts unaffected)Urltype references remain in corpus🤖 Generated with Claude Code