Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions DOCS/Usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Using Hypercode

A practical walkthrough of the toolchain, end to end. Every output below is
real — produced by the CLI from [`Examples/service.hc`](../Examples/service.hc)
and [`Examples/service.hcs`](../Examples/service.hcs).

```
.hc + .hcs + --ctx ──▶ resolve ──▶ validate (contracts) ──▶ emit (IR v2) ──▶ your generator
explain (why is this value X?)
```

## The running example

One structure, two contexts. `service.hc` is the *what*:

```hypercode
Service
Logger.console
Database#main-db
Connect
APIServer
Listen
```

`service.hcs` is the *how* — defaults, a production override block, and
invariants the cascade must respect in **every** context:

```hcs
Logger:
level: "debug"

APIServer > Listen:
host: "127.0.0.1"
port: 5000

@env[production]:
Logger:
level: "info"
'#main-db':
driver: "postgres"
pool_size: 50
APIServer > Listen:
host: "0.0.0.0"
port: 8080

@contract:
APIServer > Listen:
port: int >= 1 <= 65535
host: string
'#main-db':
pool_size[?]: int >= 1 <= 100
```

## 1. One structure, many builds (white-label / environments)

```console
$ hypercode resolve Examples/service.hc --hcs Examples/service.hcs --ctx env=production
Service
Logger (class: console)
- format: json [.console]
- level: info [Logger]
Database (id: main-db)
- driver: postgres [#main-db]
- file: dev.sqlite3 [Database]
- pool_size: 50 [#main-db]
Connect
APIServer
Listen
- host: 0.0.0.0 [APIServer > Listen]
- port: 8080 [APIServer > Listen]
```

Drop `--ctx` and the same structure resolves to the development build
(`sqlite`, `127.0.0.1:5000`, `level: debug`). The `.hc` never changes — that
is the white-label guarantee. Every value carries `[the selector that won]`.

## 2. Guardrails: contracts as a CI gate

Contracts are invariants attached to selectors. Values cascade freely;
contracts only accumulate and narrow (RFC §9.4). Two layers of checking:

**Sheet-level (static):** a more specific contract that *weakens* an inherited
one — wider interval (HC2102), changed type (HC2101), required→optional
(HC2103) — is rejected when the sheet is read.

**Value-level (per context):** the resolved values are checked against every
applicable contract — type, bounds, required presence (HC2104):

```console
$ hypercode validate app.hc --hcs app.hcs --ctx env=production
app.hcs:1:1: error[HC2104]: contract violation for 'port': 99999 exceeds upper bound 65535.0 from contract 'APIServer > Listen'
$ echo $?
1
```

The classic failure — "the production override accidentally weakened a limit" —
becomes a build error instead of an incident. The CI recipe is one line per
context:

```yaml
- name: Validate configuration for every context
run: |
hypercode validate app.hc --hcs app.hcs # development
hypercode validate app.hc --hcs app.hcs --ctx env=production
hypercode validate app.hc --hcs app.hcs --ctx env=staging
```

Diagnostics are also available LSP-shaped: `--diagnostics json`.

## 3. Debugging the cascade: `explain`

"Why is this value X in production?" — the eternal archaeology of layered
configuration, answered in one command:

```console
$ hypercode explain Examples/service.hc --hcs Examples/service.hcs --ctx env=production Logger level
Matched 1 node for selector 'Logger'

Node: Service > Logger.console
level
WINNER Logger { value: info }
file: Examples/service.hcs line: 16 specificity: (0,0,1) order: 4
────────────────────
losing Logger { value: debug }
file: Examples/service.hcs line: 1 specificity: (0,0,1) order: 0
```

Winner *and* every losing rule, each with its file, line, specificity and
source order. Selectors work the same as in sheets: `Logger`, `.console`,
`'#main-db'`, `APIServer > Listen`. Omit the property to trace all of them.

## 4. Machine-readable output: IR v2

`emit` produces the canonical resolved-graph IR — the contract between
Hypercode and any consumer ([schema](../Schema/hypercode-ir-v2.schema.json),
ajv-validated in CI):

```console
$ hypercode emit Examples/service.hc --hcs Examples/service.hcs --ctx env=production --format json
```

