Skip to content

feat(phase0): codify compatibility contracts - #4

Merged
ruby-automation merged 11 commits into
mainfrom
ext-57-phase-0-contracts
Sep 14, 2026
Merged

ruby-automation merged 11 commits into
mainfrom
ext-57-phase-0-contracts

Conversation

@ruby-automation

@ruby-automation ruby-automation commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • codify the historical Stokowski b80db05, current Stokowski 79fa1bb, Continuum 237dfbb, Linear CLI 1cc36ff, and Codex 0.154.0 compatibility evidence in validated fixtures and ADRs
  • exhaustively inventory every Stokowski commit from the accepted baseline through the current pin and disposition its runner, tracker, recovery, evidence, dashboard, workflow, session, and packaging behavior into the initial Fantasia release
  • normalize duplicate-safe workflow input, prove immutable Continuum replay, and characterize current Codex JSONL, unified effort, native session resume, tracking timestamps, environment containment, and POSIX process-group cleanup
  • restore subprocess environment containment on current Stokowski main through bougyman/stokowski#10, with an actual child-process environment assertion
  • make Codex tool resolution/version verification deterministic and keep unrestricted execution an explicit externally isolated deployment capability
  • align Phase 0 with the accepted pluggable runner and unattended CLI tracker architectures, including optional tracker artifact attachments
  • record missing lc priority and timestamp output as a deferred contract blocked by EXT-64
  • add a single version source plus an unpublished fantasia version escript smoke on Linux x86_64 and macOS arm64 CI

Verification

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test (35 tests)
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run
  • vendored Stokowski test suite (318 passed, 1 skipped)

Architecture and deferred work

The Codex module in this Phase 0 spike is provider-protocol characterization, not the production adapter boundary. Production runner and tracker adapters remain governed by the accepted pluggable registry, capability, shared command-owner, and conformance-suite ADRs.

Continuum owns durable workflow history, replay, state-announcement idempotency, and gate recovery after restart. Tracker comments remain durable external signals and legacy reconstruction inputs, not a competing workflow state machine.

Burrito/native standalone packaging, Drafter, publishing, and production process supervision remain follow-up work. Linear CLI priority and stable timestamp metadata is explicitly blocked by EXT-64; Fantasia will not bypass that CLI boundary with a direct Linear client.

Linear: https://linear.app/the-rubyists/issue/EXT-57/fantasia-phase-0-contract-and-distribution-spikes

@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework update:

  • diagnosed the Linux failure from Actions job 103875312156: the process-tree probe's negative process-group ID was parsed without an option terminator, so the port never observed group shutdown
  • added the portable -- separator before the negative PGID and re-ran all 27 tests locally
  • changed the artifact smoke expectation to derive from the canonical .version.txt-backed application version instead of duplicating 0.1.0

Verification remains green locally: format, warnings-as-errors compile, full tests, and mix phase0.verify. No force-push was used.

@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework summary

  • Diagnosed the Linux x86_64 failure in the process-lifecycle probe; macOS arm64 was already green and no reviewer comments were outstanding.
  • Made negative process-group signaling portable by separating kill options from the negative PID with --.
  • Replaced the hard-coded artifact version expectation with the repository's .version.txt authority through Stokowski.version/0.
  • Made process-tree disappearance the primary lifecycle assertion, increased the bounded CI cleanup window to five seconds, and explicitly closes the BEAM port during failure cleanup.
  • Preserved the existing PR history and pushed signed follow-up commits without force-pushing.

Verification:

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test (27 tests)
  • lifecycle probe repeated successfully 50 times
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Workflow normalization, Codex event handling, and several normative fixtures currently violate their stated contracts.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Codifies Phase 0 compatibility contracts, fixtures, runtime boundaries, and cross-platform escript verification.

Changes:

  • Adds compatibility ADRs, ledger validation, and behavioral fixtures.
  • Implements workflow normalization, Codex event handling, tracking, environment, and replay contracts.
  • Adds deterministic versioning and CI artifact smoke tests.
