diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d73c9df --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,32 @@ +# Changelog + +All notable changes to this project are documented here. Detailed notes live in +[RELEASE_NOTES.md](RELEASE_NOTES.md). + +## [0.2.0] - unreleased (relaunch) + +### Added +- Policy overlay execution mode: `xflow policy validate`, plus policy, notify, storage, plugin and + experience-digest atoms. +- `xflow intake recommend` for adaptive yolo/corps track selection. +- `xflow profile show|set` for execution profiles. +- `xflow compare super-assistant`. +- `docs/assets/demo.gif`, recorded from a real CLI run, and a README rewrite. +- `CHANGELOG.md`. + +### Changed +- The npm package is now named `@surlymochan/openflow`, because the unscoped `openflow` name is taken. The CLI is still `xflow`. +- `package.json` adds repository/homepage/bugs/keywords/author, `engines.node >= 22.5` and public `publishConfig`. +- The `xflow serve` fallback message no longer links to an unpublished repository. + +### Fixed +- `agent_invoke` no longer crashes with an uncaught `EPIPE` when an agent CLI exits before reading its stdin prompt. This fixes an intermittent `heavy-atoms` test failure. + +## [0.1.0] - 2026-05-25 + +### Added +- First public extraction: + - YAML workflows (`yolo`, `corps`) validated against the atom registry. + - Red/green TDD proof gates and a test-quality review. + - Handoff and AHA state, archive ordering, and the `xflow` CLI. +- Adapters: `xflow adapter import-file` and `xflow adapter github-issue`. diff --git a/README.md b/README.md index 3c33847..0168f24 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,152 @@ # OpenFlow [![CI](https://github.com/surlymochan/openflow/actions/workflows/ci.yml/badge.svg)](https://github.com/surlymochan/openflow/actions/workflows/ci.yml) -[![xflow score](https://img.shields.io/badge/xflow%20score-100%2F100-brightgreen)](docs/competitive-benchmark.md) -[![publish check](https://img.shields.io/badge/publish--check-dry--run%20ready-blue)](docs/public-release.md) -[![spec delta](https://img.shields.io/badge/spec%20delta-requirements--level-blueviolet)](docs/openspec-migration.md) +[![npm](https://img.shields.io/npm/v/@surlymochan/openflow?label=npm)](https://www.npmjs.com/package/@surlymochan/openflow) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +![node >= 22.5](https://img.shields.io/badge/node-%E2%89%A522.5-informational) + +**Executable delivery workflow for AI coding agents.** + +Prompt-based workflows *ask* an agent to write the failing test first, run the suite and keep notes. OpenFlow +*checks* that it did. Workflows are YAML phases made of small deterministic "atoms". Gates are code: a +red/green TDD proof, a test-quality review, artifact checks, and archive ordering. The `xflow` CLI runs the +same workflows from Codex, Claude Code, Cursor, OpenCode, Gemini or a plain terminal. + +![OpenFlow demo: a red proof must fail, a green proof must pass, and a faked red proof is rejected](docs/assets/demo.gif) + +Recorded from a real run of the CLI in an empty project. The last two commands show an agent "recording" a +red proof after the fix, and the gate rejecting it. + +## Why + +Agent workflow kits are good at shaping behaviour, but the checks only live in prose. Agents skip the red +step, write tests that assert nothing, lose context between sessions, and open PRs before verification has +finished. OpenFlow adds a harder layer underneath: + +- **Workflow as data.** `workflows/yolo.yaml` and `workflows/corps.yaml` are validated against an atom registry before they run. +- **TDD proof checked by code.** + - The red proof must fail before implementation and the green proof must pass after it. + - `I6c.tdd.quality_review` rejects code changes that have: + - no meaningful test changes, + - empty assertions, + - snapshot-only tests, + - mock-heavy tests without real assertions. +- **Context that survives sessions.** + - The `.xflow/GOAL.md` project anchor. + - `HANDOFF.md` and `AHA.md`. + - Per-change `status.json` and proof files under `specs/changes//`. +- **Executable finish.** Verify → archive → commit/push → PR ordering is a tested atom, not a checklist. -Executable delivery workflow for AI coding agents. - -OpenFlow is the public extraction of the `openflow` workflow runtime. It turns -agent work from "follow this prose process" into a local workflow runtime with -YAML phases, deterministic atoms, TDD proof gates, handoff state, archive -discipline, and packageable CLI commands. - -## Why It Exists - -Most agent workflow systems are strong at behavior shaping. OpenFlow adds a -harder layer: +## 3 Minute Start -- workflow data that can be validated before it runs -- red/green TDD proof that is checked by code, not only by prompt discipline -- `quality-0.json` test-quality review for code/test pairing and common fake-test patterns -- local handoff and AHA files so context survives across sessions -- archive and PR ordering that is executable and test-covered -- clean-project adoption proof in CI plus a reviewable maintainer adoption record +Requires Node.js ≥ 22.5 (for `node:sqlite`) and Python 3 (atoms are small Python scripts). -## 3 Minute Start +```bash +npm install -g @surlymochan/openflow # installs the `xflow` CLI +cd your-project +xflow init --project-root . # writes .as-xflow/config.json +xflow goal set "Ship the next verified change" --project-root . +xflow goal audit --project-root . --json +xflow doctor --project-root . +xflow workflow validate yolo --project-root . +xflow guide # the delivery loop in one screen +``` For a source checkout: ```bash git clone https://github.com/surlymochan/openflow.git cd openflow -npm install -npm run release:pack +npm ci && npm test node bin/xflow.js quickstart -node bin/xflow.js guide node bin/xflow.js evaluate -node bin/xflow.js assess -node bin/xflow.js demo clean node bin/xflow.js compare codex-goal -node bin/xflow.js launch dossier node bin/xflow.js launch copy ``` -To initialize OpenFlow inside a target project after the CLI is linked or -installed: +## Run a change ```bash -xflow quickstart -xflow guide -xflow init --project-root . -xflow goal set "Ship the next verified change" --project-root . -xflow goal audit --project-root . --json -xflow doctor --project-root . -xflow workflow validate yolo --project-root . +git checkout -b feat/example-change +xflow workflow run yolo \ + --title "Example change" --change-type backend \ + --tdd-red-command "npm test -- --grep new-behavior" \ + --tdd-green-command "npm test" ``` -Release-owner gates such as `xflow adoption status --json`, `xflow adoption validate --json`, -`xflow package status --json`, `xflow package preflight --check-registry --check-auth --json`, and -`xflow package audit --check-registry --json` are intentionally separate from -the first-run path because they fail until real adoption evidence, npm identity, -or published registry evidence exists. Use `xflow adoption brief --name --source --track yolo` -to generate the outbound ask, `xflow adoption trial --name --source --track yolo` -to preview the copy-paste external trial, `xflow adoption kit --name --source --track yolo` -to create a shareable packet, then `xflow adoption init --name --source --track yolo` -to create the draft record after real trial evidence exists. +The lite track runs `tdd-red -> execute -> tdd-green -> verify -> archive` and stops at human or LLM gates. Every +phase leaves evidence in `specs/changes//`. Add `--dry-run` to print the phases, atoms and gates +first. -## Run A Change +You can also run a single gate directly, as in the demo: ```bash -git checkout -b codex/example-change -xflow workflow run yolo --project-root . \ - --title "Example change" \ - --change-type backend \ - --tdd-red-command "npm test -- --grep new-behavior" \ - --tdd-green-command "npm test" +xflow atom run I6a.tdd.run --change-id my-change --phase red --test-command "npm test" +xflow atom run I6a.tdd.run --change-id my-change --phase green --test-command "npm test" +xflow atom run I6b.tdd.proof_validate --change-id my-change --phase red +``` + +## Evaluate it + +```bash +xflow quickstart # copy-paste-safe first-run commands +xflow evaluate # one-shot brief: quality score, comparisons, blockers, next actions +xflow assess # scorecard for goal, yolo, corps and the skill family +xflow score # competitive readiness score with evidence per dimension +xflow demo launch # goal -> yolo and goal -> corps proof paths +xflow launch dossier # one-page narrative backed by the same audit +xflow launch copy # claim-safe announcement copy plus forbidden phrases +xflow release status # the single next release blocker ``` -The lite workflow runs `tdd-red -> execute -> tdd-green -> verify -> archive`. +
+Release-owner gates (fail until real adoption / npm evidence exists) -Red proof must fail before implementation. Green proof must pass after implementation. `I6c.tdd.quality_review` then rejects code changes without meaningful changed tests, empty assertions, snapshot-only tests, or mock-heavy tests without real assertions. +```bash +xflow adoption trial --name --source --track yolo +xflow adoption status --json +xflow package preflight --check-registry --check-auth --json +xflow package audit --check-registry --json +xflow launch audit --pre-publish --strict --json +``` -## Choose A Track +
-| Track | Use When | Entry | +## Choose a track + +| Track | Use when | Entry | | --- | --- | --- | -| `goal` | You want a simple project direction anchor that later xflow work can read and audit | `xflow:goal`, `xflow goal set`, or `xflow goal audit` | -| `plan` | You only need a reusable implementation plan | `xflow:plan` | -| `ralph` | You want Codex to keep implementing, verifying, and repairing until completion evidence is clean | `xflow:ralph` | -| `yolo` | Backend, docs, infra, small UI, low ceremony | `xflow:yolo` or `xflow workflow run yolo` | -| `corps` | Product/UI-heavy or multi-agent work | `xflow:corps`, `xflow corps --explain`, or `xflow corps` | +| `goal` | You want a project-level direction anchor that later work reads and audits | `xflow goal set`, `xflow goal audit` | +| `plan` | You only need a reusable implementation plan | `xflow:plan` skill | +| `yolo` | Backend, docs, infra, small UI; low ceremony | `xflow workflow run yolo` | +| `corps` | Product/UI-heavy or multi-agent work with governed proof | `xflow corps --explain`, then `xflow corps` and `xflow proof --track corps` | +| `ralph` | Keep implementing, verifying and repairing until the completion evidence is clean | `xflow:ralph` skill | + +Not sure which one fits? Run `xflow intake recommend --change-id --title "" --description "<text>"`. + +## How it fits together + +``` +workflows/*.yaml ──validate──► atoms/registry.json ──► xflow/atoms/*.py (deterministic steps) + │ │ + ▼ ▼ + xflow workflow run ──► gates: deterministic | artifact-verify | human | llm + │ + ▼ + specs/changes/<id>/ status.json · tdd/red-0.json · tdd/green-0.json · quality-0.json · logs/*.ndjson +``` + +- `bin/xflow.js`: the CLI. `src/`: workflow loader, runner, policy overlays, scoring. +- `xflow/`: the portable skill family (`xflow:plan`, `xflow:yolo`, `xflow:corps`, `xflow:ralph`, …) for agent hosts. +- `schemas/`: JSON schemas for workflows, proofs and policy overlays. -`xflow:plan` is track-neutral. `yolo` and `corps` reuse an existing current plan instead of re-planning. -`xflow workflow validate corps` is preflight only; heavy-track completion is only accepted after `xflow proof --track corps` writes `corps_proof.json` with `ok=true`. The corps proof now requires the built-in governed corps manifest, hash-linked execution-log witnesses for every phase/atom/gate, and no `stub`/`pencil_stubbed` runtime fallback. +## Compared with other tools -## What Makes It Different +OpenFlow aims to complement prompt-level workflow kits and spec tools, not replace them. `xflow compare +<superpowers|openspec|gstack|spec-kit|codex-goal>` prints a side-by-side with sources. + +<details> +<summary>Full capability table</summary> | Surface | OpenFlow Position | | --- | --- | @@ -122,8 +174,13 @@ Red proof must fail before implementation. Green proof must pass after implement | Competitive proof | `xflow compare codex-goal`, `xflow compare superpowers`, `xflow compare super-assistant`, `xflow compare openspec`, `xflow compare gstack`, `xflow compare spec-kit`, benchmark docs | | Adoption proof | Minimal clean project runs in CI, plus public adoption-record templates | +</details> + ## Docs +<details> +<summary>All guides</summary> + - [Quickstart](docs/quickstart.md) - [Install and upgrade](docs/install-upgrade.md) - [Tooling matrix](docs/tooling-matrix.md) @@ -154,16 +211,21 @@ Red proof must fail before implementation. Green proof must pass after implement - [Competitive benchmark](docs/competitive-benchmark.md) - [2026-05-25 benchmark report](docs/benchmark-openflow-vs-gstack-superpowers-openspec-2026-05-25.md) -## Verify +</details> + +## Development ```bash -npm run drift:scan -npm run verify -npm run skill:diff -npm run release:pack -xflow assess -xflow launch audit -xflow score +npm ci +npx playwright install chromium # browser-evidence tests +npm test # 270+ tests +npm run drift:scan # docs/skill/workflow drift checks +npm run pack:check # what would be published ``` -Current release gate expectation: all active score dimensions are `strong`, and `xflow score` reports `100/100`. +Contributions are welcome: open an issue describing the workflow problem first, then a PR with tests. Keep +claims in docs tied to a command that reproduces them. + +## License + +[MIT](LICENSE) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 54e17ef..9d3fdbf 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,39 @@ # Release Notes +## 0.2.0 - Relaunch (first npm release) + +OpenFlow is published to npm as **`@surlymochan/openflow`**. The CLI is still `xflow`. The unscoped +`openflow` name on npm belongs to an unrelated project. + +### Highlights + +- **Policy overlays.** `xflow policy validate` checks personal and team policy layered over the built-in + workflows. Policy, notify, storage, plugin and experience-digest atoms ship with it. +- **Adaptive intake.** `xflow intake recommend` reads a demand profile (title, description, repo count) and + recommends `yolo` or `corps` plus gate overlays. It writes `workflow_recommendation.json`. +- **Execution profiles.** `xflow profile show|set` handles personal and team execution modes and provider + preferences. +- **Comparisons.** `xflow compare super-assistant` is new, next to the Superpowers, OpenSpec, gstack, + spec-kit and Codex goal comparisons. +- **New README.** It covers the problem, a demo GIF recorded from a real run, a 3-minute start and + single-gate usage (`xflow atom run I6a.tdd.run ...`). + +### Packaging + +- `package.json` now has `repository`, `homepage`, `bugs`, `keywords`, `author`, + `engines.node >= 22.5` (`node:sqlite`) and `publishConfig.access = public`. +- Install docs and the CLI's copy-paste commands now use `npm install -g @surlymochan/openflow`. +- `xflow serve` no longer points to an unpublished server repository. +- Fixed an uncaught `EPIPE` in `agent_invoke` when an agent CLI exits without reading stdin. + +### Verified for this release + +- `npm test`: 275 passed, 1 skipped, 0 failed (Node 22, Playwright Chromium installed). +- `npm run drift:scan`: 9/9. +- `npm publish --dry-run`: `@surlymochan/openflow@0.2.0`, 187 files, about 321 kB. +- Clean install from the packed tarball into an empty project: `xflow init`, `goal set`, `doctor` and + `workflow validate yolo` all pass. + ## 0.1.0 - Public Readiness Candidate This release turns `openflow` from a local skill/workflow repo into a package-ready workflow runtime for AI coding agents. diff --git a/bin/xflow.js b/bin/xflow.js index 089bdbf..05e727f 100755 --- a/bin/xflow.js +++ b/bin/xflow.js @@ -1727,7 +1727,7 @@ const LAUNCH_MISSING_SURFACES = { requirement: 'Public npm package ownership confirmed and package published from a green dry run.', why_it_matters: 'A launch story is incomplete while users cannot install the advertised package name.', acceptable_evidence: [ - 'npm view openflow name version --json returns this package', + 'npm view @surlymochan/openflow name version --json returns this package', 'npm publish --access public completed for the intended version', ], }, @@ -1993,10 +1993,10 @@ function buildLaunchCopyPayload(payload) { const packageBlocked = claims.blocked_claims.some((item) => item.id === 'published_package'); const installCommand = packageBlocked ? 'git clone <repo-url> openflow && cd openflow && npm install && node bin/xflow.js quickstart' - : 'npm install -g openflow && xflow quickstart'; + : 'npm install -g @surlymochan/openflow && xflow quickstart'; const forbiddenPhrases = []; if (packageBlocked) { - forbiddenPhrases.push('npm install -g openflow works now'); + forbiddenPhrases.push('npm install -g @surlymochan/openflow works now'); forbiddenPhrases.push('openflow is publicly installable from npm'); forbiddenPhrases.push('splash launch complete'); } @@ -4798,7 +4798,7 @@ const QUICKSTART = { label: 'Published package first run', intent: 'Copy-paste-safe commands for an evaluator after openflow is available from npm.', commands: [ - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'xflow guide', 'xflow evaluate', 'xflow assess', @@ -6532,8 +6532,8 @@ async function handleServe(args) { const { default: startServer } = await import('../src/server.js'); await startServer(); } else { - console.error('HTTP server not yet available. Heavy track requires as-agentos server.'); - console.error('See: https://github.com/surlymochan/as-agentos'); + console.error('HTTP control plane is not included in this package yet.'); + console.error('Use the CLI tracks instead: xflow workflow run yolo, or xflow corps --explain.'); process.exit(1); } } diff --git a/docs/assets/demo.gif b/docs/assets/demo.gif new file mode 100644 index 0000000..e218196 Binary files /dev/null and b/docs/assets/demo.gif differ diff --git a/docs/demo-proof.md b/docs/demo-proof.md index 61fb893..29d058c 100644 --- a/docs/demo-proof.md +++ b/docs/demo-proof.md @@ -7,7 +7,7 @@ This page defines what an external evaluator should run before trusting xflow cl From an empty temporary project: ```bash -npm install -g openflow +npm install -g @surlymochan/openflow xflow demo clean xflow guide xflow assess diff --git a/docs/install-upgrade.md b/docs/install-upgrade.md index cb973a4..ee20838 100644 --- a/docs/install-upgrade.md +++ b/docs/install-upgrade.md @@ -16,7 +16,7 @@ Use source checkout mode when developing xflow itself or when testing workflow c ## Global CLI ```bash -npm install -g openflow +npm install -g @surlymochan/openflow xflow doctor ``` diff --git a/docs/launch-dossier.md b/docs/launch-dossier.md index f1d7249..26d1641 100644 --- a/docs/launch-dossier.md +++ b/docs/launch-dossier.md @@ -101,7 +101,7 @@ Evidence: - **published_package**: Public npm package ownership confirmed and package published from a green dry run. Why it matters: A launch story is incomplete while users cannot install the advertised package name. - Acceptable evidence: npm view openflow name version --json returns this package; npm publish --access public completed for the intended version + Acceptable evidence: npm view @surlymochan/openflow name version --json returns this package; npm publish --access public completed for the intended version ## Missing Before Splash Launch @@ -110,14 +110,14 @@ Evidence: Acceptable evidence: docs/adoption/<third-party-project>.md with a public PR, external repository, or named external team source; xflow adoption validate --splash --json passes; xflow launch audit --splash --strict --json passes - **published_package**: Public npm package ownership confirmed and package published from a green dry run. Why it matters: A launch story is incomplete while users cannot install the advertised package name. - Acceptable evidence: npm view openflow name version --json returns this package; npm publish --access public completed for the intended version + Acceptable evidence: npm view @surlymochan/openflow name version --json returns this package; npm publish --access public completed for the intended version ## Current Evidence Snapshot - Adoption records: 1; status: pass - Goal audit: pass; goal: Keep OpenFlow credible as an open-source agent delivery runtime: repo-owned workflow contracts, executable verification gates, durable project context, and honest benchmark evidence. - Package evidence: missing; source: registry_json -- Package name/version: openflow@0.1.0 +- Package name/version: @surlymochan/openflow@0.2.0 ## Passing Evidence diff --git a/docs/npm-publish-handoff.md b/docs/npm-publish-handoff.md index e366669..bf2e025 100644 --- a/docs/npm-publish-handoff.md +++ b/docs/npm-publish-handoff.md @@ -8,7 +8,7 @@ distribution state. ## Current Verified State -- Package: `openflow@0.1.0` +- Package: `@surlymochan/openflow@0.2.0` - Registry name status: available in `xflow package preflight --check-registry --check-auth --json` - Current machine auth: blocked by `npm whoami` with `ENEEDAUTH` - Adoption gate: `xflow adoption validate --json` passes with @@ -22,7 +22,7 @@ distribution state. - Launch gate: `xflow launch audit --strict --json` still lists only `published_package` -Do not claim public installability until the registry reports `openflow@0.1.0`. +Do not claim public installability until the registry reports `@surlymochan/openflow@0.2.0`. ## Auth Recovery @@ -38,7 +38,7 @@ The preflight must report: - `ok: true` - `registry_status: "available"` for a first publish - a non-empty `npm_identity` -- no `registry already contains openflow@0.1.0` issue +- no `registry already contains @surlymochan/openflow@0.2.0` issue - `next_actions` containing `run_pre_publish_gate` as the next release-owner command @@ -70,7 +70,7 @@ returns the expected name and version. ## Stop Conditions - `npm whoami` fails: restore npm auth first. -- Registry already contains `openflow@0.1.0`: do not republish; bump version or +- Registry already contains `@surlymochan/openflow@0.2.0`: do not republish; bump version or verify ownership before continuing. - `xflow package preflight --check-registry --check-auth --json` fails: follow its `next_actions` before retrying or publishing. diff --git a/docs/public-release.md b/docs/public-release.md index 6c7bb25..ec8ef43 100644 --- a/docs/public-release.md +++ b/docs/public-release.md @@ -9,7 +9,7 @@ The package name `openflow` was checked against the npm public registry during t Do not treat this as permanent ownership. Re-check before publishing. ```bash -npm view openflow name version --json +npm view @surlymochan/openflow name version --json ``` ## Release Check @@ -120,7 +120,7 @@ Record these in the release note or PR: ## Failure Rules -- If `npm view openflow` returns an existing package not owned by this project, choose a new package name before publishing. +- If `npm view @surlymochan/openflow` returns an existing package not owned by this project, choose a new package name before publishing. - If `xflow package preflight --check-registry --check-auth --json` fails, do not run the real publish. - If `xflow goal audit --json` fails, do not claim xflow goal is stronger than Codex native goal. - If `xflow launch claims --json` lists a claim under `blocked_claims`, do not use that claim in launch copy. diff --git a/docs/quickstart.md b/docs/quickstart.md index ffe0736..8b3579e 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -7,7 +7,7 @@ Use this path when you want a project to adopt xflow without reading the impleme Use the published package path when `openflow` is available from npm: ```bash -npm install -g openflow +npm install -g @surlymochan/openflow xflow quickstart xflow guide xflow evaluate diff --git a/docs/team-adoption.md b/docs/team-adoption.md index 1607966..85741a0 100644 --- a/docs/team-adoption.md +++ b/docs/team-adoption.md @@ -78,7 +78,7 @@ xflow workflow validate corps --project-root . For consumer projects that only install the CLI, keep a smaller adoption smoke: ```bash -npm install -g openflow +npm install -g @surlymochan/openflow xflow guide xflow init --project-root . xflow doctor --project-root . diff --git a/docs/tooling-matrix.md b/docs/tooling-matrix.md index eec7fd2..4a45281 100644 --- a/docs/tooling-matrix.md +++ b/docs/tooling-matrix.md @@ -9,7 +9,7 @@ The rule is simple: keep the workflow runtime in the project and keep the agent- Every supported tool should be able to run this sequence: ```bash -npm install -g openflow +npm install -g @surlymochan/openflow xflow quickstart xflow guide xflow assess diff --git a/docs/walkthrough.md b/docs/walkthrough.md index df4076c..98b07ef 100644 --- a/docs/walkthrough.md +++ b/docs/walkthrough.md @@ -7,7 +7,7 @@ This walkthrough is the public demo script for evaluating xflow without reading Global package path after publish: ```bash -npm install -g openflow +npm install -g @surlymochan/openflow ``` Source checkout path: diff --git a/package-lock.json b/package-lock.json index c50e587..9586721 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { - "name": "openflow", - "version": "0.1.0", + "name": "@surlymochan/openflow", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "openflow", - "version": "0.1.0", + "name": "@surlymochan/openflow", + "version": "0.2.0", + "license": "MIT", "dependencies": { "ajv": "^8.12.0", "js-yaml": "^4.1.0" @@ -16,6 +17,9 @@ }, "devDependencies": { "playwright": "^1.59.1" + }, + "engines": { + "node": ">=22.5" } }, "node_modules/ajv": { diff --git a/package.json b/package.json index 2659f49..f9f6185 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,45 @@ { - "name": "openflow", - "version": "0.1.0", - "description": "Open agent delivery workflow runtime: atoms + workflow definitions + xflow CLI", + "name": "@surlymochan/openflow", + "version": "0.2.0", + "description": "Executable delivery workflows for AI coding agents: YAML phases, red/green TDD proof gates, handoff state and the xflow CLI.", + "keywords": [ + "ai-agents", + "coding-agents", + "workflow", + "tdd", + "cli", + "codex", + "claude-code", + "cursor", + "openspec", + "developer-tools" + ], + "homepage": "https://github.com/surlymochan/openflow#readme", + "bugs": { + "url": "https://github.com/surlymochan/openflow/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/surlymochan/openflow.git" + }, + "author": "Chao Chen (https://github.com/surlymochan)", + "license": "MIT", "type": "module", "main": "src/index.js", - "license": "MIT", + "bin": { + "xflow": "bin/xflow.js" + }, "files": [ "README.md", "RELEASE_NOTES.md", + "CHANGELOG.md", "atoms/", "bin/", "docs/", "!docs/adoption/evidence/**", "!docs/adoption/trial-packets/**", "!docs/benchmark-evidence/**", + "!docs/assets/**", "prompts/", "schemas/", "scripts/", @@ -27,6 +53,12 @@ "!**/__pycache__/**", "!**/*.pyc" ], + "engines": { + "node": ">=22.5" + }, + "publishConfig": { + "access": "public" + }, "scripts": { "start": "node bin/xflow.js serve", "test": "node scripts/run-tests.mjs", @@ -43,9 +75,6 @@ "workflow:corps": "node bin/xflow.js corps", "atom:list": "node bin/xflow.js atom list" }, - "bin": { - "xflow": "bin/xflow.js" - }, "dependencies": { "ajv": "^8.12.0", "js-yaml": "^4.1.0" diff --git a/src/core/atoms/agent-invoke.js b/src/core/atoms/agent-invoke.js index 6a884ab..81fad26 100644 --- a/src/core/atoms/agent-invoke.js +++ b/src/core/atoms/agent-invoke.js @@ -328,6 +328,12 @@ async function runProc(cmd, args, opts) { }, killAfterMs); }, opts.timeoutMs); } + // An agent CLI may exit without reading stdin (e.g. it fails fast or ignores the prompt pipe). + // Writing to the closed pipe then raises EPIPE asynchronously; the exit handler reports the real result. + child.stdin.on('error', (err) => { + if (err && err.code === 'EPIPE') return; + stderr += `\n[agent_invoke] stdin error: ${err && err.message}`; + }); child.stdin.write(opts.input || ''); child.stdin.end(); }); diff --git a/src/core/competitive-score.js b/src/core/competitive-score.js index 2e09b91..44312c6 100644 --- a/src/core/competitive-score.js +++ b/src/core/competitive-score.js @@ -210,7 +210,7 @@ const DIMENSIONS = [ ['file', 'docs/public-release.md'], ['file', 'docs/public-benchmark.md'], ['file', 'docs/npm-publish-handoff.md'], - ['text', 'docs/install-upgrade.md', /npm install -g openflow/], + ['text', 'docs/install-upgrade.md', /npm install -g @surlymochan\/openflow/], ['text', 'docs/install-upgrade.md', /xflow package preflight --check-registry --check-auth --json/], ['file', 'docs/demo-proof.md'], ['file', 'docs/fixtures/tracker-item.json'], diff --git a/src/core/workflow-loader.js b/src/core/workflow-loader.js index a535bad..b422178 100644 --- a/src/core/workflow-loader.js +++ b/src/core/workflow-loader.js @@ -96,7 +96,7 @@ export function load(workflowPath, { skipRuntimeChecks = false } = {}) { if (!skipRuntimeChecks) { const req = workflow.requires || {}; if (req.agentos_bin) { - checkBinOnPath('xflow', 'as-agentos or xflow CLI'); + checkBinOnPath('xflow', 'xflow CLI on PATH'); } if (req.gh) { checkBinOnPath('gh', 'GitHub CLI (brew install gh)'); diff --git a/test/cli-usability.test.js b/test/cli-usability.test.js index ac8b013..030841a 100644 --- a/test/cli-usability.test.js +++ b/test/cli-usability.test.js @@ -2776,7 +2776,7 @@ phases: assert.match(result.stdout, /Safe Evaluation Command/); assert.match(result.stdout, /Forbidden Until Unblocked/); assert.match(result.stdout, /git clone <repo-url> openflow/); - assert.match(result.stdout, /npm install -g openflow works now/); + assert.match(result.stdout, /npm install -g @surlymochan\/openflow works now/); result = spawnSync('node', ['bin/xflow.js', 'launch', 'copy', '--json'], { cwd: REPO_ROOT, @@ -2792,7 +2792,7 @@ phases: assert.match(payload.install_command, /git clone <repo-url> openflow/); assert.ok(payload.proof_points.some((item) => item.id === 'project_goal_beats_thread_goal')); assert.ok(payload.hold_until_evidence.some((item) => item.id === 'published_package')); - assert.ok(payload.forbidden_phrases.includes('npm install -g openflow works now')); + assert.ok(payload.forbidden_phrases.includes('npm install -g @surlymochan/openflow works now')); assert.ok(payload.evidence_commands.includes('xflow evaluate --json')); assert.ok(payload.evidence_commands.includes('xflow launch claims --json')); assert.ok(payload.evidence_commands.includes('xflow launch copy --json')); diff --git a/test/competitive-readiness.test.js b/test/competitive-readiness.test.js index ab1ab11..e0842f8 100644 --- a/test/competitive-readiness.test.js +++ b/test/competitive-readiness.test.js @@ -79,8 +79,7 @@ describe('competitive readiness benchmark', () => { assert.doesNotMatch(firstRunBlock, /xflow package audit/); assert.match(rootReadme, /actions\/workflows\/ci\.yml\/badge\.svg/); - assert.match(rootReadme, /xflow%20score-100%2F100/); - assert.match(rootReadme, /publish--check-dry--run%20ready/); + assert.match(rootReadme, /docs\/assets\/demo\.gif/); }); test('benchmark names score dimensions, current surfaces, and required next wins', () => { @@ -278,7 +277,7 @@ describe('competitive readiness benchmark', () => { 'xflow package preflight --check-registry --check-auth --json', 'xflow launch audit --pre-publish --strict --json', 'xflow package audit --check-registry --json', - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'xflow init --project-root .', 'xflow goal set "Ship the next verified change" --project-root .', 'xflow doctor --project-root .', @@ -419,7 +418,7 @@ describe('competitive readiness benchmark', () => { for (const phrase of [ 'Universal CLI Contract', - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'Codex CLI / App', 'Claude Code', 'Cursor', @@ -447,7 +446,7 @@ describe('competitive readiness benchmark', () => { 'Local Release', 'Upgrade Checks', 'Publication Readiness', - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'npm install -g .', 'xflow init --project-root .', 'npm run release:local', @@ -480,7 +479,7 @@ describe('competitive readiness benchmark', () => { for (const phrase of [ 'Clean Project Adoption', - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'xflow demo clean', 'xflow workflow validate yolo --project-root .', 'Source Checkout Release Proof', @@ -543,7 +542,7 @@ describe('competitive readiness benchmark', () => { 'xflow launch dossier --output docs/launch-dossier.md', 'xflow goal audit --json', 'npm publish --dry-run --access public', - 'npm view openflow name version --json', + 'npm view @surlymochan/openflow name version --json', 'xflow package preflight --check-registry --check-auth --json', 'xflow launch audit --pre-publish --strict --json', 'xflow package audit --check-registry --json', @@ -702,7 +701,7 @@ describe('competitive readiness benchmark', () => { const adoptionRecord = readFileSync(resolve(REPO_ROOT, 'docs', 'adoption', 'openflow-release-hardening.md'), 'utf8'); for (const phrase of [ - 'npm install -g openflow', + 'npm install -g @surlymochan/openflow', 'xflow init --project-root .', 'xflow doctor --project-root .', 'xflow workflow validate yolo --project-root .',