```jsonc
{
"version": "hypercode.ir/v2",
"context": { "env": "production" }, // echo of --ctx
"resolver": { "name": "hypercode-swift", "version": "0.5.0-dev" },
"documentHash": "3be098179523f21c…",
"nodes": [ /* … each node: */
{
"type": "Listen",
"hash": "c4ba5d08dcfca81b…", // stable content hash
"properties": {
"port": {
"value": 8080, // typed, not stringly
"winner": { "selector": "APIServer > Listen", "line": 26, "specificity": [0,0,2], "…": "…" },
"losers": [ { "value": 5000, "line": 11, "…": "…" } ],
"contracts": [ { "selector": "APIServer > Listen", "type": "int", "min": 1.0, "max": 65535.0, "required": true } ]
}
}
}
]
}
```

What each piece is for:

- **Typed values** — consumers get `8080`, not `"8080"`.
- **`hash`** covers only the *stable resolved content* (type/class/id, values,
child hashes). A different rule winning with the same value does **not**
change the hash — it is the invalidation signal for incremental
regeneration: re-generate only nodes whose hashes changed.
- **`winner` / `losers`** — full provenance; an auditor or codegen validator
can state *which rule* demanded a behavior.
- **`contracts`** — every contract governing the property, ascending
specificity, so a consumer can re-derive the effective constraint without
re-parsing the sheet.

`--ir-version 1` keeps the legacy strings-only v1 for existing consumers;
v1 values round-trip byte-for-byte (`1.10` stays `1.10`).

## 5. The target pipeline: specification for AI code generation

The intended role ([RFC §9.7](../RFC/Hypercode.md)): `.hc`/`.hcs` is the durable
specification, code is regenerated output.

```
.hc + .hcs ──▶ resolved IR ──▶ LLM generates code per node
│ │
node hashes validated against the same
(what changed?) contracts + provenance
```

- The generator consumes the IR — never the raw sheets — so it sees one
unambiguous, typed, context-resolved graph.
- Node hashes scope regeneration to what actually changed.
- Contracts give the validator formal grounds to reject a generated artifact.
- Humans review the *specification diff*; machines expand it into code
(review compression).

The missing piece for this loop is `hypercode diff <old.ir> <new.ir>` —
HC-113 in the [work plan](../workplan.md).

## Scalar typing cheat-sheet

| Written in `.hcs` | Resolved as |
|---|---|
| `port: 8080` | int `8080` |
| `ratio: 0.5` | float `0.5` |
| `active: true` | bool `true` |
| `driver: sqlite` | string `"sqlite"` (bare strings are fine) |
| `zip: "00123"` | string `"00123"` — **quoting forces string** |
| `version: 1.10` | float `1.1` in v2; v1 IR preserves the lexeme `1.10` |
7 changes: 4 additions & 3 deletions DOCS/Workplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,13 @@ All findings reproduced against `feat/hc-111-contracts` (69a38f0). R1–R8 block

### B — Decided 2026-06-11, pending implementation

- **R9 — contract value validation is not implemented.** Values are never checked
against contracts (`timeout: 999` under `int <= 300` passes; wrong-type values pass).
- **R9 — contract value validation was not implemented.** Values were never checked
against contracts (`timeout: 999` under `int <= 300` passed; wrong-type values passed).
**Decision:** separate **PR-5** — value validation against contracts with a new
**HC2104** diagnostic (type mismatch, bounds violation, missing required property).
#22 stays scoped to grammar + monotonicity; files table fixed (`Resolver` row moved
to PR-5).
to PR-5). **Done:** `ContractValueValidator` on `feat/hc-111-value-validation`;
`validate` gained `--ctx`; violations point at the winning rule.
- ✅ **R10 — v1 emitter is now lossy for numeric-looking strings.** `version: 1.10` →
`"1.1"`, `build: 0123` → `"123"` under `--ir-version 1` (regression vs pre-PR-1 raw
strings). **Decision:** store the source lexeme alongside the typed value; v1 emits
Expand Down
18 changes: 11 additions & 7 deletions EBNF/Hypercode_Resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,17 @@ Bounds at equal specificity simply intersect and are not a conflict.
All three are `error`-severity diagnostics; `hypercode validate` exits
non-zero.

### 7.3 Value validation (planned)

Checking the resolved values themselves against the effective contract
(type conformance, bounds, required presence) is diagnostic **HC2104**,
scheduled as PR-5 in [DOCS/Workplan.md](../DOCS/Workplan.md).
### 7.3 Value validation (HC2104)

Resolved values are checked against every applicable contract
(`ContractValueValidator`): type conformance (an int value satisfies a
`float` contract, ℤ ⊂ ℝ; everything else must match exactly), declared
bounds, and required presence. Because resolution is context-dependent,
this check runs on the resolved graph — the same sheet can be clean under
one `--ctx` and violating under another, so `hypercode validate` accepts
`--ctx key=value`. Violations point at the winning rule (where the value
was written); a missing required property points at the contract that
demands it.