File summaries
File Description
workflow.yaml Uses fresh Codex sessions.
Readme.adoc Documents Phase 0 verification.
mix.lock Locks new dependencies.
mix.exs Reads the shared version.
mise.toml Pins Codex 0.154.0.
documents/decisions/0001-phase-0-compatibility-and-provenance.adoc Records compatibility provenance.
documents/decisions/0002-parser-prompt-http-and-tracking.adoc Defines parser and tracking contracts.
documents/decisions/0003-runner-permissions-session-and-lifecycle.adoc Defines runner boundaries.
documents/decisions/0004-continuum-recovery.adoc Defines replay authority.
documents/decisions/0005-distribution-and-release.adoc Defines Phase 0 packaging.
apps/stokowski/test/support/stubborn_process_tree.py Provides lifecycle test process tree.
apps/stokowski/test/stokowski/workflow_test.exs Tests workflow normalization.
apps/stokowski/test/stokowski/runner_tracking_test.exs Tests runner and tracking contracts.
apps/stokowski/test/stokowski/process_lifecycle_test.exs Tests POSIX group cleanup.
apps/stokowski/test/stokowski/phase0_flow_test.exs Tests immutable replay.
apps/stokowski/test/stokowski/compatibility_test.exs Tests ledger validation.
apps/stokowski/test/stokowski/cli_test.exs Tests version output.
apps/stokowski/test/stokowski_test.exs Tests application versioning.
apps/stokowski/test/fixtures/tracking/comments.yaml Adds tracking evidence.
apps/stokowski/test/fixtures/tracking/comments.json Adds tracking input data.
apps/stokowski/test/fixtures/runners/provenance.yaml Records Codex provenance.
apps/stokowski/test/fixtures/runners/process-lifecycle.yaml Records cleanup expectations.
apps/stokowski/test/fixtures/runners/environment.yaml Records environment policy.
apps/stokowski/test/fixtures/runners/distribution.yaml Records packaging targets.
apps/stokowski/test/fixtures/runners/codex.yaml Records Codex arguments.
apps/stokowski/test/fixtures/runners/codex-events.jsonl Adds Codex event samples.
apps/stokowski/test/fixtures/prompts/context.yaml Adds prompt context.
apps/stokowski/test/fixtures/linear/responses.yaml Adds Linear response scenarios.
apps/stokowski/test/fixtures/config/normalized-flow.yaml Adds normalized replay input.
apps/stokowski/test/fixtures/config/full-workflow.yaml Adds comprehensive YAML input.
apps/stokowski/test/fixtures/config/duplicate-keys.yaml Adds duplicate-key input.
apps/stokowski/test/fixtures/compatibility_ledger.yaml Indexes compatibility evidence.
apps/stokowski/mix.exs Configures dependencies and escript.
apps/stokowski/lib/stokowski/workflow.ex Implements normalization and fingerprints.
apps/stokowski/lib/stokowski/tracking.ex Parses tracking markers.
apps/stokowski/lib/stokowski/runner/codex.ex Builds argv and normalizes events.
apps/stokowski/lib/stokowski/phase0_flow.ex Implements replay proof.
apps/stokowski/lib/stokowski/environment.ex Builds child environments.
apps/stokowski/lib/stokowski/compatibility.ex Validates the ledger.
apps/stokowski/lib/stokowski/cli.ex Implements the version command.
apps/stokowski/lib/stokowski.ex Exposes the application version.
apps/repo_management/test/mix/tasks/stokowski_test.exs Tests deterministic Codex resolution.
apps/repo_management/lib/mix/tasks/stokowski.ex Verifies the managed Codex executable.
apps/repo_management/lib/mix/tasks/phase0.verify.ex Adds Phase 0 verification.
AGENTS.md Documents verification procedures.
.version.txt Defines the canonical version.
.gitignore Ignores the generated escript.
.github/workflows/phase0.yaml Runs cross-platform Phase 0 CI.
Review details
  • Files reviewed: 46/48 changed files
  • Comments generated: 8
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/stokowski/lib/stokowski/workflow.ex Outdated
Comment thread apps/stokowski/test/fixtures/tracking/comments.yaml Outdated
Comment thread apps/stokowski/lib/stokowski/environment.ex Outdated
Comment thread apps/stokowski/lib/stokowski/runner/codex.ex
Comment thread apps/stokowski/test/fixtures/runners/codex-events.jsonl Outdated
Comment thread Readme.adoc Outdated
Comment thread apps/stokowski/test/fixtures/compatibility_ledger.yaml Outdated
Comment thread apps/stokowski/test/fixtures/prompts/context.yaml
@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework summary

Addressed all eight material review threads in signed commit 13fef92:

  • retained raw yamerl container shape so empty mappings and sequences normalize without type loss while duplicate detection remains intact;
  • added SSH_AUTH_SOCK to the explicit runner allowlist, fixture, and containment test;
  • handled top-level Codex fatal errors and nested turn failures, and corrected the Codex 0.154.0 JSONL fixture/item and usage fields;
  • repaired and consumer-tested the tracking YAML fixture;
  • corrected the README verification sequence and checkout-independent artifact terminology;
  • narrowed the prompt fixture/ADR claim to the context behavior Phase 0 actually demonstrates, leaving executable rendering semantics explicitly deferred.

Verification completed:

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test — 28 passed
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run with verified Codex 0.154.0

No force-push was used.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Environment containment remains unenforced, and parsing plus process-readiness edge cases can violate the declared contracts.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

apps/stokowski/lib/stokowski/tracking.ex:26

  • A marker without an embedded timestamp is accepted using the Linear comment creation time. That contradicts the new contract to validate embedded marker timestamps and lets an incomplete marker participate in recovery ordering. Require payload["timestamp"] to be present and parseable instead of falling back to createdAt.
    apps/stokowski/test/support/stubborn_process_tree.py:22
  • The PID file is used as a readiness signal, but the child records the grandchild immediately after Popen, before the grandchild necessarily installs its SIGTERM handler. There is also a race where this append can happen before the session leader opens the same file with "w", truncating the grandchild PID. Initialize the file before spawning and use an explicit readiness acknowledgement from each descendant before the test sends TERM; also register cleanup before waiting so a failed handshake cannot leak the detached tree.
  • Files reviewed: 46/48 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread apps/repo_management/lib/mix/tasks/stokowski.ex Outdated
