diff --git a/DOCS/RuntimeBoundary.md b/DOCS/RuntimeBoundary.md new file mode 100644 index 0000000..a0aa1ae --- /dev/null +++ b/DOCS/RuntimeBoundary.md @@ -0,0 +1,85 @@ +# Runtime Resolver Boundary (HC-114) + +**Status:** Decided · **Date:** 2026-06-12 · Decision record for workplan HC-114 +(closes RFC §10 "Performance" / the JIT-vs-AOT question). + +## The question + +Where does context binding happen? + +1. **Build/generation time** (the current mode): `--ctx` is supplied when + resolving; the output is a static resolved graph per context, consumed by + generators, validators and `diff`. +2. **Embedded runtime resolver**: an application links the resolver and + supplies per-request context (tenant, user, cohort), getting resolved + values live from a single deployment. + +RFC §9.8 had noted mode 2 as "optional, currently out of scope". This record +makes the boundary a decision, not a deferral. + +## Decision + +**Build/generation-time resolution is the only supported mode of the +reference implementation.** The embedded runtime resolver is **out of +scope** — excluded from the core's contract, with explicit revisit conditions +below. Consequently **HC-115** (an OpenFeature bridge for the runtime mode) +is parked. + +## Rationale + +1. **The product is the artifact, not the answer.** Everything that makes + Hypercode worth using — review compression, per-node SHA-256 hashes, + `hypercode diff` as an invalidation feed, HC2104 gating, generated-artifact + conformance — assumes a *finished, reviewable* resolved graph. A + per-request resolution has no stable artifact: nothing to hash, nothing to + diff, nothing to review or attest. +2. **Provenance semantics.** At build time, provenance points at a line a + human can review *before* anything ships. At runtime, "which rule won" + becomes telemetry — an observability problem with its own capture, + sampling and retention questions, foreign to the core. +3. **The validation story depends on enumerable contexts.** + `validate --ctx …` runs once per context in CI, which works because + build-time contexts are finitely enumerable. Per-request context spaces + (user IDs, cohorts) are unbounded; admitting them would silently void the + "every shipped context was checked" guarantee the contract layer provides. +4. **The runtime niche is occupied — deliberately.** OpenFeature and + LaunchDarkly decide dynamic values per request well. Hypercode's role + ([Positioning](Positioning.md)) is to provide the stable anchors + (`type`/`.class`/`#id`) such systems target. A bridge would blur exactly + the layer boundary the positioning depends on. +5. **The library stays embeddable as a fact, not as a contract.** `Resolver` + is a pure function of `(sheet, context)`; a consumer *can* call it + in-process today. The decision is that core makes **no runtime API + commitments**: no caching, no sheet hot-reload, no per-request provenance + sink, no latency guarantees. Embedding it means accepting build-time + semantics evaluated late, with none of the runtime conveniences. + +## Binding consequences for design + +- Resolution remains a **pure function**. No public API may require an + execution environment (clock, network, environment variables) at resolve + time. +- Diagnostics, IR, hashes and `diff` stay defined over the resolved artifact. +- Interpolation placeholders that appear in sheets (e.g. the `"${DB_HOST}"` + in RFC §4.2.2) pass through resolution as opaque strings; binding them is + the **consumer's** generation/deploy concern, not resolver semantics. +- HC-115 (OpenFeature bridge) is parked: it only makes sense in the runtime + mode. Runtime flags compose with Hypercode by targeting resolved anchors, + not by flowing through the resolver. + +## Revisit when + +All three together, not any one alone: + +1. A consumer demonstrates a deployment whose context space genuinely cannot + be pre-resolved (true per-request combinatorics, not "many tenants" — + N tenants × M environments enumerate fine); +2. a provenance/attestation design exists for runtime answers (what replaces + the reviewable artifact); +3. the runtime API is drafted as a **separate package** so the core's purity + and guarantees are untouched. + +## Pointers + +[RFC §9.3, §9.8](../RFC/Hypercode.md) · [Positioning — layer answers](Positioning.md) +· [OVERVIEW §6](../OVERVIEW.md) diff --git a/OVERVIEW.md b/OVERVIEW.md index 28ca70a..74d39d2 100644 --- a/OVERVIEW.md +++ b/OVERVIEW.md @@ -121,8 +121,9 @@ runnable today: [`Examples/codegen-demo/`](Examples/codegen-demo/). Binding time is explicit: context resolves at build/generation time. Runtime feature flags (OpenFeature, LaunchDarkly) are a different, composable layer; -an embedded runtime resolver is an optional mode, currently out of scope -([RFC §9.8](RFC/Hypercode.md)). +an embedded runtime resolver is decided out of scope — the resolver stays an +embeddable pure function, but core makes no runtime API commitments +([decision record](DOCS/RuntimeBoundary.md), [RFC §9.8](RFC/Hypercode.md)). ## 7. What Hypercode Is Not diff --git a/RFC/Hypercode.md b/RFC/Hypercode.md index ca5b5cf..6e2b850 100644 --- a/RFC/Hypercode.md +++ b/RFC/Hypercode.md @@ -298,7 +298,7 @@ The strongest objection to Hypercode's design comes from the configuration-langu For example, given a base contract `Database: pool_size: int >= 1`, a more specific `Database#main: pool_size: int >= 10` is valid (narrowing), while `Database#main: pool_size: int >= 0` is rejected (weakening). Behavior cascades; safety does not. This asymmetry is the design's direct answer to the GCL lesson. - Two refinements make the rule precise (normative semantics in the [resolution specification](../EBNF/Hypercode_Resolution.md)). First, contracts **accumulate by intersection**: every contract matching a node governs it simultaneously, and an omitted bound is not a statement — it inherits through the intersection. Second, as in the CSS cascade, specificity relates two contracts only when at least one node in the document is matched by both selectors; contracts on disjoint parts of the tree are independent. Monotonicity violations are resolution errors (HC2101 type change, HC2102 interval widening, HC2103 required→optional); validating resolved *values* against the effective contract is the next layer (HC2104, in progress). + Two refinements make the rule precise (normative semantics in the [resolution specification](../EBNF/Hypercode_Resolution.md)). First, contracts **accumulate by intersection**: every contract matching a node governs it simultaneously, and an omitted bound is not a statement — it inherits through the intersection. Second, as in the CSS cascade, specificity relates two contracts only when at least one node in the document is matched by both selectors; contracts on disjoint parts of the tree are independent. Monotonicity violations are resolution errors (HC2101 type change, HC2102 interval widening, HC2103 required→optional); validating resolved *values* against the effective contract is the value layer (HC2104, `validate --ctx`, shipped in 0.5.0). 4. **Known failure modes are acknowledged.** Specificity wars and selector escalation are real CSS pathologies at scale. Countermeasures — origin/layer control analogous to CSS `@layer`, dangling-selector validation (already in `hypercode validate`), and explain tooling — are sequenced in the [work plan](../workplan.md) ahead of language surface that would amplify them. ### 9.5. Why a Stable Topology @@ -319,15 +319,31 @@ Spec-driven development is converging on the view that the specification is the ### 9.8. Acknowledged Limits -* **Context binds at resolve time.** `--ctx` is supplied when resolving: Hypercode's default mode decides context at build/generation time. Runtime feature-flag systems (OpenFeature, LaunchDarkly) decide flag values per request at runtime — a different layer that composes with Hypercode rather than competing with it. Serving dynamic context from a single deployment (e.g., many tenants per process) would require embedding the resolver as a runtime library; that optional mode raises its own caching, latency, and provenance questions and is currently out of scope. +* **Context binds at resolve time.** `--ctx` is supplied when resolving: Hypercode's default mode decides context at build/generation time. Runtime feature-flag systems (OpenFeature, LaunchDarkly) decide flag values per request at runtime — a different layer that composes with Hypercode rather than competing with it. Serving dynamic context from a single deployment (e.g., many tenants per process) would require embedding the resolver as a runtime library; that mode raises its own caching, latency, and provenance questions and is **decided out of scope** for the reference implementation (HC-114, decision record with revisit conditions: [`DOCS/RuntimeBoundary.md`](../DOCS/RuntimeBoundary.md)). The resolver remains an embeddable pure function of `(sheet, context)`, but core makes no runtime API commitments — no caching, no sheet hot-reload, no per-request provenance sink. * **No integrity chain yet.** As noted in §8, nothing verifies the chain end-to-end: signed `.hc`/`.hcs` → resolved-IR hash → generator identity and version → generated-artifact hashes → validator report. SLSA provides the reference vocabulary for such attestations. For the review-compression story to carry governance weight they are eventually required; they are deliberately deferred as future work. -* **Type-system maturity.** IR v2 carries typed values (string/int/double/bool, inferred at parse time with the source lexeme preserved), and the contract layer (§9.4) ships declarations and monotonicity validation. Enforcement of resolved values against the effective contract (HC2104) is in progress; until it lands, Hypercode still does not compete with typed configuration languages on safety. IR v1 remains strings-only and is kept for backward compatibility. +* **Type-system maturity.** IR v2 carries typed values (string/int/double/bool, inferred at parse time with the source lexeme preserved), and the contract layer (§9.4) ships declarations and monotonicity validation. Resolved values are enforced against the effective contract per context (HC2104, `validate --ctx`). What is still missing versus typed configuration languages: richer value types (lists, maps, durations), cross-property constraints, and user-defined predicates. IR v1 remains strings-only and is kept for backward compatibility. ## 10. Open Questions -* **Debugging and Tooling:** How can developers effectively trace why a specific configuration was applied? This would require specialized debugging tools that can visualize the cascade and resolution of HCS rules. -* **Performance:** The overhead of parsing and resolving the HCS at startup needs to be analyzed. A JIT (Just-In-Time) resolution or an AOT (Ahead-Of-Time) compilation step might be necessary for performance-critical applications. -* **Complexity Management:** While HCS simplifies the core logic, very large and complex HCS files could become difficult to manage themselves. Best practices and modularization strategies would be required. This could include extending the at-rule system with directives like `@import`, allowing for better organization of large configurations. +The original open questions of draft 0.1 have since been answered: + +* **Debugging and Tooling** — answered by `hypercode explain` (HC-110): the + full cascade trace, winner and losing rules with file, line, specificity + and source order (§9.4). +* **Performance / binding time** — closed by decision HC-114: resolution is + ahead-of-time (build/generation time) by design; an embedded runtime + resolver is out of scope + ([`DOCS/RuntimeBoundary.md`](../DOCS/RuntimeBoundary.md), §9.8). +* **Complexity Management** — answered by `@import` (HC-116, §4.2.4): sheets + compose with deterministic order, import-once semantics and cross-file + provenance. + +Genuinely open: + +* **Integrity chain** (§8, §9.8): signed sources → resolved-IR hash → + generator identity → artifact hashes → validator report (SLSA vocabulary). +* **Type-system depth** (§9.8): richer value types, cross-property + constraints, user-defined predicates. ## 11. References @@ -358,6 +374,15 @@ Prior art surveyed in §9: the directive position, importer wins specificity ties, import-once, cycle detection, cross-file provenance. Normative semantics in `EBNF/Hypercode_Resolution.md` §5.1. +* Runtime resolver boundary decided (HC-114, §9.8): build/generation-time + resolution is the only supported mode; the embedded runtime resolver is out + of scope with explicit revisit conditions (`DOCS/RuntimeBoundary.md`); + HC-115 (OpenFeature bridge) parked accordingly. +* §10 Open Questions brought up to date: debugging (HC-110), binding time + (HC-114) and complexity management (HC-116) recorded as answered; the + integrity chain and type-system depth remain open. +* §9.4 and §9.8 no longer claim HC2104 is in progress — value-level + enforcement shipped in 0.5.0. **Version 0.2** (2026-06-11): diff --git a/workplan.md b/workplan.md index e1ba86b..b999c1a 100644 --- a/workplan.md +++ b/workplan.md @@ -97,8 +97,8 @@ P0 — what makes the novelty claim defensible: P1 — built on v2: - [x] HC-113 `hypercode diff ` — affected nodes/properties with reasons (old/new winner rule), node-hash short-circuit (unchanged subtrees skipped), selector-identity node matching, added/removed/reordered detection, `--format json` = `hypercode.diff/v1` feed, exit 1 on change — `Sources/Hypercode/Diff/` (Foundation-free JSON parser with exact number lexemes) -- ⬜ HC-114 Runtime resolver boundary — document default build/generation-time mode vs. optional embedded runtime resolver (per-request context: caching, latency, provenance); decide library API or explicit out-of-scope — RFC §9.8 -- 🅿️ HC-115 OpenFeature bridge for the runtime mode *(only if HC-114 decides "in scope")* +- [x] HC-114 Runtime resolver boundary — **decided: build/generation-time only**, embedded runtime resolver out of scope with revisit conditions; resolver stays an embeddable pure function with no runtime API commitments — `DOCS/RuntimeBoundary.md`, RFC §9.8/§10 +- 🅿️ HC-115 OpenFeature bridge for the runtime mode — parked by the HC-114 decision (runtime mode out of scope); runtime flags compose by targeting resolved anchors instead - [x] HC-116 `@import` for `.hcs` — sheet modularity: depth-first expansion at the directive position (importer wins ties), import-once for diamonds, cycle detection, cross-file provenance; contracts compose across imports — normative semantics `EBNF/Hypercode_Resolution.md` §5.1 ## M9 — Validation & adoption (DOCS/Positioning.md)