### 7.4 IR

Expand Down Expand Up @@ -179,8 +185,6 @@ hypercode resolve Examples/service.hc --hcs Examples/service.hcs --ctx env=produ
no override-file origin), so the current precedence key is
`(specificity, source-order)`. When syntax is introduced, it becomes the
most-significant component of `precedence`.
- **Contract value validation.** §7.3 — HC2104, planned as PR-5.

*(Typed scalars, previously deferred, landed with IR v2: bare scalars are
type-inferred at parse time, with the source lexeme preserved for v1
round-tripping.)*
11 changes: 11 additions & 0 deletions Examples/service.hcs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,14 @@ APIServer > Listen:
APIServer > Listen:
host: "0.0.0.0"
port: 8080

# Invariants the cascade must respect in every context (HC-111).
# A more specific selector may narrow these, never weaken them.
@contract:
APIServer > Listen:
port: int >= 1 <= 65535
host: string
'#main-db':
pool_size[?]: int >= 1 <= 100
Logger:
level: string
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ build **without touching the structure**.
📖 **API documentation:** <https://0al-spec.github.io/Hypercode/>

```
.hc + .hcs ──[resolve]──▶ resolved graph ──[emit]──▶ canonical IR (hypercode.ir/v1)
.hc + .hcs ──[resolve]──▶ resolved graph ──[validate contracts]──▶ canonical IR (hypercode.ir/v2)
```

## Why
Expand All @@ -18,8 +18,13 @@ build **without touching the structure**.
context-aware `@rules`.
- **Context switching / white-label** — one structure, many contexts. Swap
`--ctx env=production` (or `client=acme`) → different output, same `.hc`.
- **Provenance** — every resolved value records the selector and source line it
came from.
- **Provenance** — every resolved value records the selector, file and source
line it came from; `hypercode explain` shows the winner *and* every losing rule.
- **Contracts that only narrow** — `@contract:` blocks attach invariants to
selectors; values cascade, safety doesn't. A production override that breaks
a bound is a build error (`HC2104`), not an incident.
- **Hashed, typed IR** — per-node SHA-256 over stable resolved content: the
invalidation signal for incremental (re)generation.

## Install

Expand Down Expand Up @@ -50,9 +55,11 @@ swift run hypercode resolve Examples/service.hc --hcs Examples/service.hcs --ctx

```
hypercode parse <file.hc>
hypercode validate <file.hc> [--hcs <file.hcs>]
hypercode validate <file.hc> [--hcs <file.hcs>] [--ctx key=value]... # incl. contract checks
hypercode resolve <file.hc> --hcs <file.hcs> [--ctx key=value]...
hypercode emit <file.hc> [--hcs <file.hcs>] [--ctx key=value]... [--format json|yaml]
hypercode emit <file.hc> [--hcs <file.hcs>] [--ctx key=value]... [--format json|yaml] [--ir-version 1|2]
hypercode explain <file.hc> --hcs <file.hcs> [--ctx key=value]... <selector> [property]
hypercode lsp # LSP over stdio
```

The same structure, two contexts:
Expand All @@ -64,12 +71,13 @@ hypercode resolve Examples/service.hc --hcs Examples/service.hcs --ctx env=produ

## Documentation

- **[Usage guide](DOCS/Usage.md)** — every command with real outputs: contexts, contracts, explain, IR v2
- **API docs (DocC):** <https://0al-spec.github.io/Hypercode/>
- [Conceptual overview](OVERVIEW.md)
- [RFC — the paradigm](RFC/Hypercode.md)
- Formal specs: [`.hc` syntax (BNF)](EBNF/Hypercode_Syntax.md) · [resolution semantics](EBNF/Hypercode_Resolution.md)
- Architecture: [overview](DOCS/Architecture.md) · [backends & adapters](DOCS/Backends.md) · [core vs dialects](DOCS/Dialects.md) · [positioning](DOCS/Positioning.md)
- [Resolved-graph IR schema](Schema/hypercode-ir-v1.schema.json) — the cross-implementation contract
- Resolved-graph IR schemas — the cross-implementation contract: [v2](Schema/hypercode-ir-v2.schema.json) · [v1 (legacy)](Schema/hypercode-ir-v1.schema.json)
- [Lean 4 cascade oracle](SPEC/lean/) — machine-checked agreement with the resolver
- [Work plan](workplan.md) · [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md)

Expand Down
Loading
Loading