mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
569 lines
18 KiB
Text
569 lines
18 KiB
Text
digraph dttf {
|
|
graph [
|
|
goal="Build DTTF: a tool that converts bitmap glyph images to valid TrueType fonts",
|
|
rankdir=LR,
|
|
default_max_retries=3,
|
|
retry_target="impl_setup",
|
|
fallback_retry_target="impl_loader",
|
|
model_stylesheet="
|
|
* { model: gemini-3-flash-preview; provider: google; reasoning_effort: medium; }
|
|
.hard { model: gemini-3-flash-preview; provider: google; reasoning_effort: high; }
|
|
.verify { model: gemini-3-flash-preview; provider: google; reasoning_effort: medium; }
|
|
.review { model: gemini-3-flash-preview; provider: google; reasoning_effort: high; }
|
|
"
|
|
]
|
|
|
|
start [shape=Mdiamond, label="Start"]
|
|
exit [shape=Msquare, label="Exit"]
|
|
|
|
// Project setup
|
|
impl_setup [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md sections 4 (Architecture) and 7 (Data Structures).
|
|
|
|
Create Go project structure:
|
|
- go.mod with module github.com/kilroy/dttf
|
|
- pkg/dttf/ directory for core library
|
|
- cmd/dttf/ directory for CLI
|
|
- pkg/dttf/types.go with core data structures from section 7.1: GlyphBitmap, Point, Contour, TracedGlyph, FontMetadata
|
|
|
|
Run: go build ./...
|
|
|
|
Write status.json: outcome=succeeded if builds, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_setup [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify project setup was completed correctly.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. Check that pkg/dttf/types.go exists and contains all required types from specs/dttf-v1.md section 7.1
|
|
|
|
Write results to .ai/verify_setup.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_setup [shape=diamond, label="Setup OK?"]
|
|
|
|
// PNG loader implementation
|
|
impl_loader [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md sections 1 (Input) and 4.3 (Pipeline).
|
|
|
|
Implement PNG loading and parsing:
|
|
- Create pkg/dttf/loader.go
|
|
- Implement LoadGlyphs(inputDir string) ([]GlyphBitmap, *FontMetadata, error)
|
|
- Parse filename pattern: [FontName-GlyphLabel-]U+XXXX.png (section 1.2)
|
|
- Load PNGs, convert to grayscale (section 1.4)
|
|
- Load optional font.json metadata (section 1.5)
|
|
- Apply threshold conversion to 1-bit (section 1.4)
|
|
|
|
Create pkg/dttf/loader_test.go with tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_loader [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify PNG loader implementation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Loader
|
|
|
|
Write results to .ai/verify_loader.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_loader [shape=diamond, label="Loader OK?"]
|
|
|
|
// Tracer implementation (complex, uses Opus)
|
|
impl_tracer [
|
|
shape=box,
|
|
class="hard",
|
|
max_retries=2,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 3 (Tracer) completely.
|
|
|
|
Implement custom bitmap-to-vector tracer:
|
|
- Create pkg/dttf/tracer.go
|
|
- Implement TraceGlyph(bitmap GlyphBitmap, opts TraceOptions) ([]Contour, error)
|
|
- Phase 1: Path decomposition (boundary following, section 3.2)
|
|
- Phase 2: Optimal polygon approximation (section 3.2)
|
|
- Phase 3: Quadratic Bezier fitting (section 3.2)
|
|
- Phase 4: Font-aware optimization (extrema, winding, intersections, section 3.2)
|
|
- Coordinate mapping per section 3.3
|
|
- Configuration parameters from section 3.4
|
|
|
|
Create pkg/dttf/tracer_test.go with unit tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run Tracer
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_tracer [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify tracer implementation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Tracer
|
|
4. Check that tracer outputs quadratic Beziers (not cubic)
|
|
5. Verify winding direction enforcement (section 3.2 Phase 4)
|
|
|
|
Write results to .ai/verify_tracer.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_tracer [shape=diamond, label="Tracer OK?"]
|
|
|
|
// Metrics computation
|
|
impl_metrics [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 2.6 (Glyph Metrics).
|
|
|
|
Implement glyph metrics computation:
|
|
- Create pkg/dttf/metrics.go
|
|
- Compute bounding boxes from traced contours
|
|
- Compute advanceWidth, leftSideBearing per section 2.6
|
|
- Implement sidebearing strategy (proportional to UPEm)
|
|
|
|
Create pkg/dttf/metrics_test.go with tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run Metrics
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_metrics [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify metrics computation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Metrics
|
|
|
|
Write results to .ai/verify_metrics.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_metrics [shape=diamond, label="Metrics OK?"]
|
|
|
|
// TrueType table assembly (complex, uses Opus)
|
|
impl_tables [
|
|
shape=box,
|
|
class="hard",
|
|
max_retries=2,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md sections 2.2 (Required Tables), 2.5 (Vertical Metrics), and 8 (File Assembly).
|
|
|
|
Implement TrueType table assembly:
|
|
- Create pkg/dttf/tables.go
|
|
- Implement AssembleFont(glyphs []TracedGlyph, meta *FontMetadata) (*Font, error)
|
|
- Build all 10 required tables: head, maxp, hhea, hmtx, OS/2, name, post, cmap, loca, glyf (section 2.2)
|
|
- Add gasp table (section 2.3)
|
|
- Implement vertical metrics per section 2.5
|
|
- Implement glyf encoding per section 8.4
|
|
- Implement cmap format 4 per section 8.5
|
|
- Compute checksums per section 8.3
|
|
|
|
Create pkg/dttf/tables_test.go with tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run Tables
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_tables [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify TrueType table assembly.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Tables
|
|
4. Verify all 10 required tables are present
|
|
5. Verify checksums are computed correctly
|
|
|
|
Write results to .ai/verify_tables.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_tables [shape=diamond, label="Tables OK?"]
|
|
|
|
// Font writer
|
|
impl_writer [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 8 (File Assembly).
|
|
|
|
Implement font file writer:
|
|
- Create pkg/dttf/writer.go
|
|
- Implement WriteFont(font *Font, outputPath string) error
|
|
- Write offset table, table directory, table data (section 8.1)
|
|
- Order tables alphabetically by tag (section 8.2)
|
|
- Pad tables to 4-byte boundaries (section 8.1)
|
|
- Set checksumAdjustment in head table (section 8.3)
|
|
|
|
Implement main Build function:
|
|
- Create pkg/dttf/build.go
|
|
- Implement Build(inputDir string, outputPath string, opts Options) error
|
|
- Orchestrate: LoadGlyphs -> TraceGlyph (parallel) -> compute metrics -> AssembleFont -> WriteFont
|
|
|
|
Create pkg/dttf/build_test.go with integration tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_writer [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify font writer and Build function.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Writer
|
|
4. go test ./pkg/dttf/... -v -run Build
|
|
|
|
Write results to .ai/verify_writer.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_writer [shape=diamond, label="Writer OK?"]
|
|
|
|
// Validator
|
|
impl_validator [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 5.1 (Font Validity) and section 9 (Error Handling).
|
|
|
|
Implement font validation:
|
|
- Create pkg/dttf/validator.go
|
|
- Implement Validate(fontPath string) (ValidationResult, error)
|
|
- Check: loadable by golang.org/x/image/font/sfnt parser
|
|
- Check: contours closed
|
|
- Check: correct winding direction (signed area test)
|
|
- Check: no self-intersections (segment-segment test)
|
|
- Check: points at extrema (derivative roots)
|
|
|
|
Create pkg/dttf/validator_test.go with tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run Validator
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_validator [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify validator implementation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Validator
|
|
|
|
Write results to .ai/verify_validator.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_validator [shape=diamond, label="Validator OK?"]
|
|
|
|
// Rasterizer
|
|
impl_rasterizer [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 11 (Rasterizer).
|
|
|
|
Implement font-to-bitmap rasterizer:
|
|
- Create pkg/dttf/rasterizer.go
|
|
- Implement Rasterize(fontPath string, outputDir string, opts RasterizeOptions) error
|
|
- Use golang.org/x/image/font/opentype for rendering
|
|
- Character set selection: ASCII, All, Chars, Ranges (section 11.3)
|
|
- Render configuration from section 11.4
|
|
- Extract and write font.json with real metrics (section 11.5)
|
|
- PNG naming per section 1.2
|
|
|
|
Create pkg/dttf/rasterizer_test.go with tests.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run Rasterizer
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_rasterizer [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify rasterizer implementation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run Rasterizer
|
|
|
|
Write results to .ai/verify_rasterizer.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_rasterizer [shape=diamond, label="Rasterizer OK?"]
|
|
|
|
// CLI implementation
|
|
impl_cli [
|
|
shape=box,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md sections 4.2 (API Surface) and 12 (CLI Reference).
|
|
|
|
Implement CLI commands:
|
|
- Create cmd/dttf/main.go
|
|
- Use cobra or similar for CLI structure
|
|
- Implement: dttf build (section 12)
|
|
- Implement: dttf rasterize (section 12)
|
|
- Implement: dttf validate (section 12)
|
|
- Implement: dttf test (section 12)
|
|
- All flags and options from section 12
|
|
|
|
Acceptance:
|
|
- go build ./cmd/dttf
|
|
- ./cmd/dttf/dttf --help
|
|
- Test each command with --help
|
|
|
|
Write status.json: outcome=succeeded if all commands work, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_cli [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify CLI implementation.
|
|
|
|
Run:
|
|
1. go build ./cmd/dttf
|
|
2. go vet ./cmd/dttf/...
|
|
3. ./cmd/dttf/dttf --help
|
|
4. ./cmd/dttf/dttf build --help
|
|
5. ./cmd/dttf/dttf rasterize --help
|
|
6. ./cmd/dttf/dttf validate --help
|
|
7. ./cmd/dttf/dttf test --help
|
|
|
|
Write results to .ai/verify_cli.md.
|
|
Write status.json: outcome=succeeded if ALL commands exist and show help, outcome=failed with details."
|
|
]
|
|
|
|
check_cli [shape=diamond, label="CLI OK?"]
|
|
|
|
// Test harness (complex, uses Opus)
|
|
impl_test_harness [
|
|
shape=box,
|
|
class="hard",
|
|
max_retries=2,
|
|
goal_gate=true,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md section 6 (Test Harness) and section 5 (Quality Function).
|
|
|
|
Implement round-trip test harness:
|
|
- Create pkg/dttf/testharness.go
|
|
- Implement round-trip test per section 6.1: render -> trace -> compare
|
|
- Reference fonts from section 6.2 (Roboto, Open Sans, Noto Serif, Source Code Pro, Playfair Display, Roboto Slab)
|
|
- SSIM computation per section 5.2
|
|
- Multi-scale testing per section 5.3
|
|
- Quality metrics from sections 5.4, 5.5, 5.6
|
|
- Composite score per section 5.7
|
|
- Auto-download reference fonts from Google Fonts API
|
|
|
|
Create pkg/dttf/testharness_test.go with tests.
|
|
Integrate with dttf test CLI command.
|
|
|
|
Acceptance:
|
|
- go build ./...
|
|
- go test ./pkg/dttf/... -v -run TestHarness
|
|
- dttf test --help shows correct options
|
|
|
|
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
|
]
|
|
|
|
verify_test_harness [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify test harness implementation.
|
|
|
|
Run:
|
|
1. go build ./...
|
|
2. go vet ./...
|
|
3. go test ./pkg/dttf/... -v -run TestHarness
|
|
4. Verify SSIM computation is implemented
|
|
5. Verify reference font download works
|
|
|
|
Write results to .ai/verify_test_harness.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_test_harness [shape=diamond, label="Test Harness OK?"]
|
|
|
|
// Integration test
|
|
impl_integration [
|
|
shape=box,
|
|
goal_gate=true,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md completely.
|
|
|
|
Run full integration test:
|
|
1. Use dttf rasterize to create test input from a simple reference font
|
|
2. Run dttf build on the rasterized glyphs
|
|
3. Run dttf validate on the output font
|
|
4. Run dttf test to compare output vs reference
|
|
5. Verify SSIM scores meet thresholds from section 5.2
|
|
|
|
Document results in .ai/integration_test.md.
|
|
|
|
Acceptance:
|
|
- All commands succeed
|
|
- Output font is valid
|
|
- SSIM > 0.90 (acceptable threshold from section 5.2)
|
|
|
|
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason and specific metrics otherwise."
|
|
]
|
|
|
|
verify_integration [
|
|
shape=box,
|
|
class="verify",
|
|
prompt="Verify integration test results.
|
|
|
|
Run:
|
|
1. Check .ai/integration_test.md exists and shows passing results
|
|
2. Verify output font file exists and is valid
|
|
3. Verify SSIM scores are documented and meet threshold
|
|
4. go test ./... (full test suite)
|
|
|
|
Write results to .ai/verify_integration.md.
|
|
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
|
]
|
|
|
|
check_integration [shape=diamond, label="Integration OK?"]
|
|
|
|
// Final review
|
|
review [
|
|
shape=box,
|
|
class="review",
|
|
goal_gate=true,
|
|
prompt="Goal: $goal
|
|
|
|
Read specs/dttf-v1.md in full.
|
|
|
|
Review complete DTTF implementation against spec:
|
|
|
|
1. Input handling (section 1): PNG loading, filename parsing, metadata, thresholding
|
|
2. Output format (section 2): All required tables, vertical metrics, glyph metrics
|
|
3. Tracer (section 3): Custom quadratic Bezier tracer with all 4 phases
|
|
4. Architecture (section 4): Go library + CLI, correct pipeline
|
|
5. Quality function (section 5): All 6 layers implemented
|
|
6. Test harness (section 6): Round-trip testing with reference fonts
|
|
7. Data structures (section 7): All core types present
|
|
8. File assembly (section 8): Correct TrueType structure
|
|
9. Error handling (section 9): Fail loudly and early
|
|
10. Dependencies (section 10): Only Go stdlib + x/image packages
|
|
11. Rasterizer (section 11): Font-to-bitmap with all features
|
|
12. CLI (section 12): All commands with correct flags
|
|
|
|
Run:
|
|
- go build ./...
|
|
- go test ./... -v
|
|
- dttf test --reference-dir <test-fonts>/ if available
|
|
|
|
Write comprehensive review to .ai/final_review.md.
|
|
Write status.json: outcome=succeeded if complete and spec-compliant, outcome=failed with specific missing/incorrect features otherwise."
|
|
]
|
|
|
|
check_review [shape=diamond, label="Review OK?"]
|
|
|
|
// Flow
|
|
start -> impl_setup -> verify_setup -> check_setup
|
|
check_setup -> impl_loader [condition="outcome=succeeded"]
|
|
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
|
|
|
impl_loader -> verify_loader -> check_loader
|
|
check_loader -> impl_tracer [condition="outcome=succeeded"]
|
|
check_loader -> impl_loader [condition="outcome=failed", label="retry"]
|
|
|
|
impl_tracer -> verify_tracer -> check_tracer
|
|
check_tracer -> impl_metrics [condition="outcome=succeeded"]
|
|
check_tracer -> impl_tracer [condition="outcome=failed", label="retry"]
|
|
|
|
impl_metrics -> verify_metrics -> check_metrics
|
|
check_metrics -> impl_tables [condition="outcome=succeeded"]
|
|
check_metrics -> impl_metrics [condition="outcome=failed", label="retry"]
|
|
|
|
impl_tables -> verify_tables -> check_tables
|
|
check_tables -> impl_writer [condition="outcome=succeeded"]
|
|
check_tables -> impl_tables [condition="outcome=failed", label="retry"]
|
|
|
|
impl_writer -> verify_writer -> check_writer
|
|
check_writer -> impl_validator [condition="outcome=succeeded"]
|
|
check_writer -> impl_writer [condition="outcome=failed", label="retry"]
|
|
|
|
impl_validator -> verify_validator -> check_validator
|
|
check_validator -> impl_rasterizer [condition="outcome=succeeded"]
|
|
check_validator -> impl_validator [condition="outcome=failed", label="retry"]
|
|
|
|
impl_rasterizer -> verify_rasterizer -> check_rasterizer
|
|
check_rasterizer -> impl_cli [condition="outcome=succeeded"]
|
|
check_rasterizer -> impl_rasterizer [condition="outcome=failed", label="retry"]
|
|
|
|
impl_cli -> verify_cli -> check_cli
|
|
check_cli -> impl_test_harness [condition="outcome=succeeded"]
|
|
check_cli -> impl_cli [condition="outcome=failed", label="retry"]
|
|
|
|
impl_test_harness -> verify_test_harness -> check_test_harness
|
|
check_test_harness -> impl_integration [condition="outcome=succeeded"]
|
|
check_test_harness -> impl_test_harness [condition="outcome=failed", label="retry"]
|
|
|
|
impl_integration -> verify_integration -> check_integration
|
|
check_integration -> review [condition="outcome=succeeded"]
|
|
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
|
|
|
review -> check_review
|
|
check_review -> exit [condition="outcome=succeeded"]
|
|
check_review -> impl_integration [condition="outcome=failed", label="fix"]
|
|
}
|