Skip to content

Commit 5cdd5bc

Browse files
authored
docs(ttl): add v1 project and language contracts (#184)
## Summary - add docs/project-ttl.md as the v1 project contract for TTL - add docs/project-ttl-language.md as the TTL language/compiler contract - register ttl in root AGENTS.md (ProjectId, ownership, canonical doc map) - update cmds/AGENTS.md scope and TTL doc-sync rules ## Validation - documentation-only change - confirmed required section order in both new docs/project-*.md files
1 parent 585dba3 commit 5cdd5bc

4 files changed

Lines changed: 376 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
- `docs/project-cargo-mono.md`: Cargo subcommand for Rust monorepo management.
3737
- `docs/project-nodeup.md`: Rust-based Node.js version manager.
3838
- `docs/project-derun.md`: Go CLI for terminal-fidelity run execution and MCP output bridge access for AI.
39+
- `docs/project-ttl.md`: TTL language/compiler project contracts for incremental task execution on Go runtime foundations.
40+
- `docs/project-ttl-language.md`: TTL language syntax, type, invalidation, and Go code-generation contracts.
3941
- `docs/project-mpapp.md`: Expo React Native mobile app.
4042
- `docs/project-devkit.md`: Next.js 16 web micro-app platform.
4143
- `docs/project-devkit-commit-tracker.md`: Commit Tracker contracts (Web UI + API server + collector).
@@ -55,6 +57,7 @@ enum ProjectId {
5557
CargoMono = "cargo-mono",
5658
Nodeup = "nodeup",
5759
Derun = "derun",
60+
Ttl = "ttl",
5861
Devmon = "devmon",
5962
Mpapp = "mpapp",
6063
Devkit = "devkit",
@@ -71,6 +74,7 @@ enum ProjectId {
7174
- `nodeup` -> `crates/nodeup`
7275
- `cargo-mono` -> `crates/cargo-mono`
7376
- `derun` -> `cmds/derun`
77+
- `ttl` -> `cmds/ttlc`
7478
- `devmon` -> `cmds/devmon`
7579
- `mpapp` -> `apps/mpapp`
7680
- `devkit` -> `apps/devkit`
@@ -158,6 +162,7 @@ enum SerdeLiteDeriveComponent {
158162
- Reserve a unique `project-id`.
159163
- Create project path skeleton and add `.gitkeep` if implementation is not started.
160164
- Add `docs/project-<project-id>.md` using `docs/project-template.md`.
165+
- Documentation-only phase may mark canonical paths as `planned` before creating path skeletons; create the skeleton in the same change where runtime implementation begins.
161166
- Update root and domain `AGENTS.md` files when project ownership or contracts change.
162167
- Ensure path and naming contracts are consistent across docs and AGENTS rules.
163168

@@ -225,6 +230,7 @@ Release automation baseline:
225230

226231
- Every structural repository change must update relevant `docs/project-*.md` files in the same change set.
227232
- New project creation is blocked until its project document exists.
233+
- Documentation-only project onboarding may use `planned` paths, but runtime implementation must not begin before canonical paths are created and documented.
228234
- Repository-wide and domain rules must be maintained in the appropriate `AGENTS.md`.
229235
- When user-facing documentation content changes, update relevant pages in `apps/public-docs` in the same change set as needed.
230236
- Run `git commit` only after `git add`; once files are staged, create the commit without unnecessary delay.

cmds/AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- `cmds/devmon`: Go daemon CLI for recurring folder command automation.
1212
- `cmds/thenv`: Secure `.env` sharing CLI.
1313
- `cmds/commit-tracker`: Commit Tracker collector component.
14+
- `cmds/ttlc`: TTL compiler CLI for `.ttl` parsing/type-checking, Go code generation, and cache-aware task execution contracts.
1415

1516
### Command Component Contract
1617

@@ -36,3 +37,5 @@
3637
- Update `docs/project-derun.md` whenever command shape or config contracts change.
3738
- Update `docs/project-thenv.md` whenever thenv CLI operations or trust boundaries change.
3839
- Update `docs/project-devkit-commit-tracker.md` whenever commit-tracker collector contracts change.
40+
- Update `docs/project-ttl.md` whenever TTL compiler command shape, cache backend, or runtime boundaries change.
41+
- Update `docs/project-ttl-language.md` whenever TTL syntax/type/invalidation/code-generation contracts change.

docs/project-ttl-language.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Project: ttl-language
2+
3+
## Goal
4+
This document defines the stable language and compiler contracts for `.ttl` sources.
5+
The design target is Go-like syntax plus ergonomic TurboTasks-style core types (`Vc`-centric) for incremental, cache-first, parallel task execution.
6+
7+
## Path
8+
- Language spec document: `docs/project-ttl-language.md`
9+
- Compiler implementation target: `cmds/ttlc` (planned in v1 documentation phase)
10+
11+
## Runtime and Language
12+
- Language surface: TTL (`.ttl`)
13+
- v1 compiler backend: generated Go source
14+
- v1 execution/caching backend: runtime APIs + SQLite cache
15+
16+
## Users
17+
- Engineers authoring build/task pipelines in `.ttl`
18+
- Runtime/compiler maintainers implementing deterministic incremental execution
19+
20+
## In Scope
21+
- Lexical and syntactic contracts for `.ttl`
22+
- Typed task declaration and core runtime types
23+
- Incremental dependency tracking (`read(vc)` contract)
24+
- Hash-based invalidation model
25+
- Go code generation contract
26+
- Runtime/caching schema-level contracts
27+
28+
## Out of Scope
29+
- Full language grammar for every future feature
30+
- Alternative backend targets in v1
31+
- Language server protocol details
32+
- Remote/distributed scheduler protocol
33+
34+
## Architecture
35+
Language-to-runtime architecture:
36+
- Source Layer: `.ttl` modules with Go-like declarations.
37+
- Semantic Layer: type checking and task graph extraction.
38+
- Lowering Layer: typed IR lowered to runtime API calls.
39+
- Runtime Layer: dependency tracking, scheduler, cache lookup/writeback.
40+
- Persistence Layer: SQLite metadata and optional blob storage.
41+
42+
Compilation flow:
43+
1. Parse module declarations (`package`, `import`, `type`, `task func`, `func`).
44+
2. Resolve symbols and validate core type usage.
45+
3. Build dependency edges from `read(vc)` and task calls.
46+
4. Derive task/cache fingerprints.
47+
5. Emit Go source that invokes runtime task APIs.
48+
49+
## Interfaces
50+
Canonical type and command identifiers:
51+
52+
```ts
53+
enum TtlCompileTarget {
54+
GoSource = "go-source",
55+
}
56+
57+
enum TtlCacheBackend {
58+
SQLite = "sqlite",
59+
}
60+
61+
enum TtlCommand {
62+
Build = "build",
63+
Check = "check",
64+
Explain = "explain",
65+
}
66+
67+
enum TtlCoreType {
68+
Vc = "vc",
69+
ResolvedVc = "resolved-vc",
70+
OperationVc = "operation-vc",
71+
TransientValue = "transient-value",
72+
State = "state",
73+
}
74+
```
75+
76+
Core language contracts:
77+
- File extension is always `.ttl`.
78+
- Task declaration style is fixed to `task func`.
79+
- Base syntax intentionally tracks Go style (blocks, signatures, package/import model).
80+
- Every `task func` must return `Vc[T]`.
81+
- `read(vc)` establishes dependency tracking from current task to the referenced task/cell.
82+
83+
v1 syntax examples:
84+
85+
```ttl
86+
package build
87+
88+
type Artifact struct {
89+
Path string
90+
Digest string
91+
}
92+
93+
task func Build(target string) Vc[Artifact] {
94+
src := read(ResolveSource(target))
95+
digest := hash(src.Path, src.Digest)
96+
return vc(Artifact{Path: src.Path, Digest: digest})
97+
}
98+
99+
func Main(target string) {
100+
val := read(Build(target))
101+
print(val.Path)
102+
}
103+
```
104+
105+
Generated Go shape contract (illustrative):
106+
107+
```go
108+
func Build(target string) runtime.Vc[Artifact] {
109+
return runtime.Task("Build", target, func(ctx runtime.TaskContext) (Artifact, error) {
110+
src, err := runtime.Read(ctx, ResolveSource(target))
111+
if err != nil {
112+
return Artifact{}, err
113+
}
114+
digest := runtime.Hash(src.Path, src.Digest)
115+
return Artifact{Path: src.Path, Digest: digest}, nil
116+
})
117+
}
118+
```
119+
120+
Invalidation contract:
121+
- Fingerprint inputs are mandatory and ordered:
122+
1. Input content hash
123+
2. Parameter hash
124+
3. Environment snapshot hash
125+
- Reuse occurs only when full fingerprint matches.
126+
- Any component mismatch triggers recomputation.
127+
128+
Parallel execution contract:
129+
- Scheduler may execute tasks concurrently when no unresolved dependency edge exists.
130+
- Execution order is deterministic with respect to dependency constraints, not submission order.
131+
132+
## Storage
133+
Cache backend is fixed to SQLite in v1.
134+
Minimum conceptual schema (field names are stable contract names):
135+
- `task_key`
136+
- `input_fingerprint`
137+
- `output_blob_ref`
138+
- `deps`
139+
- `metadata`
140+
141+
Recommended conceptual tables:
142+
- `task_cache(task_key PRIMARY KEY, input_fingerprint, output_blob_ref, metadata_json, updated_at)`
143+
- `task_deps(task_key, dep_task_key)`
144+
- `cache_blobs(blob_ref PRIMARY KEY, codec, bytes, size_bytes)`
145+
146+
## Security
147+
- Input file resolution must stay within configured workspace roots.
148+
- Cache metadata and blobs must not expose secret env values.
149+
- Corrupted cache records must fail closed (no unsafe partial decode).
150+
151+
## Logging
152+
Compiler and runtime use `log/slog` with structured event records.
153+
Required fields:
154+
- `compile_stage`
155+
- `task_id`
156+
- `cache_key`
157+
- `cache_hit`
158+
- `invalidation_reason`
159+
- `worker_id`
160+
- `duration_ms`
161+
- `error_kind`
162+
163+
Runtime task event baseline:
164+
- `task_scheduled`
165+
- `task_started`
166+
- `task_cache_hit`
167+
- `task_cache_miss`
168+
- `task_completed`
169+
- `task_failed`
170+
171+
## Build and Test
172+
v1 implementation commands (applies when compiler/runtime code exists):
173+
- `go build ./cmds/ttlc/...`
174+
- `go test ./cmds/ttlc/...`
175+
176+
Documentation acceptance checks:
177+
1. `task func` examples always return `Vc[T]`.
178+
2. `read(vc)` examples always imply dependency tracking.
179+
3. Hash invalidation explicitly includes input/parameter/environment components.
180+
4. Cache backend remains SQLite in all ttl contracts.
181+
5. Failure modes and observability fields remain explicit and stable.
182+
183+
Failure mode contracts:
184+
- Circular dependency: fail with cycle diagnostics and no partial success state.
185+
- Cache corruption: emit `error_kind=cache_corruption`, invalidate row, recompute.
186+
- Type mismatch: fail during type-check or decode boundary with typed diagnostics.
187+
- Non-deterministic task warning: emit warning diagnostics when unstable outputs are detected.
188+
189+
## Roadmap
190+
- Phase 1: Lock syntax + type contracts and ship Go emitter skeleton.
191+
- Phase 2: Complete scheduler/dependency tracking and SQLite persistence.
192+
- Phase 3: Improve diagnostics, performance, and cache lifecycle tooling.
193+
194+
## Open Questions
195+
- Should future syntax include explicit task priority annotations?
196+
- Should environment snapshots be user-configurable by allowlist rules?
197+
- Should blob storage remain SQLite-only or move large payloads to file-backed blobs by default?
198+
199+
## References
200+
- `docs/project-ttl.md`
201+
- `docs/project-template.md`
202+
- [turbo-tasks/lib.rs](https://github.com/vercel/next.js/blob/canary/turbopack/crates/turbo-tasks/src/lib.rs)
203+
- [turbo-tasks/vc/mod.rs](https://github.com/vercel/next.js/blob/canary/turbopack/crates/turbo-tasks/src/vc/mod.rs)
204+
- [turbo-tasks/value.rs](https://github.com/vercel/next.js/blob/canary/turbopack/crates/turbo-tasks/src/value.rs)

0 commit comments

Comments
 (0)