diff --git a/.gitignore b/.gitignore index 1361896..5644329 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ temp/ # CEWP local runtime state .cewp/ +.cewp-private/ .cewp-worktrees/ # Local env and secrets @@ -53,6 +54,7 @@ env/ # Internal planning and validation docs docs/agents/ +docs/plans/ docs/adr/ CONTEXT.md source-analysis.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0f48d3..7a23270 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,13 +53,13 @@ the full suite, package dry-run, and the relevant clean-install/platform gate. ## Privacy -Do not commit `.cewp/pilots/`, `.cewp/`, `.cewp-private`, credentials, raw prompts, -private logs, or local repository paths. The private `phase-8-to-1.0` roadmap is -not a public package artifact. Before every maintainer commit, the tracking scan -must return no matches: +Do not commit CEWP runtime state, private planning material, credentials, raw +prompts, private logs, local repository paths, or machine-specific artifacts. +Before every maintainer commit, review the tracked and packaged file lists: ```bash -git ls-files | rg "phase-8-to-1\.0|\.cewp-private" +git ls-files +npm pack --dry-run ``` Redacted exports reduce disclosure risk but do not prove arbitrary prose contains diff --git a/README.md b/README.md index 405deaf..0584b91 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,45 @@ # Codex Engineering Workflow Pack -[![npm version](https://img.shields.io/npm/v/@setrathex/codex-engineering-workflow-pack?tag=latest)](https://www.npmjs.com/package/@setrathex/codex-engineering-workflow-pack) +[![CI](https://github.com/SetraTheXX/Codex-Engineering-Workflow-Pack/actions/workflows/ci.yml/badge.svg)](https://github.com/SetraTheXX/Codex-Engineering-Workflow-Pack/actions/workflows/ci.yml) +[![npm](https://img.shields.io/npm/v/@setrathex/codex-engineering-workflow-pack)](https://www.npmjs.com/package/@setrathex/codex-engineering-workflow-pack) +[![Node.js](https://img.shields.io/badge/Node.js-22%20%7C%2024%20%7C%2026-339933?logo=node.js&logoColor=white)](package.json) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -**Long-running goals without blind runs.** +**Controlled Codex execution for work that is too important to run blind.** -CEWP is an unofficial, local-first supervision layer for risky or long-running Codex work. Codex still writes the code. CEWP adds a bounded plan, an isolated worktree, scope and policy gates, deterministic verification, explicit repair limits, an independent reviewer, and a portable receipt. +CEWP is an unofficial, local-first supervision and evidence layer for Codex. It +adds explicit scope, isolated worktrees, bounded retries, deterministic +verification, independent review, recovery controls, and portable receipts while +leaving code generation to Codex. -It is not another chat client, model router, or endless agent loop. It does not attach to a private ChatGPT task, patch the desktop UI, or make a model intrinsically faster. +## Why CEWP -## Native Goal Or CEWP? +Native Codex is the right choice for small, low-risk work. CEWP is designed for +changes where an undetected scope violation, failed verification, uncontrolled +retry, or unverifiable result would be expensive. -Use a native Codex goal alone when the task is small, low risk, easy to inspect, and interruption is unlikely to cost much. +| Need | CEWP control | +| --- | --- | +| Prevent accidental broad edits | Approved file scope and isolated worktree | +| Limit repeated model operations | Explicit operation, repair, and reviewer budgets | +| Recover without losing evidence | Pause, resume, revise, retry, and retained checkpoints | +| Verify outside the model loop | Deterministic local commands and scope inspection | +| Require a second decision | Independent reviewer PASS before finalization | +| Explain what happened | JSON and Markdown receipts with honest usage labels | -Use CEWP when you need one or more of these: +CEWP does not attach to private ChatGPT sessions, scrape interfaces, infer missing +usage, route automatically between models, or merge, push, publish, tag, or +release code. -- approved scope and stopping conditions before execution, -- a hard limit on worker, repair, and reviewer operations, -- safe pause and resume evidence, -- deterministic tests outside the model loop, -- an independent reviewer PASS before finalization, -- a receipt that explains what changed and what remains unknown. +## Quick Start -CEWP currently selects one golden-path pair: execution owner `managed`, backend `codex-exec`. Experimental OpenCode support remains optional and is not part of this path. +Requirements: -## Five-Minute Start +- Node.js 22 or newer +- Git 2.39 or newer +- Codex CLI for managed execution -Requirements: maintained Node.js 22 or newer, Git, and Codex CLI for managed execution. +Install and verify the environment: ```bash npm install -g @setrathex/codex-engineering-workflow-pack @@ -34,136 +47,116 @@ cewp init cewp doctor ``` -Run the credential-free deterministic walkthrough first: +Run the credential-free walkthrough: ```bash cewp demo supervised ``` -In a disposable or reviewed repository, create one bounded checkpoint: +Create a bounded checkpoint in a disposable or reviewed repository: ```bash cewp supervise plan \ - --goal "Update the install example" \ + --goal "Update the installation example" \ --scope README.md \ --verify "git diff --check" \ - --stop "The install example is accurate and the approved check passes" + --stop "The example is accurate and the approved check passes" ``` -Inspect the preview, then explicitly approve it. Managed worker, reviewer, and finalize operations require the advanced local policy; this does not disable scope, verification, budget, or reviewer gates. +Inspect the proposal before enabling managed operations: ```bash cewp policy set full-authority cewp supervise approve --yes cewp supervise execute --yes cewp supervise verify -cewp supervise continue cewp supervise review --yes cewp supervise receipt cewp supervise finalize --yes +cewp policy reset ``` -Nothing in that flow merges, pushes, publishes, tags, or creates a release. +The advanced policy permits requested local operations; it does not disable +scope, budget, verification, ownership, or reviewer gates. -## Codex Plugin +## Safety Model -The thin plugin contributes exactly three conversational skills, a local stdio MCP bridge, and an optional -review-required subagent evidence hook. Every mutating MCP operation delegates to the same CEWP Core used -by the CLI; plugin surfaces do not become execution owners or bypass gates. +CEWP Core is the authority for every completion claim: -From a source checkout: +1. The operator approves bounded scope and stopping conditions. +2. Managed execution uses the selected `codex-exec` backend in an isolated + worktree. +3. CEWP checks changed paths and test-authoring policy. +4. Approved verification runs outside the model loop. +5. An independent reviewer must return PASS. +6. Receipt generation and explicit finalization close the run. -```bash -codex plugin marketplace add /path/to/Codex-Engineering-Workflow-Pack -codex plugin add cewp@cewp-local -codex plugin list -``` - -Then ask Codex to plan a supervised run, run the current checkpoint, or resume an existing run. The plugin -can expose `cewp_create`, `cewp_inspect`, `cewp_approve`, `cewp_continue`, `cewp_retry`, `cewp_revise`, -`cewp_verify`, and `cewp_finalize` when the package-provided `cewp-mcp` command is on `PATH`. It does not -gain direct access to the host's private thread, native goal lifecycle, billing data, or persistent UI. - -For a workflow with a validated host binding, `cewp integration controls --json` shows -preventive, post-execution, imported-observation, and unavailable control classes without promoting -audit-only evidence into enforcement. - -## What CEWP Records - -Phase 9 supervised state lives under `.cewp/supervised-runs//`; graph workflow state lives under `.cewp/workflow-runs//`. Human-readable `progress.md` is generated from canonical state and cannot silently change it. - -CEWP keeps four truth labels separate: - -- `observed`: reported by a supported structured interface, -- `estimated`: a range learned from enough comparable local runs, -- `budgeted`: an approved CEWP-controlled maximum, -- `unknown`: unavailable from the selected host or authentication boundary. - -ChatGPT subscription usage is not converted into a fabricated per-run dollar value. A soft estimate never pretends to be an exact mid-turn token cap. +Unknown host usage remains `unknown`; it is never converted to zero or a +fabricated currency value. Budget or host exhaustion produces a resumable state, +not a false PASS. -## Assurance And Recovery +## Operating Surfaces -The `prototype`, `standard`, and `critical` profiles set bounded operation, repair, elapsed-time, verification, and reserve envelopes. `standard` is the default with one worker and at most two repairs per checkpoint. +- **CLI:** planning, execution, verification, recovery, review, receipts, and + workflow operations. +- **Codex plugin:** three focused conversational skills. +- **Local MCP:** the same Core operations and gates exposed over stdio. +- **Evidence hooks:** optional, reviewable observations that never replace Core + enforcement. -Test authoring is separate from verification: +The stable managed path is `managed` + `codex-exec`. App Server remains +experimental and OpenCode remains optional and outside the golden path. -- `auto`: tests may change inside approved scope, -- `ask`: test changes require `approve --allow-test-authoring --yes`, -- `never`: Core blocks detectable test-file changes, while approved non-test verification still runs. - -Budget or host exhaustion produces a resumable pause, not a fake PASS. Partial files remain isolated and cannot finalize without verification and reviewer PASS. +## Documentation -## Existing Toolkit +Start here: -CEWP still ships ten reusable engineering skills and the earlier Coordinator Mode runtime for compatibility. The supervised path remains the managed `codex-exec` golden path. The workflow runtime adds source-bound compiler requests, approved task graphs, variable workers, result intake, recovery, revisions, and migrations without executing arbitrary prose or adding another backend. +- [Installation](docs/install.md) +- [Supervised workflow](docs/supervised-workflow.md) +- [Native Codex or CEWP?](docs/native-goal-or-cewp.md) +- [Architecture](docs/architecture.md) +- [Security model](docs/security-model.md) +- [Recovery guide](docs/recovery-guide.md) +- [Evidence receipts](docs/evidence-receipts.md) +- [Compatibility contract](docs/stable-compatibility.md) +- [Validation status](docs/validation-status.md) +- [Known limitations](docs/known-limitations.md) + +Reference: + +- [Workflow runtime](docs/workflow-runtime.md) +- [Contract index](docs/contracts.md) +- [Contract extension example](docs/contract-extension-example.md) +- [Adapter contract](docs/adapter-contract.md) +- [Operator policy](docs/operator-policy.md) +- [Migration policy](docs/migration-policy.md) +- [Contributing](CONTRIBUTING.md) +- [Security policy](SECURITY.md) -## Local Pilot Evidence +## Development -Phase 13 pilot records are optional, local, and ignored by Git. They distinguish -maintainer dogfood from genuinely independent participants and never add mandatory -telemetry: +The runtime has no package dependencies. From a source checkout: ```bash -cewp pilot create --pilot-id dogfood-1 --participant maintainer-dogfood --participant-id maintainer-1 -cewp pilot status --json -cewp pilot export dogfood-1 --json +node ./bin/cewp.js --help +node ./bin/cewp.js doctor +npm test +npm run check +npm run pack:dry-run ``` -The infrastructure is implemented, but real external pilot evidence is still -absent. Fixtures and this maintainer's own runs do not satisfy external-user gates; -1.0 is therefore not complete. +CI runs on Windows and Ubuntu with Node.js 22, 24, and 26. -## Documentation - -- [Install Guide](docs/install.md) -- [Supervised Workflow](docs/supervised-workflow.md) -- [Native Goal or CEWP?](docs/native-goal-or-cewp.md) -- [Stable Compatibility Contract](docs/stable-compatibility.md) -- [Stable Contract Reference](docs/contracts.md) -- [Migration Policy](docs/migration-policy.md) -- [Troubleshooting and Recovery](docs/recovery-guide.md) -- [Performance Budgets](docs/performance-budgets.md) -- [1.0 Security Review](docs/security-review-1.0.md) -- [Türkçe Manuel Kabul ve Deneme Rehberi](docs/manual-acceptance.md) -- [External Integration Boundary](docs/external-integration-boundary.md) -- [Evidence Receipts](docs/evidence-receipts.md) -- [Architecture](docs/architecture.md) -- [Contract Extension Example](docs/contract-extension-example.md) -- [Workflow Runtime](docs/workflow-runtime.md) -- [Known Limitations](docs/known-limitations.md) -- [Pilot Kit](docs/pilot-kit.md) -- [Operator Policy](docs/operator-policy.md) -- [Security Model](docs/security-model.md) -- [Coordinator Mode Compatibility](docs/coordinator-mode.md) -- [Adapter Contract](docs/adapter-contract.md) -- [Release Notes](docs/release-notes.md) -- [Contributing](CONTRIBUTING.md) -- [Security Policy](SECURITY.md) +## Project Status -## Status +CEWP is beta software. Stable-core compatibility, migration, recovery, security, +and package lifecycle contracts are implemented. The project is not published as +`1.0.0`; final release validation and explicit human-controlled publication +remain separate steps. -CEWP is beta software. Phase 14 stable-core contracts are available through `cewp compatibility --json`, but external pilot gates and exact clean release matrices are still required before 1.0 can be declared complete. Review the plan, evidence, and receipt before integrating changes. +See [Validation Status](docs/validation-status.md) and +[Release Notes](docs/release-notes.md) for the current evidence boundary. ## License -MIT. See [LICENSE](LICENSE). +[MIT](LICENSE) diff --git a/docs/known-limitations.md b/docs/known-limitations.md index 82ff934..c110fd4 100644 --- a/docs/known-limitations.md +++ b/docs/known-limitations.md @@ -16,7 +16,7 @@ CEWP is beta software. These limits are product boundaries, not hidden roadmap p - Manual is a non-executing handoff adapter. Claude, Gemini, Hermes, and other providers are not implemented. - Supervised worktree cleanup automation is not shipped; rollback is available for owned unverified work, and terminal evidence is retained for deliberate inspection/removal. - CEWP never automatically merges, pushes, publishes, tags, or creates a release. -- The stable-core candidate publishes explicit schema and migration contracts, but the package remains beta and 1.0 eligibility is blocked by real Phase 13 evidence and exact release matrices. -- Phase 13 pilot infrastructure validates local records and thresholds but does not supply real participants. Maintainer dogfood and deterministic fixtures remain excluded; the external-user, repository, repeat-use, case-study, feedback, and contribution gates are still open. +- The stable-core candidate publishes explicit schema and migration contracts, but the package remains beta until exact final-source release validation and an explicit release decision are completed. +- Phase 13 maintainer technical acceptance is complete. Independent user validation was not performed, so CEWP does not claim independent adoption, repeat-user evidence, or external case-study validation. Those remain optional future product feedback rather than a completion gate. Report setup failures, workflow failures, or misleading evidence through the repository issue tracker. Include `cewp doctor --json` output after removing local paths or sensitive values. diff --git a/docs/manual-acceptance.md b/docs/manual-acceptance.md index d6467b9..d8f236f 100644 --- a/docs/manual-acceptance.md +++ b/docs/manual-acceptance.md @@ -5,8 +5,9 @@ denemen içindir. Testleri yeni bir dalda, geçici bir klonda veya gözden çık bir depoda yap. Komutları onaylamadan önce oku; prompt ve test dosyalarına gizli bilgi koyma. -Kendi yaptığın testler `maintainer-dogfood` olarak kaydedilmelidir. Bunlar değerli -teknik kanıttır fakat bağımsız Phase 13 kullanıcı doğrulaması sayılmaz. +Kendi yaptığın testler `maintainer-dogfood` olarak kaydedilmelidir. Doğrulanmış +maintainer kaydı Phase 13 teknik kabul kanıtı sayılır; bağımsız kullanıcı yapılmış +gibi gösterilmez ve bağımsız reviewer PASS kapısı yine zorunludur. ## Şimdi ne yapmalısın? @@ -24,7 +25,7 @@ teknik kanıttır fakat bağımsız Phase 13 kullanıcı doğrulaması sayılmaz CEWP kaynak deposunda PowerShell aç ve kaynak komutunun yolunu tanımla: ```powershell -$cewpRepo = "C:\Users\tunca\Desktop\Projeler Ve Planlar Güncel\CEWP Phase 8" +$cewpRepo = "C:\path\to\Codex-Engineering-Workflow-Pack" $cewp = Join-Path $cewpRepo "bin\cewp.js" Set-Location $cewpRepo node $cewp --help @@ -38,7 +39,7 @@ Beklenen sonuç: - Yardım metni görüntülenir. - Doctor sonucu anlaşılır ve uygulanabilir olur. -- Uyumluluk sonucu, gerçek pilot kanıtları olmadığı için `blocked-pilot-evidence` gösterir. +- Uyumluluk sonucu `phase-13-complete-release-validation-required` gösterir. - Temiz kurulum, kimlik bilgisi gerektirmeyen demo ve kaldırma testi geçer. - İzole plugin testi kurulum, devre dışı bırakma, yükseltme ve kaldırma adımlarını geçer. - Testler yeni bir Codex kimlik doğrulama dosyası oluşturmaz. @@ -202,7 +203,7 @@ içermeyen bağımsız bir katılımcı kimliği kullanmalıdır. - Eksik, eski veya bozuk host kullanım bilgisi sıfır değildir. - Windows testi tek başına Linux release matrisini kanıtlamaz. - Artifact hazırlamak publish, tag, push veya GitHub release yapmak değildir. -- Gerçek Phase 13 kapıları geçmeden `1.0.0` hazır veya tamamlandı denmemelidir. +- Phase 13 teknik kabulü tamamlanmış olsa da son kaynak release matrisi ve açık yayın kararı geçmeden `1.0.0` yayımlandı denmemelidir. ## Test sonunda kaydetmen gerekenler diff --git a/docs/pilot-kit.md b/docs/pilot-kit.md index dd4a07a..c9326c7 100644 --- a/docs/pilot-kit.md +++ b/docs/pilot-kit.md @@ -1,6 +1,8 @@ # Supervised Workflow Pilot Kit -This kit collects real adoption evidence without mandatory telemetry. Do not mark a pilot complete unless a person outside the maintainer's normal environment performs the steps and confirms the result. +This kit collects local adoption evidence without mandatory telemetry. Phase 13 uses +the approved **maintainer technical acceptance** model. Independent user feedback +is optional and must never be fabricated or relabeled as maintainer evidence. ## Local Pilot Ledger @@ -22,18 +24,17 @@ contains no secret. A `repository-attempt` observation must use two different privacy-safe identifiers: `attempt.id` identifies that run, while `attempt.repositoryId` is a stable pseudonym -for the repository. Status counts distinct `repositoryId` values, so repeat attempts -against one repository cannot satisfy the ten-repository gate. Repeat-user evidence -is likewise counted once per privacy-safe participant id. Malformed or incompatible -local records remain visible as invalid warnings and keep status incomplete. - -Maintainer runs, fixtures, demos, and multiple machines used by one person remain -visible but excluded from independent counts. Real pilot completion requires ten -independent repositories, at least three independent participants, five full -reviewed runs, three repeat users without maintainer assistance, three comparable -native-goal studies, three recovery scenarios, budget and host-limit evidence, -three public case studies, onboarding remediation, and external contributor -evidence. The CLI infrastructure cannot manufacture any of those results. +for the repository. Status keeps distinct `repositoryId` values reviewable. +Malformed or incompatible local records remain visible as invalid warnings and +keep status incomplete. + +Technical acceptance requires one repository attempt, one supervised golden path, +one full reviewed run backed by a finalized and integrity-valid receipt, one +measurable benefit observation, one recovered control-flow scenario, and one +guardrail audit with zero unresolved bypasses. Maintainer evidence qualifies for +these gates. Receipt integrity, verification, and independent reviewer PASS remain +fail-closed. Independent user studies remain useful optional product feedback, but +they are not a Phase 13 completion quota. ## Pilot Target @@ -138,4 +139,8 @@ Provide the exact public command, sanitized error, expected behavior, actual beh ## Completion Rule -A Phase 9 external-pilot gate requires at least three independent people to complete the golden path, including at least one real bounded repository task. Deterministic fixtures and maintainer dogfooding are useful engineering evidence but do not count as those people. +`cewp pilot status --json` reports completion only when all six maintainer technical +acceptance gates have qualifying structured evidence and no local pilot record is +invalid. Deterministic fixtures prove the contract but are not runtime evidence. +Independent users, when available, must remain classified `independent-external`; +their absence does not block Phase 13. diff --git a/docs/plans/2026-07-22-phase-13-pilot-evidence-design.md b/docs/plans/2026-07-22-phase-13-pilot-evidence-design.md deleted file mode 100644 index 731c6f9..0000000 --- a/docs/plans/2026-07-22-phase-13-pilot-evidence-design.md +++ /dev/null @@ -1,151 +0,0 @@ -# Phase 13 Pilot Evidence Design - -Status: approved 2026-07-22 - -## Purpose - -Phase 13 must make real pilot evidence reviewable without inventing external -participants or adding mandatory telemetry. CEWP will provide a local, -machine-validated pilot ledger and privacy-safe export path. Maintainer -dogfooding remains useful engineering evidence but never satisfies an -independent-user gate. - -## Chosen Approach - -Pilot records live under the ignored runtime root: - -```text -.cewp/pilots//record.json -``` - -The alternatives were tracked public records by default and a documentation-only -process. Public-by-default records create unnecessary privacy risk. A -documentation-only process cannot enforce counting rules or prove which Phase 13 -gates remain open. A hosted service was rejected because the product is -local-first and does not require telemetry or an account. - -Only an explicit redacted export may leave the local pilot root. Export never -modifies the canonical record and never treats pattern redaction as proof that -arbitrary prose is secret-free. - -## Contracts - -`pilot-record/v1` is the canonical local record. It contains: - -- a stable pilot id and timestamps; -- participant classification: `maintainer-dogfood` or `independent-external`; -- a privacy-safe participant id supplied by the operator; -- repository attempt metadata using language, size, operating-system, test-stack, - input, risk, and mode buckets rather than an absolute path; -- the bounded task and golden-path outcomes; -- optional CEWP workflow run and receipt-integrity references; -- review, repeat-use, recovery, budget-pause, and controlled-host-limit outcomes; -- native-goal comparison evidence where genuinely comparable; -- onboarding failures, remediation, contributor feedback, and case-study status; -- provenance and warnings for evidence that is missing, malformed, or imported. - -`pilot-status/v1` is a derived read model. It reports every Phase 13 gate -separately, its threshold, qualifying evidence ids, exclusions, and remaining -count. It cannot mutate records. - -`pilot-export/v1` is a separately written redacted projection. It excludes raw -prompts, source code, logs, credentials, absolute paths, authentication material, -and unbounded free-form participant data. - -## CLI Surface - -The public commands are: - -```text -cewp pilot create -cewp pilot record -cewp pilot status -cewp pilot export -``` - -`create` writes one validated local skeleton. `record` applies an explicit, -validated observation without silently changing participant classification. -`status` evaluates the complete roadmap gate set and exits nonzero while any -required gate is unmet or invalid. `export` writes a redacted report only after -validation and discloses its redaction policy and counts. - -The first vertical slice is `create` plus `status`: a maintainer record can be -created and inspected, but every independent-user count remains zero. Later -slices add observation intake, linked receipt validation, recovery/comparison -evidence, and export. - -## Counting And Truth Rules - -- Only `independent-external` participants count toward external-participant, - full-reviewed-run, repeat-user, independent-repository, contribution, and case - study gates where the roadmap requires independent evidence. -- Multiple machines, repositories, or records belonging to the maintainer do not - become independent participants. -- A repository attempt is counted once by its stable attempt id. Duplicate ids, - conflicting participant classifications, or invalid timestamps fail closed. -- A full reviewed run requires linked final evidence and reviewer PASS; a test or - manually checked box alone is insufficient. -- Native-goal comparisons require equivalent task-shape metadata. Unavailable - usage remains unknown and is excluded from numeric deltas. -- Recovery, budget exhaustion, and host-limit scenarios are distinct evidence - categories and cannot substitute for one another. -- No status can report Phase 13 complete unless every roadmap gate has qualifying - evidence and no unresolved guardrail bypass is recorded. - -## Data Flow And Security - -The CLI resolves the repository root, then reads or atomically writes only below -`.cewp/pilots`. Pilot ids and export targets are validated against traversal, -absolute paths, reserved names, and symlink escapes. Canonical records use -bounded enums and structured fields instead of arbitrary prose wherever -possible. - -Run references are read-only. When a local workflow receipt is linked, CEWP -checks its run identity and integrity metadata; it does not copy raw evidence -files into the pilot record. Missing or stale references remain explicit and do -not qualify a gate. - -Export reuses the established redaction boundary, writes repository-relative -artifacts, and requires an operator-selected destination outside the ignored -canonical pilot directory only when the destination is safe. No command sends -data over the network. - -## Public Pilot And Contributor Surface - -Tracked repository assets will include: - -- issue forms for setup failure, workflow failure, feature request, and receipt - quality; -- a public case-study template with limitations and usage-truth fields; -- updated pilot instructions for manual, privacy-safe adoption milestones; -- contribution guidance, a concise architecture map, contract-extension - examples, and a private security-reporting path; -- explicit language that ecosystem listing and 1.0 remain gated on real external - evidence. - -Issue forms and templates collect no secrets, raw logs, repository paths, or -mandatory telemetry. - -## Error Handling - -Malformed JSON, unsupported schema versions, unsafe paths, duplicate identities, -contradictory observations, invalid gate claims, or broken receipt links produce -stable actionable errors. Read-only status remains available where possible and -marks affected evidence invalid rather than discarding it or converting it to -zero. Mutations use atomic writes and preserve the last valid record on failure. - -## Testing - -Development follows vertical TDD through the public CLI and Core modules: - -1. maintainer creation and an honestly incomplete status; -2. independent participant and repository-attempt counting; -3. reviewed run, repeat use, comparison, recovery, budget, host-limit, onboarding, - contribution, guardrail, and estimate-calibration gates; -4. duplicate, malformed, stale, traversal, symlink, and contradictory evidence; -5. redacted export and adversarial secret/path content; -6. package, help, documentation, Windows, and Linux contract coverage. - -Fixtures may prove behavior but never satisfy live pilot gates. The final Phase 13 -technical report will therefore distinguish implemented infrastructure from -external evidence still awaiting real users. diff --git a/docs/plans/2026-07-22-phase-13-pilot-evidence-implementation.md b/docs/plans/2026-07-22-phase-13-pilot-evidence-implementation.md deleted file mode 100644 index e284c74..0000000 --- a/docs/plans/2026-07-22-phase-13-pilot-evidence-implementation.md +++ /dev/null @@ -1,186 +0,0 @@ -# Phase 13 Pilot Evidence Implementation Plan - -Status: approved design implementation - -## Constraints - -- Keep canonical pilot data under ignored `.cewp/pilots` runtime state. -- Never count fixtures or `maintainer-dogfood` as independent evidence. -- Do not add telemetry, a hosted service, another provider, or automatic remote - actions. -- Use public CLI behavior for contract tests and Core functions for validation. -- Keep the Phase 13 release gate incomplete until genuine external evidence - proves every threshold. -- Run the private-file tracking scan before every commit. - -## Slice 1: Honest Local Pilot Creation And Status - -Files: - -- `tests/contracts/pilot-record.js` -- `src/pilot/record.js` -- `src/pilot/status.js` -- `src/pilot/cli.js` -- `src/cli/parse.js` -- `src/cli/usage.js` -- `bin/cewp.js` -- `package.json` - -TDD behavior: - -1. `cewp pilot create --participant maintainer-dogfood --participant-id - --json` writes `pilot-record/v1` below `.cewp/pilots`. -2. `cewp pilot status --json` returns `pilot-status/v1`, reports the maintainer - record separately, and leaves every independent-user threshold at zero. -3. Status exits nonzero while Phase 13 gates are unmet but still emits valid JSON. -4. Unsafe ids, missing Git repository roots, duplicate ids, and unsupported - participant classifications fail with actionable errors. - -Focused verification: `npm run test:pilot-record`. - -## Slice 2: Structured Observation Intake And Gate Evaluation - -Files: - -- `tests/contracts/pilot-gates.js` -- `src/pilot/record.js` -- `src/pilot/status.js` -- `src/pilot/cli.js` -- `src/cli/parse.js` -- `package.json` - -TDD behavior: - -1. `cewp pilot record --from --yes --json` - atomically appends a validated observation. -2. Attempts, full reviewed runs, repeat use, native comparisons, recovery, - operational-budget exhaustion, host limits, onboarding remediation, - contribution, guardrail, case-study, and calibration evidence are counted only - when their required structured facts exist. -3. Duplicate attempt ids, participant reclassification, contradictory outcomes, - invalid timestamps, and impossible PASS claims fail closed. -4. Every roadmap gate exposes threshold, qualifying evidence, excluded evidence, - status, and remaining count. - -Focused verification: `npm run test:pilot-gates`. - -## Slice 3: Workflow Receipt Linking - -Files: - -- `tests/contracts/pilot-receipt-link.js` -- `src/pilot/evidence.js` -- `src/pilot/record.js` -- `src/pilot/status.js` -- `package.json` - -TDD behavior: - -1. Repository attempts may link a local workflow run without copying raw evidence. -2. A full reviewed run qualifies only when the run identity, final state, receipt - inventory, required verification, and reviewer PASS agree. -3. Missing, stale, partial, malformed, or integrity-failing receipt links are - warnings and never qualify a gate. -4. Native-only evidence remains explicitly imported and unknown usage never - becomes zero. - -Focused verification: `npm run test:pilot-receipt-link`. - -## Slice 4: Redacted Pilot Export - -Files: - -- `tests/contracts/pilot-export.js` -- `src/pilot/export.js` -- `src/pilot/cli.js` -- `src/cli/parse.js` -- `package.json` - -TDD behavior: - -1. `cewp pilot export [] --json` writes a separate - `pilot-export/v1` JSON/Markdown projection. -2. Canonical records are not modified and export is never implicit. -3. Absolute paths, traversal, secrets, credentials, raw prompts/logs/source, and - active markup are excluded or redacted with class/count disclosure. -4. Unsafe output targets and symlink escapes fail closed. - -Focused verification: `npm run test:pilot-export`. - -## Slice 5: Public Pilot Feedback And Case-Study Surface - -Files: - -- `.github/ISSUE_TEMPLATE/setup-failure.yml` -- `.github/ISSUE_TEMPLATE/workflow-failure.yml` -- `.github/ISSUE_TEMPLATE/feature-request.yml` -- `.github/ISSUE_TEMPLATE/receipt-quality.yml` -- `.github/ISSUE_TEMPLATE/config.yml` -- `docs/case-study-template.md` -- `docs/pilot-kit.md` -- `tests/contracts/pilot-public-surface.js` -- `package.json` - -TDD behavior: - -1. Four issue forms request sanitized reproducible evidence without secrets or - mandatory telemetry. -2. The case-study template covers task shape, plan quality, checkpoints, overhead, - truth labels, estimates, interventions, failures, receipt excerpt, and limits. -3. Pilot documentation explains local records, redacted export, honest dogfood, - and every external gate. - -Focused verification: `npm run test:pilot-public-surface`. - -## Slice 6: Contributor And Security Surface - -Files: - -- `CONTRIBUTING.md` -- `SECURITY.md` -- `docs/architecture.md` -- `docs/contract-extension-example.md` -- `tests/contracts/contributor-surface.js` -- `README.md` -- `package.json` - -TDD behavior: - -1. Contributors have local setup, focused tests, architecture boundaries, - contract-extension examples, issue selection guidance, and privacy rules. -2. Security reports use a private path and public issues explicitly reject - secrets and unredacted vulnerabilities. -3. Architecture retains Core authority, one execution owner/backend, and - provider-neutral contracts. - -Focused verification: `npm run test:contributor-surface`. - -## Slice 7: Phase 13 Release Surface - -Files: - -- `tests/contracts/pilot-release.js` -- `docs/release-notes.md` -- `docs/known-limitations.md` -- `README.md` -- `package.json` -- `plugins/cewp/.codex-plugin/plugin.json` - -TDD behavior: - -1. Prepare `0.13.0-beta.0` locally without publish, tag, or release. -2. Package the reviewed public pilot/contributor files but never `.cewp/pilots`, - private roadmap files, or `.cewp-private`. -3. Release notes distinguish infrastructure readiness, maintainer dogfood, and - missing external evidence. -4. Ecosystem submission remains unperformed until real case studies and golden - path evidence exist. - -Focused verification: `npm run test:pilot-release` and package dry runs. - -## Batch And Commit Boundaries - -Implement and commit in reviewable slices: local ledger/status; observations and -receipt links; redacted export; public pilot/contributor surface; Phase 13 release -preparation. Run focused tests during each red-green-refactor loop, then the full -baseline and privacy scan at the phase checkpoint. diff --git a/docs/provider-profiles-and-terminal-ui.md b/docs/provider-profiles-and-terminal-ui.md deleted file mode 100644 index 7d3ffc8..0000000 --- a/docs/provider-profiles-and-terminal-ui.md +++ /dev/null @@ -1,284 +0,0 @@ -# Provider Profiles And Terminal Orchestration UI - -Status: architecture plan with an initial provider profile read model and experimental OpenCode model override support. CEWP does not implement user-defined full profiles, a desktop model selector, terminal server, WebSocket layer, or new provider adapter. - -CEWP currently supports: -- `codex-exec`: guarded one-shot execution through the Codex CLI. -- `manual`: non-executing human handoff and result intake. -- `opencode`: experimental OpenCode execution MVP. - -OpenCode remains experimental. Local dogfood showed that binary availability is not enough to prove provider auth, model, or subscription readiness. Future provider support must therefore make provider configuration explicit instead of depending on any CLI's default model state. - -## Product Direction - -CEWP is moving toward a local-first engineering workflow runtime that can coordinate agents, terminals, artifacts, timeline, and review gates from a single operator surface. - -The future UI should help an operator: -- select a project and run, -- choose provider profiles per role, -- see worker and reviewer sessions, -- inspect stdout, stderr, last messages, reports, reviews, and events, -- follow safe next actions, -- keep reviewer `Decision: PASS` as the hard finalize boundary. - -This should extend the existing flow: - -```txt -plan -> isolate -> execute -> collect -> review -> finalize -``` - -The UI should not turn CEWP into an automatic merge, push, publish, tag, or release tool. - -## Provider Profile - -A provider profile describes how CEWP can present a provider to operators and future UIs. The initial implementation is a generated read model derived from the adapter registry, capabilities, and availability data. Users do not define full profiles yet. - -Initial beta shape: - -```json -{ - "schemaVersion": "provider-profile/v1", - "id": "opencode", - "provider": "opencode", - "mode": "headless", - "experimental": true, - "command": "opencode", - "model": "provider/model-name", - "binary": "opencode", - "version": "1.15.8", - "binaryReadiness": "installed", - "authReadiness": "unknown", - "supportedFeatures": ["dry-run", "external-command", "last-message"], - "safety": { - "cewpGuardrailsRequired": true, - "allowedFilesRequiredForWorkers": true, - "reviewerPassRequiredForFinalize": true, - "automaticMergePushPublishRelease": false - } -} -``` - -`cewp doctor` prints a compact summary of these generated profiles. This is a beta internal read model, not a committed user config schema. - -### Profile Fields - -`id` -: Stable generated id. Initial default profiles use the provider id. - -`provider` -: Registry provider id such as `codex-exec`, `manual`, or experimental `opencode`. - -`command` -: CLI command or resolved executable path. It must remain explicit when the adapter executes an external binary. - -`model` -: Resolved experimental OpenCode model override, or `null` when no override is configured. The current source order is role config followed by `CEWP_OPENCODE_MODEL`. - -`authReadiness` -: `unknown` when an adapter requires auth but CEWP has not verified provider/model configuration, otherwise `not-applicable`. Binary/version probes never imply auth readiness. - -`binary` -: Required binary name, or `null` for non-executing providers. - -`binaryReadiness` -: `installed`, `missing`, `unknown`, or `not-applicable`, derived from structured adapter availability. - -`mode` -: One of `headless`, `interactive-terminal`, or `manual`. - -`supportedFeatures` -: Read-only feature labels derived from adapter capability metadata. - -`safety` -: The CEWP-owned boundaries that the profile cannot disable. - -## Terminal Session - -A terminal session is a future runtime projection for interactive provider processes. It is not the same as today's one-shot dispatch execution. - -Suggested read model: - -```json -{ - "sessionId": "session-01H...", - "runId": "20260617-034723", - "role": "worker-a", - "providerProfileId": "opencode", - "mode": "interactive-terminal", - "state": "starting", - "process": { - "pid": null, - "startedAt": null, - "endedAt": null, - "exitCode": null, - "timedOut": false - }, - "streams": { - "stdout": "adapter-output/worker-a-stdout.log", - "stderr": "adapter-output/worker-a-stderr.log" - }, - "input": { - "promptPath": "dispatch-prompts/worker-a.md", - "lastUserInputAt": null - }, - "artifacts": { - "lastMessage": "adapter-output/worker-a-last-message.md", - "report": "reports/worker-a-report.md" - }, - "controls": { - "canInterrupt": true, - "canStop": true, - "canSendInput": true - } -} -``` - -This should start as a read-only projection before CEWP owns long-running terminal processes. - -### Interactive Terminal Vs One-Shot Dispatch - -One-shot dispatch: -- receives one prepared prompt, -- runs one process to completion, -- captures logs and result, -- returns `adapter-result/v1`, -- lets CEWP run post-checks. - -Interactive terminal session: -- may stay open across multiple prompts, -- streams stdout and stderr over time, -- needs explicit interrupt and stop controls, -- needs a session lifecycle separate from role/task status, -- must still produce the same reports, last-message artifacts, timeline entries, and guardrail evidence before collect/review/finalize. - -Manual mode: -- does not start a process, -- writes handoff files, -- uses result intake to record human output, -- can still appear in a terminal UI as a checklist or handoff panel. - -## Future UI Layout Needs - -The future operator UI should be built around existing read models before adding process orchestration. - -Suggested layout: -- Project selector: current repo, detected CEWP setup, current policy mode. -- Run selector: `run list` data, latest marker, run state, modified time. -- Provider/model selector: provider profiles grouped by `headless`, `interactive-terminal`, and `manual`. -- Role grid: manager, worker-a, worker-b, reviewer state with assigned profile. -- Terminal grid: interactive sessions or read-only logs per role. -- Timeline panel: `operator-json/v1` timeline events, malformed event warnings, dispatch failures. -- Artifact inspector: typed artifact inventory with preview links for reports, reviews, last messages, logs, manual handoffs, review packets, run metadata, and board metadata. -- Reviewer gate panel: reviewer report, parsed decision, finalize dry-run status, and PASS requirement. -- Next action panel: `run next` recommendation and safe follow-up commands. - -The first UI-compatible API surface should remain file-backed and local. The CLI JSON envelope is already the right starting point: - -```txt -operator-json/v1 -``` - -## Multi-Agent Orchestration - -CEWP should orchestrate multiple agents by keeping role, task, and artifact ownership in CEWP rather than inside provider-specific tools. - -The orchestrator should: -1. Create a run and task board. -2. Assign worker tasks with narrow `allowedFiles` and `forbiddenFiles`. -3. Create isolated worktrees. -4. Resolve a provider profile per role. -5. Generate dispatch prompts. -6. Execute workers as one-shot adapters, interactive terminal sessions, or manual handoffs. -7. Capture stdout, stderr, last messages, reports, and events. -8. Run post-execution scope checks. -9. Collect a review packet. -10. Execute reviewer or manual review. -11. Require reviewer `Decision: PASS` before finalize. -12. Produce a resume packet and next-step guidance. - -Provider selection should be per role. For example: - -```json -{ - "profiles": { - "worker-a": "codex-default", - "worker-b": "opencode-explicit-model", - "reviewer": "manual-reviewer" - } -} -``` - -This is a future shape only. Current `cewp.config.json` still resolves provider ids, not full profiles. - -## Adapter Categories - -Current categories: -- One-shot headless adapter: `codex-exec`. -- Non-executing adapter: `manual`. -- Experimental headless external CLI adapter: `opencode`. - -Future categories: -- Interactive terminal adapter: CEWP starts or attaches to a long-running provider terminal and records a session read model. -- API/model adapter: CEWP calls an API or local model endpoint without a provider CLI. -- Hybrid adapter: CEWP uses a CLI for auth/session management but still normalizes output through `adapter-result/v1`. - -Every category must keep CEWP-owned safety boundaries intact. - -## What Not To Build Yet - -Do not build yet: -- desktop UI implementation, -- WebSocket server, -- long-running terminal process manager, -- Claude Code, Gemini, Hermes, marketplace, or placeholder providers, -- agent marketplace or plugin catalog, -- automatic merge, push, publish, tag, or release, -- weaker guardrails for `allowedFiles`, `forbiddenFiles`, scope checks, or reviewer PASS. - -The next phase should first make profiles explicit and observable through CLI/JSON before adding a UI runtime. - -## Recommended Implementation Steps - -1. Provider profile schema/read model - initial implementation complete - - Current result: `provider-profile/v1` default profiles are generated from registry, capabilities, and availability data and shown by `cewp doctor`. - - Remaining boundary: users cannot define full profiles yet and dispatch behavior is unchanged. - -2. OpenCode model override support - initial implementation complete - - Current result: role config and `CEWP_OPENCODE_MODEL` can select an explicit model without changing the default command. - - Remaining boundary: a full UI model selector and generalized provider profile configuration are still future work. - -3. Explicit auth readiness probes - - Goal: move beyond today's honest `unknown` state only when a provider offers a safe, read-only readiness check. - - Likely files: adapter availability helpers, doctor output, docs. - - Verification: provider-specific fake probes; binary availability must remain independent. - -4. Operator JSON profile projection - - Goal: expose selected provider/profile metadata in `operator-json/v1` without starting sessions. - - Likely files: run inspection serialization, status/resume JSON tests. - - Verification: `run status --json` and `run resume --json` envelope tests. - -5. Terminal session read model - - Goal: define session records and artifact links as read-only files before process control exists. - - Likely files: new runtime projection helper, docs, tests. - - Verification: snapshot tests for session inventory; no process spawning. - -6. Optional UI prototype - - Goal: validate layout and operator flow against static JSON fixtures. - - Likely files: prototype-only docs or ignored prototype area. - - Verification: fixture-driven UI smoke checks if a prototype is created. - -7. Interactive process orchestration - - Goal: only after the read model is stable, add controlled start/stop/interrupt behavior. - - Likely files: future terminal session runtime, adapter contracts, safety tests. - - Verification: fake terminal harness; no real provider dependency. - -## Release Criteria For A Future Profile Phase - -A future profile-focused beta should ship only when: -- provider profile data is visible in doctor or operator JSON, -- binary readiness and auth readiness are separate, -- model overrides are explicit and testable without real provider credentials, -- existing `codex-exec`, `manual`, and experimental `opencode` behavior remains compatible, -- package surface stays clean, -- docs still state that non-implemented providers are not supported, -- reviewer PASS, scope checks, and no automatic publish/tag/release boundaries remain unchanged. diff --git a/docs/release-notes.md b/docs/release-notes.md index e1c68f9..587770d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,21 +2,17 @@ ## Unreleased -### Added - -- Added a maintainer-safe manual acceptance guide covering credential-free preflight, - one bounded real supervised checkpoint, pause/revise/resume, review and receipt, - ownership conflicts, recovery fixtures, and honest pilot classification. +No unreleased changes. -## 0.14.0-beta.0 +## 0.14.0-beta.0 — 2026-07-27 ### Summary Stable-core candidate contracts, recovery/security guidance, CEWP-owned performance -budgets, package lifecycle coverage, and local release-artifact preparation. This -version is prepared locally and is not published, tagged, pushed, or released. -It is deliberately not `1.0.0`: real Phase 13 evidence and exact clean release -matrices remain mandatory blockers. +budgets, package lifecycle coverage, maintainer technical acceptance, and a +professional public repository surface. This beta is deliberately not `1.0.0`; +independent user validation is not claimed and stable publication remains a +separate decision. ### Added @@ -29,13 +25,32 @@ matrices remain mandatory blockers. - Added clean package install/upgrade/downgrade-warning/uninstall capability evidence. - Added local validation and artifact preparation with a hashed manifest; remote publication, tag, push, and GitHub release actions remain human-only and absent. +- Added a maintainer-safe manual acceptance guide covering credential-free + preflight, one bounded real supervised checkpoint, pause/revise/resume, review + and receipt, ownership conflicts, recovery fixtures, and honest pilot + classification. +- Added a repository hygiene contract that rejects private planning paths, CEWP + runtime state, and personal machine identities from the tracked public surface. + +### Changed + +- Closed Phase 13 under the approved maintainer technical acceptance model while + preserving verification, reviewer PASS, scope, ownership, policy reset, and + fail-closed receipt gates. +- Reworked the README and public documentation around product capabilities, + safety boundaries, aggregate validation, and current limitations. +- Removed local acceptance identifiers, private development plans, machine paths, + and an obsolete terminal UI architecture plan from the public package. ### Validation truth -- Windows local contracts can prove the candidate implementation, but do not replace - a clean Linux run of this exact source or the repository release matrix. -- No external participant, repository, repeat-use, case-study, feedback, or - contribution evidence was fabricated. Phase 13 and the 1.0 gate remain open. +- The exact release source passed the repository matrix on Windows and Ubuntu + across Node.js 22, 24, and 26. +- Phase 13 is complete under the approved maintainer technical acceptance model. + Independent external evidence was not collected and is not claimed. +- No external participant, repeat-use, case-study, feedback, or contribution + evidence was fabricated. Phase 13 closure uses maintainer technical acceptance + and does not claim independent user validation. - The security review states the local technical finding boundary; it cannot prove that no undisclosed external vulnerability exists. diff --git a/docs/security-review-1.0.md b/docs/security-review-1.0.md index ac84778..b5f7eff 100644 --- a/docs/security-review-1.0.md +++ b/docs/security-review-1.0.md @@ -1,7 +1,8 @@ # 1.0 Security Review -Status: technical review complete for the candidate surface; 1.0 remains blocked by -Phase 13 and exact release matrices. The release gate is zero open P0/P1 security or +Status: technical review complete for the candidate surface and Phase 13 maintainer +technical acceptance is complete. Exact final-source release matrices and an +explicit release decision remain. The release gate is zero open P0/P1 security or data-loss issues. This document does not assert the state of unreported external bugs. Reviewed boundaries: diff --git a/docs/stable-compatibility.md b/docs/stable-compatibility.md index 8be5e66..b28c91a 100644 --- a/docs/stable-compatibility.md +++ b/docs/stable-compatibility.md @@ -12,4 +12,6 @@ not CEWP verification or reviewer PASS. Missing host usage remains unknown. Package and plugin versions must match. Private desktop attachment, persistent native panels, automatic model routing, and non-Codex provider expansion are not supported. -The command reports `blocked-pilot-evidence` until genuine Phase 13 gates pass. +The command reports `phase-13-complete-release-validation-required`: the approved +maintainer technical acceptance gates passed, while exact final-source release +validation and human-controlled publication remain separate requirements. diff --git a/docs/validation-status.md b/docs/validation-status.md new file mode 100644 index 0000000..401c217 --- /dev/null +++ b/docs/validation-status.md @@ -0,0 +1,33 @@ +# Validation Status + +CEWP publishes validation claims at the product level. Local run identifiers, +machine paths, raw logs, private plans, and participant identities are not part of +the public repository. + +## Current Candidate + +- Package: `0.14.0-beta.0` +- Managed backend: `codex-exec` +- Supported Node.js majors: 22, 24, and 26 +- Repository CI: Windows and Ubuntu +- Technical acceptance: complete +- Independent user validation: not claimed +- Publication status: not released as `1.0.0` + +`cewp compatibility --json` is the canonical machine-readable compatibility +projection. A release still requires validation of the exact final source, +matching package and plugin versions, reviewed package contents, and explicit +human approval for publish, tag, and release actions. + +## Non-Waivable Evidence + +A completed managed run requires approved scope, CEWP verification, independent +reviewer PASS, a complete receipt, released worktree ownership, and an explicit +finalize action. Missing or malformed evidence remains incomplete. + +## Privacy Boundary + +Pilot records and runtime state remain local under ignored CEWP directories. +Public documentation reports aggregate capabilities and limitations only. It does +not publish local paths, raw prompts, source repositories, authentication data, or +private operator logs. diff --git a/package.json b/package.json index 58e2062..a3b4391 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "docs/workflow-runtime.md", "docs/known-limitations.md", "docs/pilot-kit.md", + "docs/validation-status.md", "docs/case-study-template.md", "docs/codex-capability-matrix.md", "docs/external-integration-boundary.md", @@ -52,7 +53,6 @@ "docs/adr/0005-codex-integration-backend.md", "docs/coordinator-mode.md", "docs/adapter-contract.md", - "docs/provider-profiles-and-terminal-ui.md", "docs/operator-policy.md", "docs/security-model.md", "docs/skill-plugin-compatibility.md", @@ -68,7 +68,7 @@ "test": "npm run test:contracts && npm run test:phase12 && npm run test:phase13 && npm run test:phase14 && npm run smoke", "test:phase12": "npm run test:evidence-receipt && npm run test:event-run-verify && npm run test:operator-report && npm run test:run-comparison && npm run test:evidence-redaction", "test:phase13": "npm run test:pilot-record && npm run test:pilot-gates && npm run test:pilot-receipt-link && npm run test:pilot-export && npm run test:pilot-public-surface && npm run test:contributor-surface && npm run test:pilot-release", - "test:phase14": "npm run test:stable-core && npm run test:performance-budget && npm run test:release-preparation && npm run test:package-lifecycle", + "test:phase14": "npm run test:stable-core && npm run test:repository-hygiene && npm run test:performance-budget && npm run test:release-preparation && npm run test:package-lifecycle", "test:contracts": "npm run test:init-install && npm run test:adapter-profile && npm run test:doctor-json && npm run test:operator-json && npm run test:hook-output && npm run test:skill-format && npm run test:ownership-gates && npm run test:fixtures && npm run test:plugin-package && npm run test:supervised-intake && npm run test:supervised-proposal && npm run test:supervised-controls && npm run test:supervised-execution && npm run test:supervised-review && npm run test:supervised-failure && npm run test:supervised-linear-resume && npm run test:supervised-demo && npm run test:workflow-definition && npm run test:workflow-compiler && npm run test:workflow-proposal && npm run test:workflow-scheduler && npm run test:workflow-worker-matrix && npm run test:workflow-result && npm run test:workflow-failure-result && npm run test:workflow-state-machine && npm run test:workflow-interventions && npm run test:workflow-failure-matrix && npm run test:workflow-budget && npm run test:workflow-progress && npm run test:workflow-review && npm run test:workflow-checkpoint-review && npm run test:workflow-lifecycle && npm run test:workflow-revision && npm run test:workflow-migration && npm run test:workflow-templates && npm run test:workflow-docs && npm run test:workflow-release && npm run test:integration-capabilities && npm run test:integration-binding && npm run test:integration-effort-policy && npm run test:integration-hook-evidence && npm run test:integration-mcp && npm run test:integration-observation && npm run test:native-goal-events", "test:init-install": "node tests/contracts/init-install.js", "test:adapter-profile": "node tests/contracts/adapter-profile.js", @@ -127,6 +127,7 @@ "test:contributor-surface": "node tests/contracts/contributor-surface.js", "test:pilot-release": "node tests/contracts/pilot-release.js", "test:stable-core": "node tests/contracts/stable-core.js", + "test:repository-hygiene": "node tests/contracts/repository-hygiene.js", "test:release-preparation": "node tests/contracts/release-preparation.js", "test:performance-budget": "node tests/contracts/performance-budget.js", "test:package-lifecycle": "node tests/capabilities/package-lifecycle.js", @@ -143,7 +144,7 @@ "check:mcp": "node --check ./bin/cewp-mcp.js && node --check ./src/mcp/server.js && node --check ./src/mcp/tools.js && node --check ./tests/contracts/integration-mcp.js", "check:evidence": "node --check ./src/evidence/receipt.js && node --check ./src/evidence/events.js && node --check ./src/evidence/report.js && node --check ./src/evidence/compare.js && node --check ./src/evidence/redaction.js && node --check ./src/evidence/usage.js && node --check ./src/evidence/verify.js && node --check ./src/run/verify.js && node --check ./tests/contracts/evidence-receipt.js && node --check ./tests/contracts/event-run-verify.js && node --check ./tests/contracts/operator-report.js && node --check ./tests/contracts/run-comparison.js && node --check ./tests/contracts/evidence-redaction.js", "check:pilot": "node --check ./src/pilot/record.js && node --check ./src/pilot/observation.js && node --check ./src/pilot/evidence.js && node --check ./src/pilot/status.js && node --check ./src/pilot/export.js && node --check ./src/pilot/cli.js && node --check ./tests/contracts/pilot-record.js && node --check ./tests/contracts/pilot-gates.js && node --check ./tests/contracts/pilot-receipt-link.js && node --check ./tests/contracts/pilot-export.js && node --check ./tests/contracts/pilot-public-surface.js && node --check ./tests/contracts/contributor-surface.js && node --check ./tests/contracts/pilot-release.js", - "check:phase14": "node --check ./src/compatibility/contract.js && node --check ./src/performance/budgets.js && node --check ./scripts/prepare-release.js && node --check ./tests/contracts/stable-core.js && node --check ./tests/contracts/performance-budget.js && node --check ./tests/contracts/release-preparation.js && node --check ./tests/capabilities/package-lifecycle.js", + "check:phase14": "node --check ./src/compatibility/contract.js && node --check ./src/performance/budgets.js && node --check ./scripts/prepare-release.js && node --check ./tests/contracts/stable-core.js && node --check ./tests/contracts/repository-hygiene.js && node --check ./tests/contracts/performance-budget.js && node --check ./tests/contracts/release-preparation.js && node --check ./tests/capabilities/package-lifecycle.js", "check": "npm run check:syntax && npm run check:workflow-syntax && npm run check:mcp && npm run check:evidence && npm run check:pilot && npm run check:phase14 && npm test", "pack:dry-run": "npm pack --dry-run" }, diff --git a/src/compatibility/contract.js b/src/compatibility/contract.js index 4f9dbfc..1b3ecc8 100644 --- a/src/compatibility/contract.js +++ b/src/compatibility/contract.js @@ -39,8 +39,13 @@ function buildCompatibilityContract() { packageVersion: packageVersion(), release: { line: "1.x candidate", - status: "blocked-pilot-evidence", - reason: "Phase 13 requires genuine independent pilot evidence before 1.0.", + status: "phase-13-complete-release-validation-required", + reason: "Phase 13 maintainer technical acceptance is complete; exact release validation and an explicit release decision remain.", + phase13: { + status: "complete", + validationModel: "maintainer-technical-acceptance", + independentUserValidationRequired: false, + }, }, runtime: { node: { majors: [22, 24, 26], minimum: "22.0.0", evidence: "repository CI matrix" }, diff --git a/src/pilot/evidence.js b/src/pilot/evidence.js index 86b7c05..ebcbc9f 100644 --- a/src/pilot/evidence.js +++ b/src/pilot/evidence.js @@ -5,12 +5,85 @@ const fs = require("node:fs"); const path = require("node:path"); const { verifyWorkflowRun } = require("../evidence/verify"); const { loadWorkflowRun } = require("../workflow/state"); +const { findSupervisedRun } = require("../supervise/state"); +const { validateOwnershipRecord } = require("../run/ownership"); function sha256(filePath) { return `sha256:${crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex")}`; } -function inspectReviewedRunEvidence(repoRoot, workflowRunId) { +function inspectSupervisedRunEvidence(repoRoot, supervisedRunId) { + let found; + try { + found = findSupervisedRun({ repoRoot, runId: supervisedRunId }); + } catch (error) { + return { + status: "excluded", + reason: `supervised run is unavailable: ${error.message}`, + runKind: "supervised", + supervisedRunId, + verification: { schemaVersion: "supervised-verification/v1", status: "failed", issues: [{ code: "run-unavailable", message: error.message }] }, + receipt: null, + reviewer: { decision: null, independentPass: false }, + rawEvidenceCopied: false, + }; + } + const receiptPath = path.join(found.runRoot, "receipt.json"); + const ownershipPath = path.join(found.runRoot, "ownership.json"); + let receiptValue = null; + let ownership = null; + try { + receiptValue = JSON.parse(fs.readFileSync(receiptPath, "utf8")); + } catch {} + try { + ownership = validateOwnershipRecord(JSON.parse(fs.readFileSync(ownershipPath, "utf8"))); + } catch {} + const tasks = Array.isArray(found.run.tasks) ? found.run.tasks : []; + const verificationPassed = tasks.length > 0 && tasks.every((task) => ( + task.status === "completed" + && task.verification?.latest?.status === "pass" + && task.verification?.scope?.status === "pass" + && (task.evidence || []).some((entry) => entry.type === "verification") + )); + const independentPass = found.run.reviewer?.independent === true + && found.run.reviewer?.status === "passed" + && found.run.reviewer?.decision === "PASS" + && tasks.every((task) => (task.evidence || []).some((entry) => entry.type === "independent-review" && entry.decision === "PASS")); + let reason = null; + if (found.run.status !== "completed") reason = `supervised run is not completed (status ${found.run.status})`; + else if (found.run.receipt?.status !== "finalized") reason = "supervised run receipt is not finalized"; + else if (!receiptValue || receiptValue.schemaVersion !== "supervised-receipt/v1-beta" || receiptValue.runId !== supervisedRunId || receiptValue.finalized !== true) reason = "supervised receipt is missing, incomplete, or incompatible"; + else if (!verificationPassed) reason = "supervised run verification or scope evidence failed"; + else if (!independentPass) reason = "supervised run lacks an independent reviewer PASS"; + else if (ownership?.runId !== supervisedRunId || ownership?.status !== "released") reason = "supervised execution ownership is invalid or not released"; + return { + status: reason ? "excluded" : "qualified", + reason, + runKind: "supervised", + supervisedRunId, + verification: { + schemaVersion: "supervised-verification/v1", + status: verificationPassed ? "passed" : "failed", + issues: verificationPassed ? [] : [{ code: "supervised-verification-failed", message: "Verification, scope, or task evidence did not pass." }], + }, + receipt: receiptValue ? { + schemaVersion: receiptValue.schemaVersion || null, + generatedAt: receiptValue.generatedAt || null, + completeness: receiptValue.finalized === true ? "complete" : "incomplete", + integrityClaim: "finalization-gated-local-receipt", + sha256: sha256(receiptPath), + } : null, + reviewer: { decision: found.run.reviewer?.decision || null, independentPass }, + ownership: { status: ownership?.status || "unknown" }, + rawEvidenceCopied: false, + }; +} + +function inspectReviewedRunEvidence(repoRoot, runReference) { + if (runReference && typeof runReference === "object" && runReference.supervisedRunId) { + return inspectSupervisedRunEvidence(repoRoot, runReference.supervisedRunId); + } + const workflowRunId = typeof runReference === "string" ? runReference : runReference?.workflowRunId; let found; try { found = loadWorkflowRun(repoRoot, workflowRunId); @@ -64,6 +137,7 @@ function inspectReviewedRunEvidence(repoRoot, workflowRunId) { return { status: reason ? "excluded" : "qualified", reason, + runKind: "workflow", workflowRunId, verification: { schemaVersion: verification.schemaVersion, diff --git a/src/pilot/observation.js b/src/pilot/observation.js index 91a2607..ad04389 100644 --- a/src/pilot/observation.js +++ b/src/pilot/observation.js @@ -260,8 +260,15 @@ function validateGuardrailAudit(value) { function validateReviewedRun(value) { const input = requireObject(value, "full-reviewed-run"); + const hasWorkflow = typeof input.workflowRunId === "string"; + const hasSupervised = typeof input.supervisedRunId === "string"; + if (hasWorkflow === hasSupervised) { + throw new Error("full-reviewed-run requires exactly one workflowRunId or supervisedRunId."); + } return { - workflowRunId: requireSafeId(input.workflowRunId, "full-reviewed-run workflowRunId"), + ...(hasWorkflow + ? { workflowRunId: requireSafeId(input.workflowRunId, "full-reviewed-run workflowRunId") } + : { supervisedRunId: requireSafeId(input.supervisedRunId, "full-reviewed-run supervisedRunId") }), }; } @@ -322,7 +329,9 @@ function observationEvidenceIdentity(observation) { if (observation.type === "recovery") return `recovery:${observation.data.recovery.id}`; if (observation.type === "public-case-study") return `public-case-study:${observation.data.caseStudy.id}`; if (observation.type === "onboarding-remediation") return `onboarding-remediation:${observation.data.failure.code}`; - if (observation.type === "full-reviewed-run") return `full-reviewed-run:${observation.data.run.workflowRunId}`; + if (observation.type === "full-reviewed-run") { + return `full-reviewed-run:${observation.data.run.workflowRunId || observation.data.run.supervisedRunId}`; + } return `${observation.type}:${observation.id}`; } @@ -357,11 +366,11 @@ function recordPilotObservation(options = {}) { if (duplicateIdentity) { throw new Error(`Pilot evidence identity already exists: ${duplicateIdentity}.`); } - const independentParticipant = found.record.participant.classification === "independent-external"; const evidence = observation.type === "full-reviewed-run" - ? inspectReviewedRunEvidence(repoRoot, observation.data.run.workflowRunId) + ? inspectReviewedRunEvidence(repoRoot, observation.data.run) : null; - const eligible = independentParticipant && (!evidence || evidence.status === "qualified"); + const eligible = !evidence || evidence.status === "qualified"; + const maintainerEvidence = found.record.participant.classification === "maintainer-dogfood"; const stored = { ...observation, recordedAt: (options.now || new Date()).toISOString(), @@ -370,13 +379,13 @@ function recordPilotObservation(options = {}) { qualification: { eligible, classification: eligible - ? "independent-evidence" - : independentParticipant ? "excluded-evidence" : "maintainer-dogfood", + ? maintainerEvidence ? "maintainer-technical-evidence" : "independent-evidence" + : "excluded-evidence", reason: eligible - ? "validated structured observation from an independent-external pilot record" - : independentParticipant - ? evidence.reason - : "maintainer dogfood never counts as independent Phase 13 evidence", + ? maintainerEvidence + ? "validated structured maintainer observation for Phase 13 technical acceptance" + : "validated structured observation from an independent-external pilot record" + : evidence.reason, }, }; const record = { diff --git a/src/pilot/status.js b/src/pilot/status.js index b171c9b..462b017 100644 --- a/src/pilot/status.js +++ b/src/pilot/status.js @@ -6,20 +6,11 @@ const { PILOT_RECORD_SCHEMA_VERSION } = require("./record"); const PILOT_STATUS_SCHEMA_VERSION = "pilot-status/v1"; const COUNT_GATES = Object.freeze([ - { id: "independent-repository-attempts", threshold: 10, observationType: "repository-attempt" }, - { id: "independent-external-participants", threshold: 3, source: "participants" }, - { id: "real-bounded-external-repository-task", threshold: 1, observationType: "bounded-external-task" }, - { id: "full-reviewed-runs", threshold: 5, observationType: "full-reviewed-run" }, - { id: "repeat-users-without-maintainer-assistance", threshold: 3, observationType: "repeat-user" }, - { id: "comparable-native-goal-runs", threshold: 3, observationType: "native-goal-comparison" }, + { id: "maintainer-repository-attempt", threshold: 1, observationType: "repository-attempt" }, + { id: "supervised-golden-path", threshold: 1, observationType: "golden-path-complete" }, + { id: "full-reviewed-runs", threshold: 1, observationType: "full-reviewed-run" }, { id: "measurable-cewp-benefit", threshold: 1, observationType: "measurable-benefit" }, - { id: "recovered-pause-or-failure-scenarios", threshold: 3, observationType: "recovery" }, - { id: "operational-budget-exhaustion", threshold: 1, observationType: "operational-budget-exhaustion" }, - { id: "controlled-host-limit", threshold: 1, observationType: "controlled-host-limit" }, - { id: "top-onboarding-failures-remediated", threshold: 5, observationType: "onboarding-remediation" }, - { id: "external-contribution-or-substantive-issue", threshold: 1, observationType: "external-contribution" }, - { id: "public-case-studies", threshold: 3, observationType: "public-case-study" }, - { id: "usage-estimate-calibration-reported", threshold: 1, observationType: "estimate-calibration-report" }, + { id: "recovered-control-flow", threshold: 1, observationType: "recovery" }, { id: "guardrail-audit-with-no-unresolved-bypass", threshold: 1, observationType: "guardrail-audit-pass" }, ]); @@ -67,7 +58,7 @@ function derivePilotStatus(repoRoot) { ))) .map((record) => record.participant.id)); const evidenceByType = new Map(); - for (const record of externalRecords) { + for (const record of records) { for (const observation of record.observations || []) { if (!observation || observation.qualification?.eligible !== true || typeof observation.type !== "string") continue; if (!evidenceByType.has(observation.type)) evidenceByType.set(observation.type, []); @@ -107,6 +98,8 @@ function derivePilotStatus(repoRoot) { }); return { schemaVersion: PILOT_STATUS_SCHEMA_VERSION, + validationModel: "maintainer-technical-acceptance", + independentUserValidationRequired: false, complete: inspected.invalid.length === 0 && gates.every((gate) => gate.status === "met"), records: { total: records.length + inspected.invalid.length, valid: records.length, invalid: inspected.invalid.length }, participants: { @@ -114,13 +107,7 @@ function derivePilotStatus(repoRoot) { independentExternal: externalParticipantIds.size, }, gates, - exclusions: records - .filter((record) => record.participant.classification !== "independent-external") - .map((record) => ({ - pilotId: record.pilotId, - classification: record.participant.classification, - reason: "maintainer dogfood never counts as independent Phase 13 evidence", - })), + exclusions: [], warnings: [ ...inspected.invalid.map((record) => ({ code: "pilot-record-invalid", pilotId: record.pilotId, reason: record.reason })), ...gates diff --git a/tests/capabilities/clean-install.js b/tests/capabilities/clean-install.js index 9914f36..a6ab238 100644 --- a/tests/capabilities/clean-install.js +++ b/tests/capabilities/clean-install.js @@ -56,7 +56,7 @@ function runCleanInstall() { assert(fs.existsSync(cli), "installed package exposes the CLI"); assert(fs.existsSync(path.join(installedRoot, "plugins", "cewp", ".codex-plugin", "plugin.json")), "installed package includes the plugin"); assert(fs.existsSync(path.join(installedRoot, "docs", "supervised-workflow.md")), "installed package includes supervised docs"); - assert(!fs.existsSync(path.join(installedRoot, "docs", "phase-8-to-1.0-implementation-plan.md")), "private roadmap is absent from the installed package"); + assert(!fs.existsSync(path.join(installedRoot, "docs", "plans")), "development plans are absent from the installed package"); assert(!fs.existsSync(path.join(installedRoot, ".cewp-private")), "private capability evidence is absent from the installed package"); run(process.execPath, [cli, "--help"], { cwd: target, env }); diff --git a/tests/contracts/contributor-surface.js b/tests/contracts/contributor-surface.js index 1fad337..5a30a62 100644 --- a/tests/contracts/contributor-surface.js +++ b/tests/contracts/contributor-surface.js @@ -17,13 +17,13 @@ function runContract() { "npm run check", "git diff --check", "good first issue", - "phase-8-to-1.0", - ".cewp-private", + "npm pack --dry-run", + "private planning material", "provider expansion", ]) { assert(contributing.toLowerCase().includes(requirement.toLowerCase()), `contribution guide includes ${requirement}`); } - assert(/do not commit.*\.cewp\/pilots/is.test(contributing), "contribution guide keeps pilot records private"); + assert(/do not commit.*runtime state/is.test(contributing), "contribution guide keeps runtime records private"); assert(/red.*green.*refactor/is.test(contributing), "contribution guide documents the TDD loop"); const security = read("SECURITY.md"); diff --git a/tests/contracts/pilot-gates.js b/tests/contracts/pilot-gates.js index b973d82..0d97295 100644 --- a/tests/contracts/pilot-gates.js +++ b/tests/contracts/pilot-gates.js @@ -109,15 +109,13 @@ function runContract() { const dogfood = recordObservation(repoRoot, "dogfood-1", "dogfood-attempt.json"); assert(dogfood.status === 0, `dogfood observation is recorded: ${dogfood.stderr}`); const dogfoodOutput = JSON.parse(dogfood.stdout).data; - assert(dogfoodOutput.observation.qualification.eligible === false, "maintainer observation remains ineligible"); + assert(dogfoodOutput.observation.qualification.eligible === true, "maintainer observation qualifies for technical acceptance"); const statusResult = runNode(cewpCli, ["pilot", "status", "--json"], repoRoot); const status = JSON.parse(statusResult.stdout).data; - const repositoryGate = status.gates.find((gate) => gate.id === "independent-repository-attempts"); - const participantGate = status.gates.find((gate) => gate.id === "independent-external-participants"); - assert(repositoryGate.observed === 1, "only the independent repository attempt counts"); - assert(repositoryGate.qualifyingEvidence.length === 1 && repositoryGate.qualifyingEvidence[0] === "repo-attempt-1", "privacy-safe repository identity makes qualifying evidence reviewable"); - assert(participantGate.observed === 0, "an enrolled external participant does not count before golden-path completion"); + const repositoryGate = status.gates.find((gate) => gate.id === "maintainer-repository-attempt"); + assert(repositoryGate.observed === 2, "maintainer and external repository attempts remain honestly classified and count as technical evidence"); + assert(repositoryGate.qualifyingEvidence.includes("repo-attempt-dogfood"), "privacy-safe maintainer repository identity makes evidence reviewable"); createPilot(repoRoot, "external-2", "independent-external", "person-2"); createPilot(repoRoot, "external-3", "independent-external", "person-3"); @@ -131,16 +129,15 @@ function runContract() { assert(recorded.status === 0, `${pilotId} golden path is recorded: ${recorded.stderr}`); } const afterGolden = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; - const completedParticipants = afterGolden.gates.find((gate) => gate.id === "independent-external-participants"); - assert(completedParticipants.observed === 3 && completedParticipants.status === "met", "three distinct completed external participants satisfy the deferred gate"); - assert(afterGolden.complete === false, "participant completion alone cannot complete Phase 13"); + const goldenGate = afterGolden.gates.find((gate) => gate.id === "supervised-golden-path"); + assert(goldenGate.observed === 3 && goldenGate.status === "met", "a supervised golden path satisfies its technical gate"); + assert(afterGolden.complete === false, "golden-path completion alone cannot complete technical acceptance"); writeJson(path.join(repoRoot, "bounded-task.json"), boundedExternalTask("bounded-task-1")); const bounded = recordObservation(repoRoot, "external-1", "bounded-task.json"); assert(bounded.status === 0, `bounded external task is recorded: ${bounded.stderr}`); const afterBounded = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; - const boundedGate = afterBounded.gates.find((gate) => gate.id === "real-bounded-external-repository-task"); - assert(boundedGate.observed === 1 && boundedGate.status === "met", "one real bounded external task satisfies its distinct gate"); + assert(afterBounded.complete === false, "legacy external-task evidence remains recordable without becoming a completion quota"); for (let index = 2; index <= 10; index += 1) { recordInline(repoRoot, `external-${((index - 1) % 3) + 1}`, repositoryAttempt(`external-attempt-${index}`, `repo-attempt-${index}`)); @@ -214,17 +211,10 @@ function runContract() { const broadStatus = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; const expectedMet = [ - "independent-repository-attempts", - "repeat-users-without-maintainer-assistance", - "comparable-native-goal-runs", + "maintainer-repository-attempt", + "supervised-golden-path", "measurable-cewp-benefit", - "recovered-pause-or-failure-scenarios", - "operational-budget-exhaustion", - "controlled-host-limit", - "top-onboarding-failures-remediated", - "external-contribution-or-substantive-issue", - "public-case-studies", - "usage-estimate-calibration-reported", + "recovered-control-flow", "guardrail-audit-with-no-unresolved-bypass", ]; for (const gateId of expectedMet) { @@ -243,8 +233,7 @@ function runContract() { withoutMaintainerAssistance: true, }, 59)); const afterRepeatedSameParticipant = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; - const repeatGate = afterRepeatedSameParticipant.gates.find((gate) => gate.id === "repeat-users-without-maintainer-assistance"); - assert(repeatGate.observed === 3, "repeat-user gate counts distinct participant ids rather than repeat observations"); + assert(afterRepeatedSameParticipant.complete === false, "legacy repeat-use evidence cannot bypass the reviewed-run gate"); writeJson(path.join(repoRoot, "duplicate-attempt.json"), repositoryAttempt("duplicate-attempt-observation", "repo-attempt-1")); const duplicateAttempt = recordObservation(repoRoot, "external-2", "duplicate-attempt.json"); diff --git a/tests/contracts/pilot-public-surface.js b/tests/contracts/pilot-public-surface.js index 759b95e..494543e 100644 --- a/tests/contracts/pilot-public-surface.js +++ b/tests/contracts/pilot-public-surface.js @@ -51,9 +51,10 @@ function runContract() { assert(pilotKit.includes(command), `pilot kit documents ${command}`); } assert(pilotKit.includes(".cewp/pilots/"), "pilot kit documents ignored canonical storage"); - assert(/ten\s+independent repositories/.test(pilotKit), "pilot kit documents the repository threshold"); - assert(/five full\s+reviewed runs/.test(pilotKit), "pilot kit documents the reviewed-run threshold"); - assert(/three repeat users/.test(pilotKit), "pilot kit documents the repeat-use threshold"); + assert(/maintainer technical acceptance/i.test(pilotKit), "pilot kit names the approved validation model"); + assert(/one repository attempt/i.test(pilotKit), "pilot kit documents the repository-attempt threshold"); + assert(/one full reviewed run/i.test(pilotKit), "pilot kit documents the reviewed-run threshold"); + assert(/independent user.*optional/i.test(pilotKit), "pilot kit keeps independent feedback optional without fabricating it"); } try { diff --git a/tests/contracts/pilot-receipt-link.js b/tests/contracts/pilot-receipt-link.js index f548eb9..129af54 100644 --- a/tests/contracts/pilot-receipt-link.js +++ b/tests/contracts/pilot-receipt-link.js @@ -22,8 +22,8 @@ function createPilot(repoRoot, pilotId) { const result = runNode(cewpCli, [ "pilot", "create", "--pilot-id", pilotId, - "--participant", "independent-external", - "--participant-id", `person-${pilotId.slice(-1)}`, + "--participant", "maintainer-dogfood", + "--participant-id", `maintainer-${pilotId.slice(-1)}`, "--json", ], repoRoot); assert(result.status === 0, `pilot ${pilotId} is created: ${result.stderr}`); @@ -97,6 +97,53 @@ function reviewedObservation(observationId, workflowRunId) { }; } +function supervisedReviewedObservation(observationId, supervisedRunId) { + return { + schemaVersion: "pilot-observation/v1", + observationId, + type: "full-reviewed-run", + observedAt: "2026-07-22T07:30:00.000Z", + run: { supervisedRunId }, + }; +} + +function completeSupervisedRun(repoRoot, runId) { + const runRoot = path.join(repoRoot, ".cewp", "supervised-runs", runId); + writeJson(path.join(runRoot, "run.json"), { + schemaVersion: "supervised-run/v1", + runId, + status: "completed", + reviewer: { independent: true, status: "passed", decision: "PASS" }, + receipt: { status: "finalized" }, + tasks: [{ + id: "checkpoint-1", + status: "completed", + verification: { latest: { status: "pass" }, scope: { status: "pass" } }, + evidence: [ + { type: "verification", verificationIds: ["targeted-1"], scopeStatus: "pass" }, + { type: "independent-review", decision: "PASS", path: "review/reviewer-report.md" }, + ], + }], + }); + writeJson(path.join(runRoot, "receipt.json"), { + schemaVersion: "supervised-receipt/v1-beta", + runId, + status: "completed", + finalized: true, + reviewer: { independent: true, status: "passed", decision: "PASS" }, + }); + writeJson(path.join(runRoot, "ownership.json"), { + schemaVersion: "execution-ownership/v1", + runId, + taskId: "checkpoint-1", + checkpointId: "checkpoint-1", + owner: "managed", + backend: "codex-exec", + status: "released", + worktree: { id: `${runId}-checkpoint-1`, path: "worktrees/checkpoint-1" }, + }); +} + function recordObservation(repoRoot, pilotId, observation) { const fileName = `${observation.observationId}.json`; writeJson(path.join(repoRoot, fileName), observation); @@ -127,7 +174,7 @@ function runContract() { const status = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; const reviewedGate = status.gates.find((gate) => gate.id === "full-reviewed-runs"); - assert(reviewedGate.observed === 1 && reviewedGate.remaining === 4, "only the complete reviewed run counts"); + assert(reviewedGate.observed === 1 && reviewedGate.remaining === 0, "only the complete reviewed run counts and it satisfies the technical gate"); const tampered = completeRun(repoRoot, 2); fs.appendFileSync(path.join(repoRoot, tampered.paths.targeted), "tampered\n"); @@ -144,7 +191,16 @@ function runContract() { } const completedStatus = JSON.parse(runNode(cewpCli, ["pilot", "status", "--json"], repoRoot).stdout).data; const completedGate = completedStatus.gates.find((gate) => gate.id === "full-reviewed-runs"); - assert(completedGate.observed === 5 && completedGate.status === "met", "five distinct verified reviewed runs satisfy the roadmap threshold"); + assert(completedGate.observed === 5 && completedGate.threshold === 1 && completedGate.status === "met", "one verified reviewed run satisfies the technical acceptance threshold while all evidence remains visible"); + + createPilot(repoRoot, "supervised-1"); + completeSupervisedRun(repoRoot, "20260722-073000"); + const supervisedLink = recordObservation(repoRoot, "supervised-1", supervisedReviewedObservation("supervised-reviewed-1", "20260722-073000")); + assert(supervisedLink.status === 0, `finalized supervised run is linkable: ${supervisedLink.stderr}`); + const supervisedEvidence = JSON.parse(supervisedLink.stdout).data.observation; + assert(supervisedEvidence.qualification.eligible === true, "finalized supervised receipt qualifies"); + assert(supervisedEvidence.evidence.runKind === "supervised", "linked evidence identifies the supervised run kind"); + assert(supervisedEvidence.evidence.reviewer.independentPass === true, "supervised link preserves independent reviewer PASS"); } finally { cleanupRepo(repoRoot); } diff --git a/tests/contracts/pilot-record.js b/tests/contracts/pilot-record.js index b87340e..4835a45 100644 --- a/tests/contracts/pilot-record.js +++ b/tests/contracts/pilot-record.js @@ -34,16 +34,18 @@ function runContract() { const status = JSON.parse(statusResult.stdout); assert(status.command === "pilot.status", "pilot status has a stable command envelope"); assert(status.data.schemaVersion === "pilot-status/v1", "pilot status is versioned"); - assert(status.data.complete === false, "maintainer dogfood cannot complete Phase 13"); + assert(status.data.complete === false, "an empty maintainer record cannot complete technical acceptance"); + assert(status.data.validationModel === "maintainer-technical-acceptance", "status names the approved Phase 13 validation model"); + assert(status.data.independentUserValidationRequired === false, "independent user quotas are not a Phase 13 completion gate"); assert(status.data.participants.maintainerDogfood === 1, "maintainer dogfood is visible"); assert(status.data.participants.independentExternal === 0, "maintainer dogfood is excluded from independent participants"); - const externalGate = status.data.gates.find((gate) => gate.id === "independent-external-participants"); - const repositoryGate = status.data.gates.find((gate) => gate.id === "independent-repository-attempts"); + const repositoryGate = status.data.gates.find((gate) => gate.id === "maintainer-repository-attempt"); + const goldenGate = status.data.gates.find((gate) => gate.id === "supervised-golden-path"); const reviewedGate = status.data.gates.find((gate) => gate.id === "full-reviewed-runs"); - assert(externalGate.threshold === 3 && externalGate.observed === 0 && externalGate.status === "unmet", "three independent participants remain required"); - assert(repositoryGate.threshold === 10 && repositoryGate.observed === 0, "ten repository attempts remain required"); - assert(reviewedGate.threshold === 5 && reviewedGate.observed === 0, "five reviewed runs remain required"); - assert(status.data.exclusions.some((entry) => entry.pilotId === "dogfood-1"), "excluded maintainer evidence is explained"); + assert(repositoryGate.threshold === 1 && repositoryGate.observed === 0, "one repository attempt remains required"); + assert(goldenGate.threshold === 1 && goldenGate.observed === 0, "one supervised golden path remains required"); + assert(reviewedGate.threshold === 1 && reviewedGate.observed === 0, "one reviewed finalized run remains required"); + assert(status.data.exclusions.length === 0, "maintainer records are not excluded from technical acceptance"); const duplicate = runNode(cewpCli, [ "pilot", "create", diff --git a/tests/contracts/pilot-release.js b/tests/contracts/pilot-release.js index b4eb2c4..1470284 100644 --- a/tests/contracts/pilot-release.js +++ b/tests/contracts/pilot-release.js @@ -21,27 +21,31 @@ function runContract() { assert(/^## Unreleased\s*$/m.test(notes), "release notes retain an Unreleased section after beta preparation"); assert(notes.includes("## 0.13.0-beta.0"), "Phase 13 beta has versioned release notes"); assert(/prepared locally.*not published, tagged, or released/is.test(notes), "release notes prohibit a false publication claim"); - assert(/real external.*evidence.*absent/is.test(notes), "release notes disclose missing external evidence"); - assert(/Phase 13.*exit gate.*open/is.test(notes), "release notes keep the Phase 13 exit gate open"); - assert(/ecosystem.*not.*submitted/is.test(notes), "ecosystem submission remains gated on real evidence"); + assert(/Phase 13.*complete.*maintainer technical acceptance/is.test(notes), "release notes record the approved Phase 13 closure"); + assert(/independent external.*not collected/is.test(notes), "release notes disclose that independent external evidence was not collected"); const limitations = read("docs/known-limitations.md"); - assert(/pilot infrastructure.*does not supply real participants/is.test(limitations), "limitations distinguish pilot infrastructure from users"); + assert(/independent user validation.*not performed/is.test(limitations), "limitations disclose the remaining external-validation truth"); assert(!limitations.includes("A general multi-checkpoint graph, dependency scheduler, automatic plan compiler, and plan migration engine are not shipped"), "known limitations no longer contradict the shipped workflow runtime"); const readme = read("README.md"); - assert(readme.includes("cewp pilot status --json"), "README exposes the pilot status entry point"); - assert(/real external pilot evidence.*still\s+absent/is.test(readme), "README keeps product validation honest"); - assert(/1\.0.*not\s+complete/is.test(readme), "README does not imply 1.0 completion"); + assert(readme.includes("docs/validation-status.md"), "README links the aggregate validation boundary"); + assert(!/dogfood|pilot id|run id/i.test(readme), "README omits local acceptance-run details"); - for (const privateSurface of [".cewp", ".cewp-private", "phase-8-to-1.0", "docs/plans"]) { + const validation = read("docs/validation-status.md"); + assert(/technical acceptance: complete/i.test(validation), "validation status records technical acceptance"); + assert(/independent user validation: not claimed/i.test(validation), "validation status avoids an external-user claim"); + assert(/local run identifiers.*not part of\s+the public repository/is.test(validation), "validation status excludes local run identities"); + assert(packageJson.files.includes("docs/validation-status.md"), "aggregate validation status is packaged"); + + for (const privateSurface of [".cewp", ".cewp-private", "docs/plans", "docs/agents"]) { assert(!packageJson.files.some((entry) => entry === privateSurface || entry.startsWith(`${privateSurface}/`)), `package files exclude ${privateSurface}`); } } try { runContract(); - console.log("[PASS] Phase 13 beta release surface remains locally prepared and evidence-honest"); + console.log("[PASS] release surface is professional and evidence-honest"); } catch (error) { console.error("[FAIL] Phase 13 release surface contract"); console.error(error && error.stack ? error.stack : error); diff --git a/tests/contracts/repository-hygiene.js b/tests/contracts/repository-hygiene.js new file mode 100644 index 0000000..4945c61 --- /dev/null +++ b/tests/contracts/repository-hygiene.js @@ -0,0 +1,62 @@ +"use strict"; + +const fs = require("node:fs"); +const path = require("node:path"); +const { spawnSync } = require("node:child_process"); +const { assert } = require("../harness/lib/assertions"); + +const repoRoot = path.join(__dirname, "..", ".."); + +function gitFiles() { + const result = spawnSync("git", ["ls-files"], { cwd: repoRoot, encoding: "utf8" }); + assert(result.status === 0, `git ls-files succeeds: ${result.stderr}`); + return result.stdout + .split(/\r?\n/) + .filter(Boolean) + .filter((file) => fs.existsSync(path.join(repoRoot, file))); +} + +function runContract() { + const tracked = gitFiles(); + const forbiddenPaths = [ + /^docs\/plans\//, + /roadmap/i, + /^\.cewp(?:-private)?\//, + ]; + for (const file of tracked) { + assert(!forbiddenPaths.some((pattern) => pattern.test(file)), `tracked public path is repository-ready: ${file}`); + } + + const textFiles = tracked.filter((file) => /\.(?:md|json|ya?ml|js|ps1|sh|txt|gitignore)$/i.test(file) || file === ".gitignore"); + const personalPatterns = [ + /C:\\Users\\[^<\s]+/i, + /C:\/Users\/[^<\s]+/i, + /\/Users\/[^<\s]+/i, + /\/home\/[^<\s]+/i, + /\btunca\b/i, + ]; + for (const file of textFiles) { + const content = fs.readFileSync(path.join(repoRoot, file), "utf8"); + assert(!personalPatterns.some((pattern) => pattern.test(content)), `tracked text contains no personal machine identity: ${file}`); + } + + const readme = fs.readFileSync(path.join(repoRoot, "README.md"), "utf8"); + for (const heading of ["## Why CEWP", "## Quick Start", "## Safety Model", "## Documentation", "## Project Status"]) { + assert(readme.includes(heading), `README includes ${heading}`); + } + assert(!/dogfood|run id|pilot id/i.test(readme), "README contains no personal acceptance-run narrative"); + + const ignore = fs.readFileSync(path.join(repoRoot, ".gitignore"), "utf8"); + for (const entry of [".cewp/", ".cewp-private/", "docs/plans/"]) { + assert(ignore.includes(entry), `.gitignore protects ${entry}`); + } +} + +try { + runContract(); + console.log("[PASS] professional repository hygiene"); +} catch (error) { + console.error("[FAIL] professional repository hygiene"); + console.error(error && error.stack ? error.stack : error); + process.exitCode = 1; +} diff --git a/tests/contracts/stable-core.js b/tests/contracts/stable-core.js index 786aaf6..a17242b 100644 --- a/tests/contracts/stable-core.js +++ b/tests/contracts/stable-core.js @@ -19,7 +19,9 @@ function runContract() { const contract = JSON.parse(result.stdout); assert(contract.schemaVersion === "stable-compatibility/v1", "compatibility output has a stable schema"); assert(contract.packageVersion === "0.14.0-beta.0", "package is prepared for the Phase 14 stable-core beta"); - assert(contract.release.status === "blocked-pilot-evidence", "compatibility truth does not claim 1.0 eligibility"); + assert(contract.release.status === "phase-13-complete-release-validation-required", "compatibility reports Phase 13 complete without claiming publication"); + assert(contract.release.phase13.validationModel === "maintainer-technical-acceptance", "compatibility names the approved Phase 13 model"); + assert(contract.release.phase13.independentUserValidationRequired === false, "compatibility removes independent-user quotas"); assert(JSON.stringify(contract.runtime.node.majors) === JSON.stringify([22, 24, 26]), "tested Node majors are explicit"); assert(contract.execution.managedBackend.id === "codex-exec", "codex-exec remains the stable managed backend"); assert(contract.execution.appServer.status === "experimental-not-graduated", "App Server remains ungraduated"); @@ -71,7 +73,7 @@ function runContract() { assert(manualAcceptance.includes(phrase), `manual acceptance covers ${phrase}`); } assert(manualAcceptance.includes("maintainer-dogfood"), "manual acceptance classifies the maintainer honestly"); - assert(manualAcceptance.includes("bağımsız Phase 13 kullanıcı doğrulaması sayılmaz"), "manual acceptance cannot turn maintainer testing into external evidence"); + assert(manualAcceptance.includes("Phase 13 teknik kabul kanıtı sayılır"), "manual acceptance explains the maintainer technical evidence policy"); } try { diff --git a/tests/harness/run-smoke.js b/tests/harness/run-smoke.js index 2bf129a..b48d1b8 100644 --- a/tests/harness/run-smoke.js +++ b/tests/harness/run-smoke.js @@ -2590,7 +2590,7 @@ async function main() { assert(!packOutput.includes(".ctxo/"), ".ctxo/ should not be packed"); assert(!packOutput.includes(".codegraph/"), ".codegraph/ should not be packed"); assert(!packOutput.includes(".cewp-private/"), ".cewp-private/ should not be packed"); - assert(!packOutput.includes("phase-8-to-1.0-implementation-plan.md"), "private implementation roadmap should not be packed"); + assert(!packOutput.includes("docs/plans/"), "development plans should not be packed"); assert(!packOutput.includes("docs/agents/"), "docs/agents/ should not be packed"); assert(!packOutput.includes("tests/"), "tests/ should not be packed"); });