Comment thread apps/stokowski/lib/stokowski/workflow.ex Outdated
Comment thread apps/stokowski/lib/stokowski/workflow.ex Outdated
@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework summary

Addressed the three remaining inline comments and both material suppressed findings in signed Fantasia commit ab3bd33:

  • enforced the agent environment allowlist at the real Python subprocess boundary, preserving SSH_AUTH_SOCK and explicit Linear/project values while excluding ambient credentials; the owning Stokowski change is signed commit 342862a and the Fantasia gitlink/ledger/ADRs now record it;
  • reject non-string YAML mapping keys with a structured error and detect duplicate merge keys before separating merge entries;
  • require a valid embedded tracking-marker timestamp instead of falling back to Linear createdAt;
  • initialize the lifecycle readiness file before spawning descendants, publish each PID only after its SIGTERM handler is installed, and register cleanup before waiting for readiness.

Verification completed:

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test — 31 passed
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run with Codex 0.154.0
  • vendored Stokowski unittest suite — 30 passed
  • lifecycle probe — 50 consecutive passes

Both commits are SSH-signed and were pushed without force.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Ledger validation currently accepts required fields with empty or non-string values.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 46/49 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread apps/stokowski/lib/stokowski/compatibility.ex
@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework verification — ledger validation

The existing PR branch is aligned locally with head d064e97, including the signed a77e7f5 correction for the latest review finding. Compatibility-ledger validation now rejects nil, empty, whitespace-only, and non-string values for every required field, with focused coverage across all seven fields. The shallow-submodule compatibility test and the current vendor/stokowski@79fa1bb pin are also present.

Verification from the PR head:

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test — 35 passed
  • mise exec -- mix cmd --app stokowski mix escript.build and ./fantasia version — fantasia 0.1.0
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run with verified Codex 0.154.0
  • vendored Stokowski ./scripts/test.sh — 318 passed, 1 skipped
  • GitHub Actions — Linux x86_64 and macOS arm64 passed

The PR remains mergeable and no new limitations were introduced.

@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework summary

Addressed the adversarial review findings on signed commit 4af04e0:

  • Added YAML merge-sequence normalization with YAML precedence, explicit handling/documentation for yamerl flow-mapping alias limitations, and coverage for inherited keys, empty documents, and parser errors.
  • Bound every compatibility-ledger fixture to a consumer assertion or the Phase 0 verifier; corrected deferred prompt/Linear claims and added Claude provenance.
  • Pinned Claude Code 2.1.270, resolved and version-verified both configured runners through mise, and prepended only their verified executable directories.
  • Hardened ledger validation for empty ledgers and unavailable vendored revisions, scoped runner pins to [tools], and fetched complete submodule history in CI.
  • Made .version.txt authoritative across Mix projects/tests/docs, preserved pre-existing root escripts during verification, enforced the project environment allowlist, and fixed detached process-group cleanup on readiness failure.

Local verification:

  • mise exec -- mix format --check-formatted
  • mise exec -- mix compile --warnings-as-errors
  • mise exec -- mix test — 45 passed
  • mise exec -- mix phase0.verify
  • mise exec -- mix stokowski --dry-run — verified Codex 0.154.0 and Claude 2.1.270
  • 50 lifecycle repetitions
  • vendored Stokowski suite — 318 passed, 1 skipped
  • escript build/version smoke and invalid-command exit check

The branch was pushed without force-pushing; Ubuntu x86_64 and macOS arm64 checks are queued.

@ruby-automation

Copy link
Copy Markdown
Contributor Author

Rework update

Addressed the latest adversarial review on signed commit 5779dcd:

  • replaced the raw YAML source regex with yamerl token-stream detection;
  • reject ordinary and merge aliases to flow mappings/sequences with {:invalid_alias, anchor};
  • added plain-alias fixtures and regression coverage for comments, quoted scalars, and invalid-key precedence;
  • made [tools] runner resolution independent of TOML table order and support prerelease probes;
  • bound both environment allowlists to their fixture and removed the unused Environment.child/3 parameter;
  • removed the orphan tracking JSON, simplified the artifact smoke to one temporary directory, and excluded zombies from lifecycle liveness.

Verification:

  • umbrella format, warnings-as-errors compilation, and 49 Elixir tests pass;
  • mix phase0.verify, live mix stokowski --dry-run, and escript version smoke pass;
  • vendored Stokowski suite: 318 passed, 1 skipped;
  • PR checks pass on Ubuntu x86_64 and macOS arm64.

@ruby-automation
ruby-automation merged commit f329248 into main Sep 14, 2026
2 checks passed
@ruby-automation
ruby-automation deleted the ext-57-phase-0-contracts branch September 14, 2026 23:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants