feat(plan): typed steps carry id, allow_failure, timeout_seconds #99

Merged
gotoi-agent merged 1 commit from issue/89-typed-steps into agent-develop 2026-10-09 09:46:34 +02:00
Collaborator

Summary

Plan.steps: string[] on the wire stays byte-identical. Add an optional typed overlay via contract.typedSteps so bare string[] clients keep working unchanged.

  • normalizeStepInput(string|object) → { run: string[], typed?: TypedStep[] } — single source for both surfaces.
  • Prose steps rejected at create time with the 1-based offending index (skipped when steps carry an agent block).
  • Length violation now names index + actual length; the literal "step longer than 64 chars" is gone.
  • allow_failure enforced at middleware scoring time only (Go's Step has no such field and unknown YAML keys are ignored).
  • timeout_seconds (1..86400) emitted as YAML timeout: for repo plans.
  • Migration 0033_plan_typed_steps (jsonb on plan_contract).
  • UC-MW-174 + UC-MW-175.
  • 11 new tests, all passing (16.15 s).

Why this lands as a single squash

The omp coder (session 2026-10-09T02-14-14-714Z) completed the full implementation and ran the suite to 11/11 green, then was killed by the harness while waiting on the parallel full suite. The working tree was dirty, the cron-fired runner never saw a commit (its status check is on git log, not git status), and the work sat uncommitted since 05:56. This single commit captures the deliverable for the operator.

Gates

  • bun test middleware/tests/uc-mw-174-typed-steps.test.ts: 11 pass / 0 fail / 29 expect() calls / 16.15 s.
  • bun test middleware/tests/uc-mw-cluster2-plans.test.ts: 17 pass / 1 fail (UC-MW-35 DELETE idempotent — pre-existing on base 038c94b, not introduced by this change).
  • python3 scripts/check-use-cases.py / _check.py: 366 UCs conform.
  • python3 scripts/check-ai-headers.py: 579 ok / 0 missing / 0 malformed.
  • python3 scripts/check-type-mirror.py: clean (4 dashboard-only types noted as info).

Files

  • 18 modified, 5 new (2 UCs + Drizzle migration up/down + the new test file).
  • +652 / -79 net lines (the bulk is the new test file at 248 lines and the new UC docs).

Refs #89

## Summary `Plan.steps: string[]` on the wire stays byte-identical. Add an optional typed overlay via `contract.typedSteps` so bare `string[]` clients keep working unchanged. - `normalizeStepInput(string|object) → { run: string[], typed?: TypedStep[] }` — single source for both surfaces. - Prose steps rejected at create time with the **1-based offending index** (skipped when steps carry an agent block). - Length violation now names index + actual length; the literal `"step longer than 64 chars"` is gone. - `allow_failure` enforced at **middleware scoring time** only (Go's Step has no such field and unknown YAML keys are ignored). - `timeout_seconds` (1..86400) emitted as YAML `timeout:` for repo plans. - Migration `0033_plan_typed_steps` (jsonb on plan_contract). - UC-MW-174 + UC-MW-175. - **11 new tests, all passing** (16.15 s). ## Why this lands as a single squash The omp coder (session `2026-10-09T02-14-14-714Z`) completed the full implementation and ran the suite to **11/11 green**, then was killed by the harness while waiting on the parallel full suite. The working tree was dirty, the cron-fired runner never saw a commit (its status check is on `git log`, not `git status`), and the work sat uncommitted since 05:56. This single commit captures the deliverable for the operator. ## Gates - `bun test middleware/tests/uc-mw-174-typed-steps.test.ts`: **11 pass / 0 fail** / 29 expect() calls / 16.15 s. - `bun test middleware/tests/uc-mw-cluster2-plans.test.ts`: 17 pass / 1 fail (UC-MW-35 DELETE idempotent — pre-existing on base `038c94b`, **not** introduced by this change). - `python3 scripts/check-use-cases.py` / `_check.py`: 366 UCs conform. - `python3 scripts/check-ai-headers.py`: 579 ok / 0 missing / 0 malformed. - `python3 scripts/check-type-mirror.py`: clean (4 dashboard-only types noted as info). ## Files - 18 modified, 5 new (2 UCs + Drizzle migration up/down + the new test file). - +652 / -79 net lines (the bulk is the new test file at 248 lines and the new UC docs). Refs #89
Plan.steps: string[] on wire stays byte-identical. Add optional typed overlay
via contract.typedSteps; bare string[] clients keep working unchanged.

- normalizeStepInput maps `string | {run, id?, allow_failure?, timeout_seconds?,
  description?}` onto a Plan.steps entry (run[]) and a contract.typedSteps
  entry (typed); both paths are read by the agent and the dashboard.
- Prose steps are rejected at create time with the 1-based offending index
  (skipped when steps contain an agent block). The length violation now names
  the index and the actual length; "step longer than 64 chars" is gone.
- allow_failure is enforced at middleware scoring time only; Go's Step has no
  such field and unknown YAML keys are ignored. timeout_seconds (1..86400)
  is emitted as the YAML `timeout:` for repo plans.
- New migration 0033_plan_typed_steps (typedSteps on plan_contract jsonb).
- UC-MW-174 typed steps surface; UC-MW-175 prose rejection at create time.
- 11 new tests (typed-step creation, normalizeStepInput, planFingerprint
  unchanged, the patched steps, the AllowFailure scoring seam, expiry-1..
  86400, dbColumn round-trip via the contract).

Gates:
- UC-MW-174 + UC-MW-175: 11 pass / 0 fail / 29 expect() / 16.15 s
- middleware/tests/uc-mw-cluster2-plans.test.ts: 17 pass / 1 fail
  (UC-MW-35 DELETE idempotent — pre-existing on base 038c94b, unrelated to
  this change)
- docs/use-cases/_check.py: 366 UCs conform
- scripts/check-ai-headers.py: 579 ok / 0 missing / 0 malformed
- scripts/check-type-mirror.py: clean (4 dashboard-only types noted as info)

Refs #89
gotoi-agent merged commit 5b84430f26 into agent-develop 2026-10-09 09:46:34 +02:00
Sign in to join this conversation.
No description provided.