diff --git a/README.md b/README.md index 18b2097..306f5bc 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,17 @@ [![npm](https://img.shields.io/npm/v/@bodanglin/verdict-node.svg)](https://www.npmjs.com/package/@bodanglin/verdict-node) [![TypeScript](https://img.shields.io/badge/typescript-strict-blue.svg)](https://www.typescriptlang.org/) [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) +[![CI](https://github.com/mrnicholasbcarter-code/verdict-node/actions/workflows/ci.yml/badge.svg)](https://github.com/mrnicholasbcarter-code/verdict-node/actions/workflows/ci.yml) -> **OpenAI-compatible gateway adapter for Express and Next.js** — includes pre-forward execution-envelope validation. +> **Safety-checking middleware for Express and Next.js apps that call an OpenAI-compatible API.** In short: **Verdict Core decides, verdict-node enforces at the HTTP edge** — this package does not make policy decisions itself, it checks each outgoing request against a decision made elsewhere before letting it through. --- ## What is @bodanglin/verdict-node? -`@bodanglin/verdict-node` is the TypeScript gateway adapter for the **Verdict** ecosystem. Verdict Core owns policy and execution authorization; Node supplies transport middleware that can validate an `ExecutionEnvelope` before forwarding a request to an OpenAI-compatible upstream. The canonical cross-language envelope contract and Core issuance path are still being reconciled, so this alpha must not be represented as complete end-to-end policy enforcement. Node also retains local classification, discovery, ranking, and fallback behavior for compatibility routing; those heuristics are not Core authorization. +`@bodanglin/verdict-node` is a TypeScript middleware library for Express and Next.js. In plain terms, it sits in front of your app's calls to an OpenAI-compatible API and checks each request before it goes out — it does not decide what is allowed; that is the job of **Verdict Core** (the Python control plane). This package's job is to enforce Core's decision at the HTTP edge: **core decides, node enforces**. + +The mechanism it enforces against is called an `ExecutionEnvelope` — plain-language: a signed record of what Core has authorized for a given request. By default, the standalone Express forwarder rejects a request outright ("fail-closed") if it arrives without a valid envelope or fails a policy check. The canonical cross-language contract for that envelope between Core (Python) and Node (TypeScript) is **still being reconciled**, so this alpha must not be represented as complete end-to-end policy enforcement yet. Node also retains its own local classification, discovery, ranking, and fallback behavior for compatibility routing; those heuristics are separate from, and not a substitute for, Core's authorization. **Works with any OpenAI-compatible client**: Claude Code, Codex, Cursor, Cline, Hermes, Agents SDK, raw HTTP. @@ -223,15 +226,15 @@ verdict-node/ ## Ecosystem -| Package | Purpose | -| ----------------------------------------------------------------- | -------------------------------------- | -| [`verdict-core`](https://github.com/verdict/verdict-core) | Python control plane | -| `@bodanglin/verdict-node` | Express/Next.js middleware (this repo) | -| [`verdict-cockpit`](https://github.com/verdict/verdict-cockpit) | Next.js dashboard | -| [`verdict-risk`](https://github.com/verdict/verdict-risk) | Risk engine | -| [`verdict-edge`](https://github.com/verdict/verdict-edge) | Edge mining framework | -| [`verdict-backtest`](https://github.com/verdict/verdict-backtest) | Monte Carlo harness | -| OmniRoute | 250+ providers, 90+ free tiers | +| Package | Purpose | +| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| [`verdict-core`](https://github.com/verdict/verdict-core) | Python control plane | +| `@bodanglin/verdict-node` | Express/Next.js middleware (this repo) | +| [`verdict-cockpit`](https://github.com/verdict/verdict-cockpit) | Next.js dashboard | +| [`verdict-risk`](https://github.com/verdict/verdict-risk) | Risk engine | +| [`verdict-edge`](https://github.com/verdict/verdict-edge) | Edge mining framework | +| [`verdict-backtest`](https://github.com/verdict/verdict-backtest) | Monte Carlo harness | +| OmniRoute | Per OmniRoute's own description: 250+ providers, 90+ free tiers (third-party claim, not verified by this repository) | --- diff --git a/specs/001-docs-pitch-accuracy/checklists/requirements.md b/specs/001-docs-pitch-accuracy/checklists/requirements.md new file mode 100644 index 0000000..c8a9306 --- /dev/null +++ b/specs/001-docs-pitch-accuracy/checklists/requirements.md @@ -0,0 +1,40 @@ +# Specification Quality Checklist: Documentation & Pitch Accuracy + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-09-05 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- No clarification markers were needed; all ambiguities were resolved using + the audit's verified findings and documented as Assumptions in spec.md. +- The fail-open code defect (FR-009) is intentionally tracked as a task within + this feature's tasks.md, but is explicitly out of scope for implementation — + this is a planning/tracking inclusion, not a spec ambiguity. +- All items pass; feature is ready for `/speckit-clarify` (optional, given no + markers remain) or directly for `/speckit-plan`. diff --git a/specs/001-docs-pitch-accuracy/plan.md b/specs/001-docs-pitch-accuracy/plan.md new file mode 100644 index 0000000..450a4ca --- /dev/null +++ b/specs/001-docs-pitch-accuracy/plan.md @@ -0,0 +1,90 @@ +# Implementation Plan: Documentation & Pitch Accuracy + +**Branch**: `001-docs-pitch-accuracy` | **Date**: 2026-09-05 | **Spec**: [spec.md](./spec.md) + +**Input**: Feature specification from `/specs/001-docs-pitch-accuracy/spec.md` + +## Summary + +Rewrite the verdict-node README's opening pitch into plain, non-jargon language +while preserving three protected, already-accurate statements (Next.js +fail-open warning, envelope-reconciliation-in-progress statement, alpha +label) and the "downstream enforcement client of verdict-core" framing; hedge +the OmniRoute ecosystem-table entry as an attributed third-party claim; leave +the three verified badges untouched; and track two out-of-scope items +(missing CI badge, `createNextApiHandler` fail-open code defect) as separate, +clearly flagged tasks that this feature's implementation does not resolve. +This is a documentation-only change — no source code, dependencies, or test +framework are touched by this feature's implementable scope. + +## Technical Context + +**Language/Version**: N/A (Markdown documentation edit only; repository is TypeScript, but no `.ts` source is touched by this feature) + +**Primary Dependencies**: N/A — no new dependencies + +**Storage**: N/A + +**Testing**: Editorial/diff review, not automated unit tests. Verification is a manual/scripted text-diff check confirming protected phrases are present pre- and post-edit (see quickstart.md). + +**Target Platform**: GitHub-rendered Markdown (README.md), npm registry package description if applicable + +**Project Type**: Library (TypeScript Express/Next.js middleware) — this feature touches only its documentation surface + +**Performance Goals**: N/A + +**Constraints**: Must not alter the three verified-accurate badges (npm version, TypeScript strict, MIT license) byte-for-byte; must not weaken, remove, or relocate the disclosed Next.js fail-open warning; must not touch production source files (`src/**`) + +**Scale/Scope**: Single file primarily (`README.md`); optionally any doc that mirrors the same pitch/badge/ecosystem-table content + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +Checked against `.specify/memory/constitution.md` v1.0.0: + +- **Principle I (Downstream Enforcement Client, Not a Peer Product)**: PASS — FR-002 requires the "core decides, node enforces at the HTTP edge" framing be explicit in the rewritten pitch. +- **Principle II (Verifiable Claims Only)**: PASS — FR-006 and FR-011 require the OmniRoute claim be attributed as third-party; no new unverifiable claims are introduced. +- **Principle III (Disclosed Defects Stay Disclosed Until Fixed)**: PASS — FR-003, FR-009, and FR-010 explicitly forbid softening/removing the Next.js fail-open warning and forbid fixing the underlying code defect within this feature (the defect fix is a prerequisite for ever removing the warning, tracked separately). +- **Principle IV (Alpha Status Is Explicit Until Declared Otherwise)**: PASS — FR-005 requires the alpha label be retained at equal or greater prominence. + +No violations identified. No entries required in Complexity Tracking. + +**Post-Phase-1 re-check**: No design decisions in Phase 1 (below) introduce new constitution risk — the design is a documentation edit plus two tracked-but-deferred tasks, both of which reinforce rather than weaken Principle III. PASS (unchanged). + +## Project Structure + +### Documentation (this feature) + +```text +specs/001-docs-pitch-accuracy/ +├── plan.md # This file +├── research.md # Phase 0 output +├── quickstart.md # Phase 1 output (validation guide) +├── checklists/ +│ └── requirements.md # Spec quality checklist +└── tasks.md # Phase 2 output (/speckit-tasks command) +``` + +No `data-model.md` or `contracts/` are produced: this feature has no new data +entities, persistence, or external interface contracts — it edits static +Markdown content in an existing file. + +### Source Code (repository root) + +```text +README.md # primary edit target (pitch, ecosystem table, badges) +.github/workflows/ci.yml # referenced only (CI badge task), not modified by this feature's implementation +src/middleware/next.ts (or similar) # referenced only for the fail-open defect tracking task; NOT edited by this feature +``` + +**Structure Decision**: Single-file documentation edit against the existing +repository root (`README.md`). No new directories, packages, or modules are +created. The two out-of-scope tracked tasks (CI badge, fail-open defect) +reference existing files (`.github/workflows/ci.yml`, the Next.js handler +source) for identification purposes only; this feature's tasks.md will mark +those tasks explicitly non-blocking/out-of-scope-for-implementation. + +## Complexity Tracking + +No constitution violations identified; this section is intentionally empty. diff --git a/specs/001-docs-pitch-accuracy/quickstart.md b/specs/001-docs-pitch-accuracy/quickstart.md new file mode 100644 index 0000000..50924b7 --- /dev/null +++ b/specs/001-docs-pitch-accuracy/quickstart.md @@ -0,0 +1,75 @@ +# Quickstart: Validating Documentation & Pitch Accuracy + +This is a documentation-only feature. Validation is editorial/diff-based, not +a runtime test suite. Use this guide to confirm the change meets the spec's +Success Criteria (SC-001 through SC-006) before merge. + +## Prerequisites + +- A checkout of this repository on the feature branch (`001-docs-pitch-accuracy` or equivalent). +- The pre-edit `README.md` available for comparison (e.g., via `git show main:README.md` or the original audit snapshot). + +## Step 1 — Capture the baseline + +```bash +git show HEAD:README.md > /tmp/readme-before.md +``` + +## Step 2 — Apply the documentation edits + +(Performed during `/speckit-implement` — not part of this planning pass.) +Edits touch only: +- The opening pitch/title/tagline block. +- The OmniRoute row in the ecosystem/comparison table. +- Optionally, the badge row (CI badge addition only — the three existing badges must not change). + +## Step 3 — Verify protected statements survive (SC-002) + +Confirm the following phrases (or clear paraphrases carrying the same claim) +are present in the edited `README.md`: + +```bash +grep -i "fail-closed\|fail-open" README.md # Next.js warning must still appear +grep -i "reconcil" README.md # envelope contract statement must still appear +grep -i "alpha" README.md # alpha status label must still appear +``` + +Each command MUST return at least one match. If any returns no match, the +edit has removed a protected statement and must be reverted/fixed before +proceeding. + +## Step 4 — Verify badges are unchanged (SC-004) + +```bash +diff <(grep -i "npm/v/\|badge.*typescript\|badge.*license" /tmp/readme-before.md) \ + <(grep -i "npm/v/\|badge.*typescript\|badge.*license" README.md) +``` + +Expected: no diff output (the three badge lines are identical). + +## Step 5 — Verify the OmniRoute attribution (SC-003) + +Manually read the OmniRoute row in the ecosystem table and confirm a second +reviewer agrees the figures are unambiguously attributed to OmniRoute itself +(e.g., "per OmniRoute," "OmniRoute states," a footnote citing OmniRoute), +not stated as this repository's own verified fact. + +## Step 6 — Verify plain-language comprehension (SC-001) + +Ask a reviewer unfamiliar with terms like "ExecutionEnvelope" or +"fail-closed" to read only the rewritten pitch and restate, in their own +words, what verdict-node does and how it relates to verdict-core. Success: +they can do so without needing the jargon defined first. + +## Step 7 — Verify no source code was touched (SC-006) + +```bash +git diff --name-only HEAD | grep -E '^src/' && echo "FAIL: source files touched" || echo "PASS: no source files touched" +``` + +## Optional automated check + +For a lightweight repeatable regression check on the three protected +phrases, consider adding a CI step running the `grep` checks from Step 3 — +noted here as an optional follow-up, not a requirement of this feature +(see research.md, Decision: Verification method is text/diff review). diff --git a/specs/001-docs-pitch-accuracy/research.md b/specs/001-docs-pitch-accuracy/research.md new file mode 100644 index 0000000..59b91dc --- /dev/null +++ b/specs/001-docs-pitch-accuracy/research.md @@ -0,0 +1,46 @@ +# Phase 0 Research: Documentation & Pitch Accuracy + +No `NEEDS CLARIFICATION` markers remain in the Technical Context — this is a +documentation-only feature with no unresolved technology choices. This file +records the small number of judgment calls made while scoping the plan. + +## Decision: Treat this as a documentation-only feature (no code changes) + +- **Decision**: Implementation scope is limited to Markdown documentation + (primarily `README.md`); the `createNextApiHandler` fail-open defect is + tracked as a task but explicitly excluded from this feature's + implementable work. +- **Rationale**: The originating audit already separated the two concerns + (docs accuracy vs. a real code defect); conflating them would let a + docs-cleanup pass silently absorb or bury a safety-relevant bug fix, which + the project constitution (Principle III) forbids. +- **Alternatives considered**: Bundling the code fix into this feature was + considered and rejected — it would inflate scope, mix a safety-critical + code change into a low-risk documentation PR, and make the docs change + harder to review and revert independently. + +## Decision: Verification method is text/diff review, not unit tests + +- **Decision**: "Tests" for this feature are a before/after text comparison + confirming protected phrases (fail-open warning, reconciliation statement, + alpha label, three badges) are present and unweakened, plus a manual + read-through for the OmniRoute attribution clarity. +- **Rationale**: There is no runtime behavior to unit-test; the deliverable + is static prose. A diff-based check is the most direct, low-overhead way + to enforce the "must not remove/soften" constraints from the spec. +- **Alternatives considered**: A markdown-linting script that greps for the + exact protected strings was considered as a stronger automated gate; + documented as an optional follow-up in quickstart.md rather than a hard + requirement, since exact-string matching would break on any legitimate + copy-edit and create false failures. + +## Decision: "Related docs" scope boundary + +- **Decision**: In-scope docs are `README.md` and any file it directly + duplicates content from (pitch, badges, ecosystem table); out of scope is + any unrelated documentation that doesn't repeat these specific claims. +- **Rationale**: Keeps the feature bounded and matches the audit's findings, + which were all located in `README.md`. +- **Alternatives considered**: A repo-wide documentation sweep was + considered and rejected as out of scope — no audit evidence indicates the + same inaccuracies exist elsewhere. diff --git a/specs/001-docs-pitch-accuracy/spec.md b/specs/001-docs-pitch-accuracy/spec.md new file mode 100644 index 0000000..655c012 --- /dev/null +++ b/specs/001-docs-pitch-accuracy/spec.md @@ -0,0 +1,115 @@ +# Feature Specification: Documentation & Pitch Accuracy + +**Feature Branch**: `001-docs-pitch-accuracy` + +**Created**: 2026-09-05 + +**Status**: Draft + +**Input**: User description: "Fix documentation/pitch accuracy for verdict-node README and related docs, based on a completed read-only audit (plain-language pitch rewrite preserving disclosed Next.js fail-open warning and the accurate 'still being reconciled' envelope-contract statement; hedge the third-party OmniRoute claim as attributed, not owned; optionally note missing CI badge; track the createNextApiHandler fail-open code defect as a separate, non-blocking, prioritized-attention tracked task, out of scope for this docs feature)." + +## Clarifications + +### Session 2026-09-05 + +- No critical ambiguities found. Full taxonomy scan performed (functional scope, data model, interaction/UX, non-functional quality, integrations, edge cases, constraints/tradeoffs, terminology, completion signals, misc placeholders) against this spec's FR-001–FR-011, Assumptions, and Success Criteria. All categories were Clear or explicitly resolved by the existing Assumptions section (audit treated as ground truth, "related docs" scope boundary, rewrite-basis handling, "prioritized attention" meaning for the deferred code-defect task, editorial-not-runtime testing framing). No question would materially change task decomposition, architecture, or test design for this documentation-only feature. Proceeding to implementation without further questions is appropriate. + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Approachable, Accurate Pitch for a New Evaluator (Priority: P1) + +A developer evaluating verdict-node for the first time reads the README's opening pitch and immediately understands, in plain language, what the library does, how it relates to verdict-core, and what its current limitations are — without needing to already know terms like "execution envelope" or "fail-closed." + +**Why this priority**: The pitch is the first thing every reader sees. An inaccurate or jargon-heavy pitch either misleads readers about safety guarantees or turns away readers who could otherwise adopt or evaluate the project correctly. This is the highest-value, most visible fix. + +**Independent Test**: Can be fully tested by reading only the README's opening section (title, tagline, first descriptive paragraph) and confirming: (1) a non-technical reader can state in their own words what the library does and how it relates to verdict-core, (2) the Next.js fail-open warning is present and no less prominent than before the rewrite, (3) the "still being reconciled" envelope-contract statement is unchanged in substance, (4) verdict-node is described as verdict-core's downstream enforcement client, never as an independent product. + +**Acceptance Scenarios**: + +1. **Given** the current README pitch uses jargon ("ExecutionEnvelope," "fail-closed," "policy digest," "canonical routing contract") without plain-language grounding, **When** the pitch is rewritten, **Then** the opening section explains the library's purpose in plain language before or alongside any technical term, such that a reader unfamiliar with the jargon can still understand the library's purpose and relationship to verdict-core. +2. **Given** the README currently discloses that the Next.js integration path is not fail-closed, **When** the pitch section is rewritten for approachability, **Then** the disclosure of the Next.js fail-open bug remains present, equally prominent (same section-level visibility, not demoted to a footnote or removed), and equally clear in meaning. +3. **Given** the README currently states the cross-language (Python/TypeScript) envelope contract "is still being reconciled," **When** the pitch is rewritten, **Then** this statement's substance is preserved unchanged (wording may be smoothed for plain language but the claim itself — reconciliation is incomplete — is not altered, strengthened, or removed). +4. **Given** verdict-node is architecturally the downstream enforcement client of verdict-core, **When** any part of the pitch, README, or package description is rewritten, **Then** the text explicitly frames the relationship as "core decides, node enforces at the HTTP edge" (or materially equivalent plain-language framing) and never implies verdict-node is a standalone or peer product. +5. **Given** the project is alpha software, **When** the pitch is rewritten, **Then** the "Alpha — not production-ready" label (or equivalent) remains present and at least as prominent as before. + +--- + +### User Story 2 - Correctly Attributed Third-Party Claim (Priority: P2) + +A reader scanning the README's ecosystem/comparison table sees the OmniRoute reference ("250+ providers, 90+ free tiers") and can immediately tell this is a claim made by a third-party product, not a claim this repository is making or vouching for. + +**Why this priority**: This is a narrower, single-line accuracy fix. It matters for trust and correctness but affects a smaller surface area than the top-of-README pitch, so it is P2. + +**Independent Test**: Can be fully tested by reading the ecosystem table row referencing OmniRoute in isolation and confirming a reader can tell the "250+ providers, 90+ free tiers" figure is OmniRoute's own claim about itself, not a verified or owned fact of this repository. + +**Acceptance Scenarios**: + +1. **Given** README.md's ecosystem table currently states "OmniRoute — 250+ providers, 90+ free tiers" with no attribution marker, **When** the table is updated, **Then** the entry is hedged/attributed (e.g., "per OmniRoute's own description," "OmniRoute-reported," or a footnote citing OmniRoute as the source) such that it is unambiguous this is an external, unverified, third-party claim. +2. **Given** the hedge is added, **When** the rest of the ecosystem table (rows for verdict-node itself and verdict-cockpit) is reviewed, **Then** those rows — which describe this project's own repos — are left unchanged, since they are not third-party claims. + +--- + +### User Story 3 - Missing CI Badge Noted as Optional Improvement (Priority: P3) + +A maintainer reviewing the README's badge row notices that a CI workflow exists in the repository but has no corresponding status badge, and this gap is tracked as a nice-to-have rather than silently left unnoticed or conflated with the badges that are already accurate. + +**Why this priority**: This is a cosmetic completeness gap, not an accuracy problem — the existing badges (npm version, TypeScript strict, MIT license) are already correct and must not be touched. Lowest priority; explicitly non-blocking. + +**Independent Test**: Can be fully tested by confirming a task or note exists describing the missing CI badge as a nice-to-have, without any change having been forced into this feature's must-ship scope. + +**Acceptance Scenarios**: + +1. **Given** `.github/workflows/ci.yml` exists with no corresponding README badge, **When** this feature's task list is produced, **Then** a task exists to add a CI status badge, explicitly marked optional/nice-to-have and not a release blocker for this feature. +2. **Given** the npm version, TypeScript strict, and MIT license badges are already verified accurate, **When** the CI badge task is scoped, **Then** no task in this feature proposes changing those three existing badges. + +--- + +### Edge Cases + +- What happens if a future contributor tries to remove or shorten the Next.js fail-open warning during an unrelated docs cleanup? → Per governing constitution Principle III, any such change must be rejected unless the underlying `createNextApiHandler` code defect has been fixed and verified; this specification's tasks must not include or permit that removal. +- What happens if the OmniRoute attribution hedge is worded so vaguely that it still reads as this repo's own claim? → The acceptance test requires the hedge to be unambiguous; task validation must include a read-through check by someone other than the editor. +- What happens if the plain-language rewrite accidentally drops the word "alpha" or a qualifier like "known bug" while simplifying language? → Explicitly disallowed by FR-004 and FR-005 below; task acceptance criteria must check for presence of these qualifiers post-edit. +- How does this feature interact with the separate, out-of-scope `createNextApiHandler` fail-open code defect? → This feature only touches documentation; the code defect is tracked as a separate task (see FR-009) and must not be fixed as a side effect of this feature. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: The README's opening pitch (title, tagline, and introductory paragraph(s)) MUST be rewritten in plain, approachable language that a non-technical reader can follow, while remaining technically accurate. +- **FR-002**: The rewritten pitch MUST explicitly frame verdict-node as verdict-core's downstream enforcement client (e.g., "core decides, node enforces at the HTTP edge"), and MUST NOT describe or imply verdict-node as an independent or peer product. +- **FR-003**: The rewritten pitch and surrounding sections MUST preserve the existing disclosure that the Next.js integration path (`createNextApiHandler`) is not fail-closed, at equal or greater prominence (same or higher section-level visibility) compared to the current README. +- **FR-004**: The rewritten pitch and surrounding sections MUST preserve, without softening, the existing accurate statement that the cross-language (Python/TypeScript) envelope contract is still being reconciled. +- **FR-005**: The rewritten pitch and surrounding sections MUST retain the "Alpha — not production-ready" status label (or equivalent), at equal or greater prominence. +- **FR-006**: The README's ecosystem/comparison table entry for OmniRoute ("250+ providers, 90+ free tiers") MUST be updated to clearly attribute the figures to OmniRoute as a third-party claim, not as a fact verified or owned by this repository. +- **FR-007**: The three existing verified-accurate badges (npm version, TypeScript strict, MIT license) MUST NOT be modified by this feature. +- **FR-008**: This feature's task list MUST include a separate, explicitly-flagged, non-blocking task tracking the addition of a CI status badge, given `.github/workflows/ci.yml` exists without one. +- **FR-009**: This feature's task list MUST include a separate, explicitly-flagged task tracking the `createNextApiHandler` fail-open code defect (continues to `proxy()` after a 503 denial) as a code-level bug requiring a fix and regression test — this task MUST be clearly marked as OUT OF SCOPE for implementation within this docs-accuracy feature, and MUST be flagged for prioritized, separate attention. +- **FR-010**: No task produced by this feature's planning MAY specify or permit editing production code (e.g., `createNextApiHandler`, `middleware()`, `proxy()`); this feature is documentation-only in its implementable scope, with the code defect tracked but explicitly deferred. +- **FR-011**: All new or edited documentation claims MUST be verifiable from this repository's own source, config, or tests, per project constitution Principle II; any third-party claim MUST be attributed as such. + +### Key Entities + +- **README pitch section**: The title, tagline, and introductory paragraphs at the top of `README.md` that describe what verdict-node is and does. +- **Ecosystem/comparison table**: The README table listing related projects and tools, including the OmniRoute third-party reference row. +- **Disclosed defect warning**: The existing README text disclosing that `createNextApiHandler` is not fail-closed; a protected artifact that must survive this feature unweakened. +- **CI badge task**: A tracked, optional improvement item to add a status badge for the existing `.github/workflows/ci.yml` workflow. +- **Fail-open code defect**: The underlying `createNextApiHandler` bug (continues to `proxy()` after a 503 denial); tracked as a separate task, explicitly out of scope for code changes in this feature. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: A reader with no prior knowledge of "execution envelope," "fail-closed," or "policy digest" can correctly summarize, in one or two sentences after reading only the rewritten pitch, what verdict-node does and how it relates to verdict-core. +- **SC-002**: 100% of the protected statements (Next.js fail-open warning, envelope-contract reconciliation statement, alpha label) are present and unweakened in the post-edit README, verified by direct text comparison against the pre-edit baseline. +- **SC-003**: The OmniRoute README entry contains an explicit third-party attribution marker, verified by direct inspection, with zero ambiguity about ownership of the claim in a read-through by a second reviewer. +- **SC-004**: The three previously-verified-accurate badges (npm version, TypeScript strict, MIT license) remain byte-for-byte unchanged in the final README. +- **SC-005**: 100% of tasks generated for this feature that touch documentation are traceable to FR-001 through FR-007 or FR-011; the CI badge task and the fail-open code-defect task are each traceable to their own distinct, separately-flagged FR (FR-008 and FR-009 respectively) and are excluded from any "must ship together" grouping with the pitch/attribution tasks. +- **SC-006**: Zero production source files (`.ts` files under `src/` or equivalent) are modified as part of completing this feature's in-scope (documentation) tasks. + +## Assumptions + +- The audit referenced in the feature input is treated as ground truth for this specification; this feature does not re-run or re-verify the audit's findings, only acts on them. +- "Related docs" in scope means README.md and any documentation files it directly links to that repeat the pitch, badges, or ecosystem table content; it does not extend to unrelated documentation (e.g., internal architecture docs) unless they repeat the same inaccurate claims. +- The drafted plain-language rewrite provided in the feature input is the basis for the final pitch text but MAY be lightly copy-edited for flow, so long as FR-002 through FR-005 remain satisfied. +- "Prioritized attention" for the fail-open code defect task means it should be flagged with a priority label recognizable outside this feature's own tracking (e.g., a P0/P1-equivalent label or explicit "needs code fix" flag) when mirrored to GitHub issues, but the actual code fix work itself is out of scope for this feature's implementation phase. +- No new user-facing behavior is introduced by this feature; it is a documentation-accuracy correction, so standard "user scenario" testing here means editorial/documentation-review testing, not runtime software testing. diff --git a/specs/001-docs-pitch-accuracy/tasks.md b/specs/001-docs-pitch-accuracy/tasks.md new file mode 100644 index 0000000..7b77ff8 --- /dev/null +++ b/specs/001-docs-pitch-accuracy/tasks.md @@ -0,0 +1,218 @@ +# Tasks: Documentation & Pitch Accuracy + +**Input**: Design documents from `/specs/001-docs-pitch-accuracy/` + +**Prerequisites**: plan.md, spec.md, research.md, quickstart.md + +**Tests**: This is a documentation-only feature; "tests" are editorial/diff +verification steps (see quickstart.md), not automated unit tests. Verification +tasks are included per user story since the spec requires provable +non-regression of protected statements. + +**Organization**: Tasks are grouped by user story (US1 = pitch rewrite, US2 = +OmniRoute attribution, US3 = CI badge nice-to-have), plus a separate, +non-implementable tracked task for the out-of-scope code defect. + +## Format: `[ID] [P?] [Story] Description` + +## Phase 1: Setup + +- [ ] T001 Capture baseline snapshot of `/home/nick/dev/verdict-node/README.md` for before/after comparison (`git show HEAD:README.md > /tmp/readme-before.md`), per quickstart.md Step 1. + **Acceptance Criteria**: + - `/tmp/readme-before.md` exists and is byte-identical to the current committed `README.md`. + - The snapshot is taken before any edit in this feature begins. + - The snapshot file is not committed to the repository (scratch artifact only). + +--- + +## Phase 2: Foundational + +**Purpose**: Establish the exact set of protected strings/sections that every downstream task must preserve. This MUST be complete before any User Story edit begins. + +- [ ] T002 Identify and record the exact line ranges in `README.md` for: (a) the opening pitch/title/tagline block, (b) the Next.js fail-open disclosure, (c) the envelope-reconciliation statement, (d) the alpha status label, (e) the badge row (npm/TypeScript/license), (f) the OmniRoute row in the ecosystem table. + **Acceptance Criteria**: + - A written note (in the PR description or a scratch file, not committed) lists line numbers/anchors for all six items above as they exist in the pre-edit README. + - Every protected item from spec.md (FR-003, FR-004, FR-005, FR-007) has a corresponding recorded location. + - No line range overlaps incorrectly (e.g., pitch block correctly excludes the badge row). + +**Checkpoint**: Foundation ready — all protected content is located and recorded; edits in Phase 3+ can proceed without accidentally overwriting protected text. + +--- + +## Phase 3: User Story 1 - Approachable, Accurate Pitch (Priority: P1) 🎯 MVP + +**Goal**: Replace the jargon-heavy opening pitch with the plain-language rewrite while preserving the Next.js fail-open warning, the envelope-reconciliation statement, the alpha label, and the "core decides, node enforces" framing. + +**Independent Test**: Read only the rewritten opening section of `README.md` and confirm a non-technical reader can state the library's purpose and its relationship to verdict-core, and that all four protected statements are present and unweakened. + +### Implementation for User Story 1 + +- [ ] T003 [US1] Rewrite the title/tagline/opening paragraph(s) of `/home/nick/dev/verdict-node/README.md` using the drafted plain-language pitch as the basis, lightly copy-edited for flow. + **Acceptance Criteria**: + - The rewritten text explains, before or alongside any jargon term, that verdict-node is an Express/Next.js middleware library that checks requests against a safety envelope before forwarding them. + - The rewritten text explicitly states the "core decides, node enforces at the HTTP edge" relationship to verdict-core (FR-002), using materially equivalent plain language if not verbatim. + - No jargon term (ExecutionEnvelope, fail-closed, policy digest, canonical routing contract) appears without an adjacent plain-language explanation. + - The rewrite does not exceed the scope of the pitch block identified in T002 (does not bleed into or alter the badge row or ecosystem table). + - A second reviewer, given only the new pitch text, can correctly summarize the library's purpose and its relationship to verdict-core in 1-2 sentences (SC-001). + +- [ ] T004 [US1] Verify and, if necessary, re-integrate the Next.js fail-open disclosure into the rewritten pitch/README section so it remains present and equally prominent. + **Acceptance Criteria**: + - `grep -i "fail-closed\|fail-open"` against the post-edit `README.md` returns at least one match (quickstart.md Step 3). + - The disclosure's section-level visibility (heading level, position relative to the fold) is equal to or greater than in `/tmp/readme-before.md` — it is not demoted to a footnote, collapsed section, or removed. + - The disclosure's meaning is unchanged: it still communicates that the Next.js path can forward a request after a denial and should not be treated as a complete safety guarantee. + - This task blocks T003 sign-off: T003 cannot be marked complete until this task's grep check passes. + +- [ ] T005 [US1] Verify the envelope-reconciliation statement ("still being reconciled") survives the rewrite unchanged in substance. + **Acceptance Criteria**: + - `grep -i "reconcil"` against the post-edit `README.md` returns at least one match (quickstart.md Step 3). + - The claim itself (cross-language contract reconciliation is incomplete) is neither strengthened (e.g., claiming full parity) nor removed; wording may be smoothed but meaning is preserved (FR-004). + - A reviewer comparing `/tmp/readme-before.md` and the post-edit README confirms no change in the factual claim, only optional wording polish. + +- [ ] T006 [US1] Verify the "Alpha — not production-ready" label (or equivalent) remains present and at least as prominent. + **Acceptance Criteria**: + - `grep -i "alpha"` against the post-edit `README.md` returns at least one match (quickstart.md Step 3). + - The label's position (e.g., top-of-README badge or callout) is not moved to a less visible location. + - No new or edited copy anywhere in the pitch section implies production readiness (FR-005). + +**Checkpoint**: At this point, the README's pitch is rewritten, plain-language, and every protected statement is verified present. This story is independently mergeable as the MVP of this feature. + +--- + +## Phase 4: User Story 2 - Correctly Attributed Third-Party Claim (Priority: P2) + +**Goal**: Hedge the OmniRoute ecosystem-table entry so its "250+ providers, 90+ free tiers" claim is unambiguously attributed to OmniRoute, not stated as this repo's own fact. + +**Independent Test**: Read only the OmniRoute row of the ecosystem table and confirm a reader can tell the figures are OmniRoute's own claim about itself. + +### Implementation for User Story 2 + +- [ ] T007 [US2] Edit the OmniRoute row in `README.md`'s ecosystem/comparison table (originally at or near line 234) to add an explicit third-party attribution marker. + **Acceptance Criteria**: + - The edited row contains unambiguous attribution language (e.g., "per OmniRoute," "OmniRoute-reported," or a footnote/citation naming OmniRoute as the source of the "250+ providers, 90+ free tiers" figures) (FR-006). + - A second reviewer reading only this row agrees, without prompting, that the figures are an external claim and not verified/owned by this repository (SC-003). + - No other cell in the same table row (e.g., project name, one-line description) is altered beyond what is needed for the attribution. + - The numeric figures themselves ("250+", "90+") are not changed, invented, or independently verified as part of this task — only their attribution is added. + +- [ ] T008 [P] [US2] Confirm the verdict-node and verdict-cockpit rows of the same ecosystem table are unchanged by the T007 edit. + **Acceptance Criteria**: + - `diff` of the verdict-node and verdict-cockpit table rows between `/tmp/readme-before.md` and the post-edit README shows no differences. + - Only the OmniRoute row differs between before/after in this table (FR-006 scope discipline). + +**Checkpoint**: OmniRoute claim is now correctly attributed; User Stories 1 and 2 together form a coherent, independently verifiable accuracy pass. + +--- + +## Phase 5: User Story 3 - Missing CI Badge Noted as Optional Improvement (Priority: P3) + +**Goal**: Track the missing CI status badge as an explicit, non-blocking nice-to-have without touching the three already-accurate badges. + +**Independent Test**: Confirm a task exists describing the missing CI badge as optional, and that no task in this feature proposes changing the npm/TypeScript/license badges. + +### Implementation for User Story 3 + +- [ ] T009 [P] [US3] [OPTIONAL / NON-BLOCKING] Add a CI status badge to the badge row of `README.md`, referencing `.github/workflows/ci.yml`. + **Acceptance Criteria**: + - If implemented: the new badge follows the same badge format/style as the existing three badges and links to the actual CI workflow's status page. + - The three existing badges (npm version, TypeScript strict, MIT license) remain byte-for-byte unchanged (`diff` against `/tmp/readme-before.md` shows no change to those three specific badge lines) (FR-007, SC-004). + - This task is explicitly optional: the feature is considered complete and mergeable whether or not T009 is implemented. It MUST NOT block sign-off of User Stories 1 or 2. + - If not implemented in this pass, this task remains open and is carried forward as a standalone backlog item, not silently dropped. + +**Checkpoint**: All three user stories addressed. CI badge task can ship now or be deferred without affecting the rest of the feature. + +--- + +## Tracked, Out-of-Scope Task: `createNextApiHandler` Fail-Open Code Defect + +> **PRIORITY FLAG: needs separate prioritized attention — DO NOT implement here.** +> This task exists for tracking and visibility only. It is intentionally +> given **zero implementation subtasks** in this docs-only feature. Per +> spec.md FR-009/FR-010 and constitution Principle III, fixing this defect +> requires its own feature (spec → plan → tasks → implement), including a +> regression test proving the Next.js path becomes fail-closed. This +> feature's documentation changes MUST NOT be blocked on, nor silently +> resolve, this defect — and MUST NOT soften the existing disclosure of it +> (see T004). + +- [ ] T010 **[CODE-DEFECT] [priority: needs separate prioritized attention]** File/confirm a tracked follow-up for the `createNextApiHandler` fail-open bug (continues to call `proxy()` after a 503 denial instead of short-circuiting), to be scheduled as its own spec-kit feature. + **Acceptance Criteria**: + - A GitHub issue (or equivalent tracked item) exists describing: the exact defect (fail-open on 503 denial in the Next.js integration path), its safety impact (documented integration path does not actually guarantee fail-closed behavior), and that it requires a code fix plus a regression test. + - The issue/task is labeled or flagged in a way that is visibly distinct from the docs-accuracy tasks (e.g., a `bug`/`P0`/`P1` label, or explicit "code defect — not a docs task" note). + - This task's acceptance is satisfied by the existence of a properly flagged tracking item — it does NOT require or permit any code change to `createNextApiHandler`, `middleware()`, `proxy()`, or any file under `src/` as part of this feature. + - The disclosed warning in `README.md` (verified surviving via T004) continues to reference this defect accurately after this feature merges. + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +- [ ] T011 [P] Run the full quickstart.md validation sequence (Steps 3-7) against the final edited `README.md` and record results. + **Acceptance Criteria**: + - All grep checks in quickstart.md Step 3 pass (fail-open/fail-closed, reconcil, alpha all present). + - Badge diff check (Step 4) shows zero differences on the three protected badges. + - OmniRoute attribution read-through (Step 5) is confirmed by a reviewer other than the editor. + - Plain-language comprehension check (Step 6) is confirmed by at least one reviewer unfamiliar with the project's jargon. + - Source-file diff check (Step 7) confirms zero files under `src/` were modified (SC-006). + +- [ ] T012 Final diff review of all changes to `README.md` against `/tmp/readme-before.md`, confirming every change traces to FR-001 through FR-007 or FR-011, and that only T009 (if implemented) and no other unrelated edits are present. + **Acceptance Criteria**: + - Every hunk in the diff is attributable to a specific FR from spec.md. + - No hunk touches content outside the pitch block, OmniRoute row, or badge row (unless it is whitespace-only/incidental). + - The diff is attached to or summarized in the pull request description for reviewer sign-off (SC-005). + +--- + +## Dependencies & Execution Order + +- **Setup (T001)**: No dependencies. +- **Foundational (T002)**: Depends on T001; blocks all user story tasks. +- **User Story 1 (T003-T006)**: Depends on Foundational. T004, T005, T006 are verification gates on T003 and should be run immediately after T003's edit, before moving to US2. +- **User Story 2 (T007-T008)**: Depends on Foundational; independent of US1's content but conventionally sequenced after US1 since both land in the same file/PR. +- **User Story 3 (T009)**: Depends on Foundational; fully independent and optional; may be skipped without affecting US1/US2 sign-off. +- **Tracked defect (T010)**: No implementation dependency on any other task; can be filed at any point, but is listed after the user stories to emphasize it is not part of the docs deliverable. +- **Polish (T011-T012)**: Depends on completion of US1 and US2 (US3/T010 optional inputs). + +### Parallel Opportunities + +- T008 [P] can run in parallel with T007's review once the OmniRoute edit is drafted (T008 only inspects unrelated rows). +- T009 [P] (CI badge) can be done at any time in parallel with US1/US2 work since it touches a different part of the badge row. +- T011 [P] can run in parallel with T010 (filing the tracked defect) since they are unrelated verification vs. tracking activities. + +## Implementation Strategy + +### MVP First (User Story 1 Only) + +1. Complete Phase 1 (T001) and Phase 2 (T002). +2. Complete Phase 3 (T003-T006) — the pitch rewrite with all protections verified. +3. **STOP and VALIDATE**: Run quickstart.md Steps 3 and 6 against the US1-only change. +4. This alone is mergeable as the MVP: it delivers the highest-value fix (SC-001, SC-002) independently of US2/US3. + +### Incremental Delivery + +1. Setup + Foundational → protected-content map ready. +2. US1 (pitch rewrite) → validate → mergeable MVP. +3. US2 (OmniRoute attribution) → validate → merge/extend same PR or follow-up. +4. US3 (CI badge) → optional, non-blocking → merge whenever convenient. +5. File T010 (tracked code defect) at any point; it never blocks 1-4. +6. Polish (T011-T012) once US1+US2 are both in. + +## Notes + +- No `[P]` marker on T003-T007 individually where they edit the same file/region sequentially, to avoid conflicting edits to `README.md`. +- T010 is deliberately excluded from the Dependencies graph as a blocker — it is tracked, not scheduled, within this feature. +- Total tasks: 12 (T001-T012), of which T010 is explicitly out-of-scope-for-implementation and T009 is explicitly optional/non-blocking. + +## Issue mirror + +| Task | GitHub Issue | +|------|-------------| +| T001 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/52 | +| T002 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/53 | +| T003 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/54 | +| T004 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/55 | +| T005 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/56 | +| T006 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/57 | +| T007 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/58 | +| T008 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/59 | +| T009 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/60 | +| T010 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/51 (pre-existing) | +| T011 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/61 | +| T012 | https://github.com/mrnicholasbcarter-code/verdict-node/issues/62 |