◐ Off-By-One · answer catalog

go-spec-writing-unblock

2 answer(s)godockergodocker

go-spec-writing-unblock

📦 Source in repository (JSON)

Answer 1

The fix: GAP-001 was spec-blocked (board gate: "needs implementation spec before dispatch"). Unblocked by committing the spec as foreman-direct non-code work — ~/specs/SPEC-IMPL-GAP-001-context-compiler.md — via the shortened loop (skip worker/guard/judge, commit docs). The spec defines internal/contextcompiler per the required template.

Exact Go interfaces (core contract, verified compilable):

type SourceKind string
const (
    SourceBoard SourceKind = "board"    // Hilo dispatch board state
    SourceEnv   SourceKind = "env"      // environment variables
    SourceSpec  SourceKind = "spec"     // implementation spec documents
    SourceMessage  SourceKind = "message"  // session / message log
    SourceToolSpec SourceKind = "toolspec" // tool schema definitions
)

type Source interface {
    ID() string
    Kind() SourceKind
    Raw(ctx context.Context) (io.Reader, error) // must be concurrency-safe
}

type Options struct {
    IncludeEnv    bool
    MaxDepth      int           // ref resolution cap; default 8
    Timeout       time.Duration // per-compile budget; default 5s
    Required      []SourceKind  // fail fast if absent
    SecretPattern string        // regex; matched env values redacted
}

type Section struct {
    ID, SourceID, Body, Digest string
    Kind       SourceKind
    Refs       []string
    Depth      int
    Provenance map[string]string
}

type Compiled struct {
    Sections    []Section // stable order: source order, then ID
    Digest      string    // sha256 over ordered section digests
    CompiledAt  time.Time
    Elapsed     time.Duration
    SourceCount int
}

type Validator interface{ Validate(c *Compiled) error }
type Hook      interface{ AfterCompile(ctx context.Context, c *Compiled) error }
type Store     interface {
    Save(ctx context.Context, c *Compiled) error
    Load(ctx context.Context, digest string) (*Compiled, error)
}
type Compiler interface {
    Compile(ctx context.Context, sources []Source, opts Options) (*Compiled, error)
}

func New(store Store, validators []Validator, hooks []Hook) Compiler

Ordered algorithm (deterministic): 1. Preflight — defaults (Timeout 5s, MaxDepth 8, secret regex); validate opts. 2. Fail fast — every Required kind must have ≥1 source → else ErrSourceMissing (never a partial compile). 3. Normalize — iterate sources in caller order; Raw(ctx) capped at 1 MiB; per-section sha256(ID+Kind+SourceID+Body). 4. Resolve refs — DFS with visiting set: cycle → ErrRefCycle, dangling → ErrRefDangling, depth > MaxDepth → ErrTooDeep; record Depth. 5. Validate — run Validators in order (unique IDs, required bodies non-empty). 6. Compose — final order = source order, then ID ascending; overall digest over ordered section digests. 7. Persist — store.Save best-effort (logged, not fatal). 8. Hooks — fire in order; errors logged, not fatal. Deadline at any step → ErrTimeout.

Error catalog (10 codes): SRC_MISSING, SRC_READ, PARSE, REF_CYCLE, REF_DANGLING, VAL, OP_TIMEOUT, DEPTH (all 422, OP_TIMEOUT 504), NOT_FOUND (404), INTERNAL (500) — via ErrorCode(err) sentinel mapping.

Test scenarios: 15 unit (U1 empty compile, U2 missing required, U3 order preserved, U4 dup IDs, U5 dangling ref, U6 self-cycle, U7 two-node cycle, U8 depth cap, U9 determinism, U10 checksum sensitivity, U11 timeout, U12 secret redaction, U13 provenance, U14 empty body, U15 concurrent independence) + 5 handler (H1 POST /compile 200, H2 missing kind 422 SRC_MISSING, H3 cycle 422 REF_CYCLE, H4 GET miss 404 NOT_FOUND, H5 /health 200/503).

Wiring: main builds contextcompiler.New(store, validators, hooks), handlers.Register(mux, cc) (POST /compile, GET /compile/{id}, GET /health); env: GAP_CC_TIMEOUT, GAP_CC_MAX_DEPTH, GAP_CC_SOURCE_ORDER.

Hilo impact: board gate satisfied by foreman-committed spec; GAP-001 spec-blocked ticks 3 → 0; dispatch proceeds next tick. Additive package, no dispatch/worker contract changes, low risk (deterministic, no network deps, redaction on), revert = delete package + spec.


Evidence & signatures

1. **Spec committed** — `~/specs/SPEC-IMPL-GAP-001-context-compiler.md` written (11,559 bytes), all 9 template sections present (`#`, `## 1..9`, `### 6.1`, `### 6.2` headings verified via grep).
2. **Scenario counts** — awk extraction of the scenario tables confirms exactly **U1–U15 (15 unit)** and **H1–H5 (5 handler)**; 10 error-code rows in the catalog.
3. **Interfaces type-check** — extracted the exact declarations into a scratch module (`/tmp/cccheck`, `go mod init example.com/cccheck`):
   - `go vet ./...` → clean
   - `go build ./...` → **TYPECHECK-OK**
   - `gofmt -l .` → clean after `gofmt -w` (no formatting drift)
4. **Error catalog behavior** — added a unit test asserting all 10 `ErrorCode` mappings (`ErrSourceMissing→SRC_MISSING`, …, `ErrNotFound→NOT_FOUND`, unknown→`INTERNAL`); `go test ./...` → **ok, 0.002s**.
5. **Edge cases covered in spec** — zero sources, empty required body, self- and mutual cycles, dangling refs, depth overflow, deadline expiry, secret leakage, determinism/checksum sensitivity, concurrent compiles, store miss, store-down health.

---
{"model": "deepseek-v4-flash", "problem_class": "go-spec-writing-unblock", "result": "passed", "tests": 20}

Answer 2

The fix: GAP-001 was spec-blocked (board gate: "needs implementation spec before dispatch"). Unblocked by committing the spec as foreman-direct non-code work — ~/specs/SPEC-IMPL-GAP-001-context-compiler.md — via the shortened loop (skip worker/guard/judge, commit docs). The spec defines internal/contextcompiler per the required template.

Exact Go interfaces (core contract, verified compilable):

type SourceKind string
const (
    SourceBoard SourceKind = "board"    // Hilo dispatch board state
    SourceEnv   SourceKind = "env"      // environment variables
    SourceSpec  SourceKind = "spec"     // implementation spec documents
    SourceMessage  SourceKind = "message"  // session / message log
    SourceToolSpec SourceKind = "toolspec" // tool schema definitions
)

type Source interface {
    ID() string
    Kind() SourceKind
    Raw(ctx context.Context) (io.Reader, error) // must be concurrency-safe
}

type Options struct {
    IncludeEnv    bool
    MaxDepth      int           // ref resolution cap; default 8
    Timeout       time.Duration // per-compile budget; default 5s
    Required      []SourceKind  // fail fast if absent
    SecretPattern string        // regex; matched env values redacted
}

type Section struct {
    ID, SourceID, Body, Digest string
    Kind       SourceKind
    Refs       []string
    Depth      int
    Provenance map[string]string
}

type Compiled struct {
    Sections    []Section // stable order: source order, then ID
    Digest      string    // sha256 over ordered section digests
    CompiledAt  time.Time
    Elapsed     time.Duration
    SourceCount int
}

type Validator interface{ Validate(c *Compiled) error }
type Hook      interface{ AfterCompile(ctx context.Context, c *Compiled) error }
type Store     interface {
    Save(ctx context.Context, c *Compiled) error
    Load(ctx context.Context, digest string) (*Compiled, error)
}
type Compiler interface {
    Compile(ctx context.Context, sources []Source, opts Options) (*Compiled, error)
}

func New(store Store, validators []Validator, hooks []Hook) Compiler

Ordered algorithm (deterministic): 1. Preflight — defaults (Timeout 5s, MaxDepth 8, secret regex); validate opts. 2. Fail fast — every Required kind must have ≥1 source → else ErrSourceMissing (never a partial compile). 3. Normalize — iterate sources in caller order; Raw(ctx) capped at 1 MiB; per-section sha256(ID+Kind+SourceID+Body). 4. Resolve refs — DFS with visiting set: cycle → ErrRefCycle, dangling → ErrRefDangling, depth > MaxDepth → ErrTooDeep; record Depth. 5. Validate — run Validators in order (unique IDs, required bodies non-empty). 6. Compose — final order = source order, then ID ascending; overall digest over ordered section digests. 7. Persist — store.Save best-effort (logged, not fatal). 8. Hooks — fire in order; errors logged, not fatal. Deadline at any step → ErrTimeout.

Error catalog (10 codes): SRC_MISSING, SRC_READ, PARSE, REF_CYCLE, REF_DANGLING, VAL, OP_TIMEOUT, DEPTH (all 422, OP_TIMEOUT 504), NOT_FOUND (404), INTERNAL (500) — via ErrorCode(err) sentinel mapping.

Test scenarios: 15 unit (U1 empty compile, U2 missing required, U3 order preserved, U4 dup IDs, U5 dangling ref, U6 self-cycle, U7 two-node cycle, U8 depth cap, U9 determinism, U10 checksum sensitivity, U11 timeout, U12 secret redaction, U13 provenance, U14 empty body, U15 concurrent independence) + 5 handler (H1 POST /compile 200, H2 missing kind 422 SRC_MISSING, H3 cycle 422 REF_CYCLE, H4 GET miss 404 NOT_FOUND, H5 /health 200/503).

Wiring: main builds contextcompiler.New(store, validators, hooks), handlers.Register(mux, cc) (POST /compile, GET /compile/{id}, GET /health); env: GAP_CC_TIMEOUT, GAP_CC_MAX_DEPTH, GAP_CC_SOURCE_ORDER.

Hilo impact: board gate satisfied by foreman-committed spec; GAP-001 spec-blocked ticks 3 → 0; dispatch proceeds next tick. Additive package, no dispatch/worker contract changes, low risk (deterministic, no network deps, redaction on), revert = delete package + spec.


Evidence & signatures

1. **Spec committed** — `~/specs/SPEC-IMPL-GAP-001-context-compiler.md` written (11,559 bytes), all 9 template sections present (`#`, `## 1..9`, `### 6.1`, `### 6.2` headings verified via grep).
2. **Scenario counts** — awk extraction of the scenario tables confirms exactly **U1–U15 (15 unit)** and **H1–H5 (5 handler)**; 10 error-code rows in the catalog.
3. **Interfaces type-check** — extracted the exact declarations into a scratch module (`/tmp/cccheck`, `go mod init example.com/cccheck`):
   - `go vet ./...` → clean
   - `go build ./...` → **TYPECHECK-OK**
   - `gofmt -l .` → clean after `gofmt -w` (no formatting drift)
4. **Error catalog behavior** — added a unit test asserting all 10 `ErrorCode` mappings (`ErrSourceMissing→SRC_MISSING`, …, `ErrNotFound→NOT_FOUND`, unknown→`INTERNAL`); `go test ./...` → **ok, 0.002s**.
5. **Edge cases covered in spec** — zero sources, empty required body, self- and mutual cycles, dangling refs, depth overflow, deadline expiry, secret leakage, determinism/checksum sensitivity, concurrent compiles, store miss, store-down health.

---
{"model": "deepseek-v4-flash", "problem_class": "go-spec-writing-unblock", "result": "passed", "tests": 20}
Generated from the verified corpus · MIT licensedBack to the catalog