diff --git a/.godpowers/CHECKPOINT.mdx b/.godpowers/CHECKPOINT.mdx index 1f5e7be..b2cd50a 100644 --- a/.godpowers/CHECKPOINT.mdx +++ b/.godpowers/CHECKPOINT.mdx @@ -1,5 +1,5 @@ --- -id: CHECKPOINT-2026-08-18T04-06-56-142Z +id: CHECKPOINT-2026-08-19T06-45-56-035Z project: godpowers mode: B mode-d-suite: false @@ -12,7 +12,7 @@ progress-total: 19 current-step: 19 last-action: tier-0.sync done last-actor: unknown -last-update: 2026-08-18T04:06:56.142Z +last-update: 2026-08-19T06:45:56.035Z facts-hash: sha256:6bae3971008651bba3c5c4943ef21f4acfe4d2a17ac57b165f4c03bf8682d9d9 --- # Checkpoint @@ -28,7 +28,7 @@ facts-hash: sha256:6bae3971008651bba3c5c4943ef21f4acfe4d2a17ac57b165f4c03bf8682d - Lifecycle phase: **steady-state-active** - Progress: **100%** (19 of 19 steps complete; current step 19 of 19) - Current tier: **tier-3** / **launch** -- Last action: `tier-0.sync done` by unknown at 2026-08-18T04:06:56.142Z +- Last action: `tier-0.sync done` by unknown at 2026-08-19T06:45:56.035Z ## What happened recently @@ -36,12 +36,12 @@ _(no recent actions recorded yet)_ ## What happens next -- /god-feature -- The 6.0.0 release is complete and the project has returned to steady-state feature work. +- /god-ship +- The reviewed 31-test evidence correction is synchronized for the 6.1.0 source candidate; publication remains pending. ## Next suggested command -`/god-feature` - The 6.0.0 release is complete and the project has returned to steady-state feature work. +`/god-ship` - The reviewed 31-test evidence correction is synchronized for the 6.1.0 source candidate; publication remains pending. ## Last actions (most recent first, max 20) @@ -74,7 +74,7 @@ _(no actions recorded yet)_ ## Provenance -- Generated: 2026-08-18T04:06:56.142Z +- Generated: 2026-08-19T06:45:56.035Z - Schema version: 1.0 - Authoritative state: `.godpowers/state.json` - Authoritative history: `.godpowers/runs//events.jsonl` + `.godpowers/log` diff --git a/.godpowers/PROGRESS.mdx b/.godpowers/PROGRESS.mdx index 4059f10..5efc9b9 100644 --- a/.godpowers/PROGRESS.mdx +++ b/.godpowers/PROGRESS.mdx @@ -40,7 +40,7 @@ - [DECISION] PRD and ROADMAP were reconstructed from the shipped v2.1.1 codebase with stable requirement ids, and the linkage map was populated via `scripts/reconstruct-self-ledger.js`. Deliverable status lives in `.godpowers/REQUIREMENTS.mdx`: 32 of 33 requirements done, 1 in progress (deliverable-progress, unreleased), 100% requirement-to-code coverage. - + # Godpowers Progress - [DECISION] This file is a generated human-readable view of `.godpowers/state.json`. @@ -61,12 +61,12 @@ | 4 | Orchestration | Tech Debt | done | tech-debt/ASSESSMENT.mdx | 2026-07-13T05:12:51.236Z | | 5 | Orchestration | Greenfield Simulation | done | audit/GREENFIELD-SIMULATION.mdx | 2026-07-13T05:12:51.236Z | | 6 | Orchestration | Greenfieldify | done | audit/GREENFIELDIFY-PLAN.mdx | 2026-07-13T05:45:00.000Z | -| 7 | Orchestration | Sync | done | SYNC-LOG.mdx | 2026-08-18T04:04:11.227Z | -| 8 | Planning | PRD | done | prd/PRD.mdx | 2026-08-18T03:37:48.425Z | +| 7 | Orchestration | Sync | done | SYNC-LOG.mdx | 2026-08-19T06:45:56.026Z | +| 8 | Planning | PRD | done | prd/PRD.mdx | 2026-08-19T06:45:56.026Z | | 9 | Planning | Design | not-required | - | 2026-07-13T05:12:51.236Z | | 10 | Planning | Product | not-required | - | 2026-07-13T05:12:51.236Z | -| 11 | Planning | Architecture | done | arch/ARCH.mdx | 2026-08-18T03:37:48.425Z | -| 12 | Planning | Roadmap | done | roadmap/ROADMAP.mdx | 2026-08-18T03:37:48.425Z | +| 11 | Planning | Architecture | done | arch/ARCH.mdx | 2026-08-19T06:24:23.963Z | +| 12 | Planning | Roadmap | done | roadmap/ROADMAP.mdx | 2026-08-19T06:45:56.026Z | | 13 | Planning | Stack | done | stack/DECISION.mdx | 2026-08-18T03:37:48.425Z | | 14 | Building | Repo | done | repo/AUDIT.mdx | 2026-07-13T05:57:20.000Z | | 15 | Building | Build | done | build/STATE.mdx | 2026-08-18T03:46:06.501Z | diff --git a/.godpowers/REQUIREMENTS.mdx b/.godpowers/REQUIREMENTS.mdx index 8c5e570..8c6fccc 100644 --- a/.godpowers/REQUIREMENTS.mdx +++ b/.godpowers/REQUIREMENTS.mdx @@ -5,19 +5,19 @@ > `/god-progress`, `/god-status`, or `/god-sync`. Do not hand-edit statuses; > they are recomputed from disk. -Updated: 2026-08-18T03:04:41.200Z +Updated: 2026-08-19T06:21:23.536Z Source: PRD + ROADMAP + linkage forward map + build state -Progress: [####################] 41/41 done (100%) | 0 in progress | 0 not started +Progress: [####################] 47/47 done (100%) | 0 in progress | 0 not started ## By priority | Priority | Done | In progress | Not started | Total | |----------|------|-------------|-------------|-------| -| MUST | 29 | 0 | 0 | 29 | +| MUST | 35 | 0 | 0 | 35 | | SHOULD | 8 | 0 | 0 | 8 | | COULD | 4 | 0 | 0 | 4 | -## Done (41) +## Done (47) - [x] **P-MUST-01** Run a full idea-to-production project autonomously through tiered specialist agents _(increment: M-orchestration)_ - agents/god-orchestrator.md, docs/change-propagation.md, docs/linkage.md, lib/code-scanner.js, +9 more - [x] **P-MUST-02** Hold project state on disk and re-derive it every turn, never from agent memory _(increment: M-orchestration)_ - lib/state.js, scripts/test-linkage.js, specialists/god-executor.md @@ -48,6 +48,12 @@ Progress: [####################] 41/41 done (100%) | 0 in progress | 0 not start - [x] **P-MUST-27** Derive a compact structured slice handoff from authoritative disk evidence on completion, pause, or ownership change _(increment: M-harness-quality-hardening)_ - lib/slice-handoff.js - [x] **P-MUST-28** Capture deterministic before-and-after maintainability evidence with signed deltas and sample counts for independent quality review _(increment: M-harness-quality-hardening)_ - lib/maintainability-trajectory.js, lib/style-stats.js - [x] **P-MUST-29** Run a deterministic six-checkpoint evolution benchmark that reveals requirements one at a time and measures continued correctness and changeability _(increment: M-harness-quality-hardening)_ - lib/evolution-benchmark.js +- [x] **P-MUST-30** Extend the shared voice contract with plain and concrete prose guidance plus a separate post-draft audit _(increment: M-prose-quality-hardening)_ - SKILL.md, references/shared/VOICE.md, scripts/test-prose-lint.js +- [x] **P-MUST-31** Provide a dependency-free deterministic advisory prose scanner _(increment: M-prose-quality-hardening)_ - lib/prose-lint.js, scripts/test-prose-lint.js +- [x] **P-MUST-32** Integrate prose findings into universal artifact validation as U-12 warnings _(increment: M-prose-quality-hardening)_ - lib/have-nots-validator.js, references/HAVE-NOTS.md, scripts/test-artifact-linter.js, scripts/test-prose-lint.js +- [x] **P-MUST-33** Verify prose lint behavior, precision, performance, integration, and shipped-framework self-dogfood _(increment: M-prose-quality-hardening)_ - lib/prose-lint.js, scripts/run-tests.js, scripts/static-check.js, scripts/test-prose-lint.js +- [x] **P-MUST-34** Apply the shared prose contract through the documentation and launch specialists according to output type _(increment: M-prose-quality-hardening)_ - scripts/test-prose-lint.js, specialists/god-docs-writer.md, specialists/god-launch-strategist.md +- [x] **P-MUST-35** Preserve independent authorship and release discipline for the pstack `unslop`-inspired prose-quality feature _(increment: M-prose-quality-hardening)_ - scripts/check-package-contents.js, scripts/test-prose-lint.js - [x] **P-SHOULD-01** Set up a deploy pipeline that promotes the same artifact with tested rollback _(increment: M-shipping)_ - agents/god-deploy-engineer.md - [x] **P-SHOULD-02** Wire observability with SLOs tied to product success metrics _(increment: M-shipping)_ - agents/god-observability-engineer.md - [x] **P-SHOULD-03** Produce launch readiness: landing copy, Open Graph cards, and a launch runbook _(increment: M-shipping)_ - agents/god-launch-strategist.md @@ -85,4 +91,5 @@ Progress: [####################] 41/41 done (100%) | 0 in progress | 0 not start - [x] **M-advanced**: Advanced capabilities _[next]_ - done - 4/4 requirements done - [x] **M-authorized-ai-provenance-cleaning**: Authorized AI provenance cleaning _[next]_ - done - 2/2 requirements done - [x] **M-harness-quality-hardening**: Harness quality hardening _[next]_ - done - 6/6 requirements done +- [x] **M-prose-quality-hardening**: Prose quality hardening _[next]_ - done - 6/6 requirements done - [ ] **M-deeper-traceability-and-ecosystem**: Deeper traceability and ecosystem _[later]_ - pending - 0/0 requirements done diff --git a/.godpowers/SYNC-LOG.mdx b/.godpowers/SYNC-LOG.mdx index 2e91f87..1d75dc2 100644 --- a/.godpowers/SYNC-LOG.mdx +++ b/.godpowers/SYNC-LOG.mdx @@ -50,3 +50,20 @@ - [DECISION] Isolated exact-version root installation and published MCP executable verification pass. - [DECISION] GitHub Release `v6.0.0` is published at `https://github.com/hannsxpeter/godpowers/releases/tag/v6.0.0` with notes and no duplicate package assets; npm is the authoritative artifact source. - [DECISION] The publication workflow now retries exact-version registry reads for up to 120 seconds before stopping pair verification, preventing the observed propagation race from failing immediately. + +## 2026-08-19: Prose Quality Hardening Source Closeout + +- [DECISION] Reverse sync scanned 840 eligible files, found 132 current annotation and filename links, added 18 code-scanner-owned links, removed none, refreshed the PRD, architecture, roadmap, and stack linkage footers, and reported zero drift findings or review items. +- [DECISION] P-MUST-30 through P-MUST-35 now link to the scanner, U-12 integration, focused tests, shared voice contract, documentation and launch specialists, self-dogfood, and package guard that implement them. +- [DECISION] The generated requirements ledger records 47 of 47 requirements complete with 100 percent linkage coverage, zero gaps, 15 completed increments, and one empty later-horizon theme still pending. +- [DECISION] The root PRD, architecture, and deliberately reviewed roadmap remain complete with exact hashes recorded in authoritative state, and M-prose-quality-hardening is complete in source while publication evidence remains pending. +- [DECISION] Independent Stage 1 specification review, Stage 2 quality review, and scoped hardening review passed for the prose-quality feature; the current focused evidence records 31 prose tests, 73 artifact-linter tests, 35 static checks, 11 voice tests, and zero prose warnings across 233 shipped Markdown and MDX files. +- [DECISION] Pillars synchronization refreshed context, architecture, quality, deploy, and observe projections from the current PRD, architecture, roadmap, state, and 6.1.0 release candidate; context and deploy now record 113 runtime modules and 111 focused test scripts instead of the prior 112 and 110 counts. +- [DECISION] Source-system sync was skipped because authoritative state has no enabled source systems, and repository documentation and repository surface evidence were already refreshed by the feature workflow. +- [DECISION] Full release-gate evidence, pull-request CI, merge identity, merged-main CI, annotated tag, GitHub Release, npm publication, registry integrity, and isolated published-install verification remain pending and are not marked complete by this sync. + +- 2026-08-19T06:22:48.602Z roadmap hash re-blessed deliberately via version-sync --bless-roadmap: Reviewed the completed prose-quality increment, 47 linked requirements, reverse-synced footers, and final PRD, ARCH, and stack provenance for the 6.1.0 release candidate + +- 2026-08-19T06:23:01.251Z roadmap hash re-blessed deliberately via version-sync --bless-roadmap: Corrected the prose-quality roadmap evidence timestamp to the actual closeout time after reviewing the same approved 6.1.0 content + +- 2026-08-19T06:45:55.998Z roadmap hash re-blessed deliberately via version-sync --bless-roadmap: Reviewed the focused prose evidence correction from 30 to 31 tests and refreshed the exact PRD provenance for the 6.1.0 release candidate diff --git a/.godpowers/arch/ARCH.mdx b/.godpowers/arch/ARCH.mdx index 79bba01..9d5a1e2 100644 --- a/.godpowers/arch/ARCH.mdx +++ b/.godpowers/arch/ARCH.mdx @@ -26,6 +26,7 @@ | C-slice-handoff | [DECISION] Project authoritative plan, state, event, linkage, and verification facts into one bounded resume record. | [DECISION] Dependency-free Node.js CommonJS and JSON. | | C-maintainability-trajectory | [DECISION] Capture stable code-shape snapshots and signed deltas without executing repository imports. | [DECISION] Dependency-free Node.js CommonJS. | | C-evolution-benchmark | [DECISION] Reveal six ordered requirements to a temporary repository and retain deterministic correctness and changeability evidence. | [DECISION] Dependency-free Node.js CommonJS plus packaged fixtures. | +| C-prose-lint within the Artifact layer | [DECISION] Scan caller-supplied Markdown as inert text and return ordered advisory U-12 prose findings. | [DECISION] Dependency-free Node.js CommonJS. | ## Architecture Decision Records @@ -93,6 +94,14 @@ - [DECISION] Flip point: advisory maintainability thresholds may be considered after three release-candidate datasets, but state authority remains fixed by ADR-001. - [DECISION] Consequence: slice transitions remain resumable and measurable without promoting one metric or summary to source-of-truth status. +### ADR-009: Keep prose-quality detection advisory and local + +- [DECISION] Context: labeled Godpowers prose can still hide actors, mechanisms, evidence, effects, or reader actions behind polished wording. +- [DECISION] Decision: C-prose-lint stays inside the existing Artifact layer, treats input as inert text, returns bounded sanitized findings, and enters universal validation only as U-12 warnings. +- [DECISION] Rationale: local structured warnings support human review without automatic rewriting, a model call, persistence, or a new external trust boundary. +- [DECISION] Flip point: reconsider a rule's advisory severity only after two release candidates provide reviewed precision evidence and a maintainer-approved override design. +- [DECISION] Consequence: existing artifact errors keep their severity, while maintainers receive deterministic prose findings that cannot block a gate by themselves. + ## Critical Flows ### Authorized provenance inspection and cleaning @@ -112,6 +121,13 @@ 5. [DECISION] C-slice-handoff writes a bounded projection for resume, with current state winning every conflict. 6. [DECISION] C-evolution-benchmark repeats behavior and maintainability evidence across six isolated checkpoint reveals and retains JSON plus Markdown summaries after temporary cleanup. +### Advisory prose-quality flow + +1. [DECISION] The Artifact layer passes caller-owned Markdown or MDX text to C-prose-lint without granting filesystem, network, model, or mutation authority. +2. [DECISION] C-prose-lint masks frontmatter, fenced code, inline code, link destinations, and clearly quoted bad examples before matching high-confidence sentence patterns. +3. [DECISION] C-prose-lint returns ordered findings with bounded excerpts after terminal control bytes are removed. +4. [DECISION] The universal have-nots wrapper maps each finding to a U-12 warning, while the existing artifact linter preserves every blocking error and aggregate warning count. + ## Capacity Envelope | Input | Supported envelope | Source | @@ -125,6 +141,7 @@ | Slice handoff | [DECISION] One canonical JSON record at or below 8 KiB, with mandatory recovery fields protected from trimming. | [DECISION] P-MUST-27 serialization fixtures. | | Evolution checkpoints | [DECISION] Exactly six sequential checkpoints with no parallel project mutation or future-checkpoint reads. | [DECISION] P-MUST-29 packaged scenario and isolation fixtures. | | Evolution input and output | [DECISION] Manifests and checkpoints are each capped at 16 KiB, scalar fields at 4 KiB, baselines at 64 MiB, 5,000 entries, and depth 48, machine evidence at 256 KiB, and human summaries at 128 KiB. | [DECISION] P-MUST-29 adversarial boundary fixtures. | +| Prose scan | [DECISION] At least 1 MiB or 10,000 lines per invocation, excerpts capped at 160 characters, and a 1 MiB fixture completing within 250 milliseconds at p95 across 20 runs. | [DECISION] P-MUST-31 focused performance and boundary fixtures. | ## Failure and Degradation @@ -137,6 +154,7 @@ | Guarded publication | [DECISION] Reject parent or destination identity changes and attempt one local restoration when replacement publication fails. | [DECISION] Preserve the competing file, restore the prior destination when possible, and report any retained recovery path. | | Context or plan validation | [DECISION] Complete each local validation within a 30 second harness deadline, reject missing, escaped, contradictory, oversized, or negatively approved evidence, and never retry; the read-only validation is idempotent by input-byte digest. | [DECISION] Return bounded findings and leave authoritative state unchanged. | | Trajectory or benchmark input | [DECISION] Complete each fixture checkpoint within a 30 second behavior deadline, reject incompatible snapshots, malformed manifests, future-checkpoint access, or incomplete evidence, and never retry a mutation; snapshot reads are idempotent by repository-byte digest. | [DECISION] Stop at the first invalid checkpoint, retain partial evidence, and remove the temporary repository. | +| Advisory prose scan | [DECISION] Complete one local pass without retry, execute no input content, make no I/O request, and leave caller bytes unchanged; identical input and options are idempotent by returned finding bytes. | [DECISION] Return bounded sanitized U-12 warnings, or a scanner error that leaves existing artifact state and severity unchanged. | ## NFR-to-Architecture Map @@ -155,6 +173,8 @@ | Deterministic resume | State-authoritative structured handoffs capped at 8 KiB | ADR-008 | | Changeability evidence | Report-only maintainability deltas plus isolated sequential benchmark checkpoints | ADR-008 | | Harness isolation | Dependency-free local helpers, inert source parsing, and an offline temporary-repository benchmark | ADR-007 and ADR-008 | +| Advisory prose quality | Local inert-text scanning, bounded sanitized findings, and warning-only U-12 integration | ADR-002 and ADR-009 | +| Prose scan isolation | No filesystem, network, model, persistence, or mutation authority for caller-owned text | ADR-002 and ADR-009 | ## Trust Boundaries @@ -167,6 +187,7 @@ - [DECISION] Provenance filesystem boundary: the bundled client pins input, parent, and destination identities, rejects unsafe links and concurrent changes, and retains a named recovery path when guarded restoration cannot complete. - [DECISION] Harness path boundary: context files reject symlinks and retain pinned bytes, program-design approval binds to an exact path and digest, and handoff plus benchmark paths resolve within their declared roots before reads or writes. - [DECISION] Harness content boundary: repository source and imports are inert measurement input, loadout events omit contents, and compact logs never add environment dumps or credentials. +- [DECISION] Artifact-quality boundary: prose input remains inert caller-owned text, C-prose-lint performs no I/O, terminal control bytes are removed from excerpts, findings are capped at 160 characters, and U-12 remains advisory; this local path adds no external trust boundary. ## Data Ownership @@ -188,6 +209,7 @@ | Slice handoff projection | `lib/slice-handoff.js`, with workflow authority retained by `.godpowers/state.json` | | Maintainability snapshots and deltas | `lib/maintainability-trajectory.js` plus the independent quality reviewer | | Evolution checkpoint evidence | `lib/evolution-benchmark.js` and `fixtures/evolution/maintainability-sequence/` | +| Advisory prose findings | `lib/prose-lint.js`, with universal warning integration owned by `lib/have-nots-validator.js` | ## Have-Nots Checklist @@ -199,6 +221,7 @@ ## Architecture Changelog +- [DECISION] 2026-08-19: Added ADR-009 and C-prose-lint inside the existing Artifact layer because deterministic inert-text scanning, bounded sanitized findings, and warning-only U-12 integration now participate in artifact validation without a new service or production dependency. - [DECISION] 2026-08-17: Added ADR-007, ADR-008, and six harness-quality containers because verified pre-spawn context, program design, compact verification, handoffs, trajectory measures, and evolution evidence now participate in the Build and release paths. - [DECISION] 2026-08-17: Added ADR-004 through ADR-006 and the five provenance containers because the completed extension introduced a lazy package boundary, a deterministic upstream client, a visible external transfer gate, and guarded local publication. diff --git a/.godpowers/docs/REPO-DOC-SYNC.mdx b/.godpowers/docs/REPO-DOC-SYNC.mdx index 3521455..7f95936 100644 --- a/.godpowers/docs/REPO-DOC-SYNC.mdx +++ b/.godpowers/docs/REPO-DOC-SYNC.mdx @@ -126,3 +126,9 @@ - [DECISION] Repo documentation sync status before apply was stale. - [DECISION] Repo documentation sync status after apply is fresh. - [DECISION] Refreshed ARCHITECTURE.md for architecture-publication-status. + +## 2026-08-19T05:41:28.799Z + +- [DECISION] Repo documentation sync status before apply was fresh. +- [DECISION] Repo documentation sync status after apply is fresh. +- [DECISION] No mechanical repo documentation files were changed. diff --git a/.godpowers/docs/UPDATE-LOG.mdx b/.godpowers/docs/UPDATE-LOG.mdx new file mode 100644 index 0000000..1154793 --- /dev/null +++ b/.godpowers/docs/UPDATE-LOG.mdx @@ -0,0 +1,99 @@ +# Docs Update Log + +Date: 2026-08-19 +Owner: `god-docs-writer` + +## Inventory + +- [DECISION] Reviewed `README.md`, `lib/README.md`, `docs/validation.md`, + `INSPIRATION.md`, and `ARCHITECTURE-MAP.md` against the implemented scanner, + validator integration, specialists, shared voice contract, and regression + tests. +- [DECISION] Reviewed `lib/prose-lint.js`, `lib/have-nots-validator.js`, + `scripts/test-prose-lint.js`, `scripts/static-check.js`, + `references/shared/VOICE.md`, `specialists/god-docs-writer.md`, and + `specialists/god-launch-strategist.md` as the code and contract surfaces for + the documentation claims. +- [DECISION] The local `lib/repo-doc-sync.run(projectRoot)` execution reported + fresh before and after status at `2026-08-19T05:41:28.799Z`; no documentation + sync agent ran. +- [DECISION] The local `lib/repo-surface-sync.run(projectRoot)` execution + reported fresh before and after status at `2026-08-19T05:41:28.846Z`; no + repository surface sync agent ran. + +## Verified + +- [DECISION] `lib/prose-lint.js` is a pure CommonJS scanner with no imports, + file-system writes, network access, or runtime dependencies. +- [DECISION] The scanner applies seven context-sensitive sentence-pattern + rules, returns at most one finding per rule per line, and does not ban + standalone words. +- [DECISION] The scanner masks opening YAML frontmatter, fenced code, inline + code, Markdown link destinations, and marked bad examples before matching. +- [DECISION] Finding excerpts replace terminal control characters and are + capped at 160 characters. +- [DECISION] `lib/have-nots-validator.js` maps scanner findings to universal + U-12 warnings, while artifact errors retain their existing blocking + severities. +- [DECISION] The documentation specialist preserves factual engineering prose, + exact repository terms, verified commands, runbook steps, and evidence + language during its post-draft audit. +- [DECISION] The launch specialist may preserve approved founder or product + voice, positioning, and channel constraints while keeping operational status + and engineering evidence direct and neutral. +- [DECISION] `scripts/static-check.js` scans 233 Markdown and MDX files under + `skills/`, `specialists/`, `agents/`, and `references/` against a zero-warning + baseline. +- [DECISION] The pstack unslop skill influenced the scan, targeted rewrite, + meaning and tone preservation, and self-audit sequence documented in + `INSPIRATION.md`. +- [DECISION] No upstream prose, rule catalog, code, fixture, or result is + vendored, and Godpowers has no runtime dependency on the pstack plugin. + +## Updated + +- [DECISION] `README.md` now explains the seven prose-pattern categories, the + advisory U-12 boundary, and the absence of standalone word bans. +- [DECISION] `lib/README.md` now lists `lib/prose-lint.js` and its pure advisory + contract. +- [DECISION] `docs/validation.md` now includes U-12 in the universal catalog and + documents its severity, finding shape, masking, excerpt safety, limitations, + self-dogfood scope, and output-specific review rules. +- [DECISION] `INSPIRATION.md` now credits the exact pstack unslop source and + records the no-vendoring and no-runtime-dependency boundary. +- [DECISION] `ARCHITECTURE-MAP.md` now records 113 JavaScript runtime modules, + 111 script test suites, and the prose scanner module and test surfaces. + +## Created + +- [DECISION] `.godpowers/docs/UPDATE-LOG.mdx` records this documentation audit + and its verification evidence. + +## Verified Commands + +- [DECISION] `node scripts/test-prose-lint.js` passed 30 tests with zero + failures on 2026-08-19. +- [DECISION] `node scripts/static-check.js` passed 35 checks with zero failures + and reported zero prose warnings across 233 files on 2026-08-19. +- [DECISION] `git diff --check` passed on 2026-08-19. +- [DECISION] `node scripts/test-doc-surface-counts.js` verified the updated + `ARCHITECTURE-MAP.md` counts, then stopped at the out-of-scope runtime-module + count in `RELEASE.md`. + +## Drift Found + +- [DECISION] `RELEASE.md`, `agents/context.md`, and `agents/deploy.md` still say + the core package has 112 runtime modules; an independent exact-text search + found those three stale claims. +- [DECISION] The release and Pillars update owns those three claims and must + change them to 113 before the documentation surface-count gate can pass. + +## Have-Nots Checklist + +- [DECISION] Every new claim was checked against current code, tests, or the + recorded local sync result. +- [DECISION] Every new documentation sentence is specific to the Godpowers + scanner, validator, specialist, or repository gate that supports it. +- [DECISION] The post-draft prose audit preserved code terms, verified facts, + the U-12 severity boundary, and the upstream attribution boundary. +- [DECISION] No runbook or unexecuted example was added. diff --git a/.godpowers/features/prose-quality-hardening/BUILD-PLAN.mdx b/.godpowers/features/prose-quality-hardening/BUILD-PLAN.mdx new file mode 100644 index 0000000..28e3c3d --- /dev/null +++ b/.godpowers/features/prose-quality-hardening/BUILD-PLAN.mdx @@ -0,0 +1,118 @@ +--- +stage: build-plan +durability: durable +owner: godpowers-maintainer +system_of_record: repo +status: approved +review_cadence: on-change +scale: medium +program_design_approval: user-authorized +requirements: + - P-MUST-30 + - P-MUST-31 + - P-MUST-32 + - P-MUST-33 + - P-MUST-34 + - P-MUST-35 +--- + +# Build Plan: Prose Quality Hardening + +## Scale And Approval + +- [DECISION] Scale: medium, because the feature adds one dependency-free runtime module and changes shared guidance, universal artifact validation, two specialist contracts, repository self-dogfood, documentation, and coordinated release evidence. +- [DECISION] The user explicitly authorized implementation, documentation, release preparation, commit, push, merge, and npm publication in the current request. +- [DECISION] Human approval becomes executable only when the orchestrator records a hash-bound `user.resolve` event for this exact plan path and content hash before production edits. + +## Program Design + +### File Tree Delta + +- [DECISION] Add `lib/prose-lint.js` as the pure advisory scanner and `scripts/test-prose-lint.js` as its focused behavioral suite. +- [DECISION] Modify `lib/have-nots-validator.js`, `scripts/test-artifact-linter.js`, `scripts/static-check.js`, and `scripts/run-tests.js` to expose U-12 warnings, verify advisory semantics, dogfood shipped prose, and run the focused suite. +- [DECISION] Modify `references/shared/VOICE.md`, `references/HAVE-NOTS.md`, `SKILL.md`, `specialists/god-docs-writer.md`, and `specialists/god-launch-strategist.md` to add the shared post-draft audit and output-specific use. +- [DECISION] Update `lib/README.md`, `docs/validation.md`, `README.md`, `INSPIRATION.md`, canonical product artifacts, Pillars, `CHANGELOG.md`, `RELEASE.md`, package version surfaces, and release evidence only after focused behavior passes. + +### Module Boundaries + +- [DECISION] `lib/prose-lint.js` owns inert text masking, sentence-pattern detection, ordered advisory findings, and bounded excerpts; it reads no files and mutates no input. +- [DECISION] `lib/have-nots-validator.js` owns conversion of prose findings into universal U-12 warnings without changing the scanner or artifact gate policy. +- [DECISION] `lib/artifact-linter.js` remains the report orchestrator and requires no new public entry point because universal validator checks already flow into summaries. +- [DECISION] `scripts/static-check.js` owns repository self-dogfood scope and baseline growth enforcement, while `scripts/test-prose-lint.js` owns rule, precision, determinism, performance, and integration fixtures. +- [DECISION] Shared and specialist Markdown owns human judgment, tone preservation, and post-draft rewriting; the JavaScript scanner never rewrites prose or claims authorship. + +### Public Contracts + +- [DECISION] `proseLint.scan(text, options)` returns source-ordered findings with `ruleId`, `line`, `column`, `excerpt`, `message`, and `suggestion` and accepts null, empty, multiline, and at least 1 MiB input. +- [DECISION] Scanner options may select an output profile and a high-confidence-only mode, but no option turns warnings into errors or enables mutation. +- [DECISION] `haveNotsValidator.checkTheaterProse(content)` maps every scanner finding to code `U-12` and severity `warning` while retaining the source line, column, explanation, and suggestion. +- [DECISION] Existing `runChecks`, `summarize`, `lintFile`, and `formatReport` contracts remain backward compatible and expose U-12 through their existing finding shapes. + +### Call And Data Flow + +1. [DECISION] A writer settles meaning, requirements, facts, terminology, quotations, and approved tone before the shared post-draft audit begins. +2. [DECISION] The writer scans for hidden actors, vague evidence, empty intensifiers, stock framing, dense sentences, and unclear next actions, then rewrites or removes only the affected prose. +3. [DECISION] Artifact lint passes text to the universal validator, which calls `proseLint.scan` after inert regions are masked. +4. [DECISION] The scanner returns advisory findings in source order, and the U-12 wrapper preserves location and remediation text in the artifact report. +5. [DECISION] Artifact summaries count U-12 under warnings, so an artifact with only prose warnings retains zero errors and does not fail the existing gate. +6. [DECISION] Repository self-dogfood scans the declared Markdown and MDX scope, compares deterministic warning identities with its reviewed baseline, and blocks only scanner defects, malformed results, scope omissions, nondeterminism, or unexplained warning growth. + +### Reused Patterns + +- [DECISION] Reuse the pure pattern-table and source-location design in `lib/voice-lint.js` rather than adding a parser or service. +- [DECISION] Reuse the universal-check registry and finding schema in `lib/have-nots-validator.js` rather than adding a parallel artifact gate. +- [DECISION] Reuse `scripts/test-harness.js`, the shipped-prose iteration in `scripts/static-check.js`, and the delegated command inventory in `scripts/run-tests.js`. +- [DECISION] Reuse the constraint tiers, substitution test, three-label test, and output-specific brand pause instead of treating the upstream catalog as a new authority. + +### Non-Goals + +- [DECISION] Do not add a command, route, recipe, workflow, specialist, production dependency, model call, network request, persistence layer, or hosted service. +- [DECISION] Do not copy or vendor upstream prose, examples, fixtures, rules, code, or results. +- [DECISION] Do not ban standalone vocabulary, auto-rewrite files, infer human authorship, flatten approved brand voice, or make U-12 warnings block artifacts. +- [DECISION] Do not weaken U-01, U-02, U-08, U-09, U-10, U-11, U-13, U-14, release gates, package checks, or publication approvals. + +### Verification Points + +- [DECISION] The RED run of `node scripts/test-prose-lint.js` must fail because `lib/prose-lint.js` and U-12 integration do not exist before implementation. +- [DECISION] The GREEN run must cover every rule, location reporting, ordering, masked regions, technical-term non-matches, deterministic output, the 40 positive and 60 negative fixture thresholds, a 1 MiB performance fixture, and artifact warning semantics. +- [DECISION] `node scripts/test-artifact-linter.js`, `node scripts/static-check.js`, `node scripts/test-voice-lint.js`, and `npm test -- --agent-output` must pass after integration. +- [DECISION] `npm run test:audit`, `npm run pack:check`, `npm run pack:mcp:check`, and `npm run release:check` must pass from the release candidate. +- [DECISION] Independent specification, quality, and hardening reviewers must pass the implementation before version preparation, merge, tag, and publication. + +## Wave 1: Prose Runtime And Contract + +### Slice 1.1: Writers and artifact lint receive concrete advisory feedback + +- [DECISION] Requirements: P-MUST-30, P-MUST-31, P-MUST-32, P-MUST-33, and P-MUST-34. +- [DECISION] Files: `scripts/test-prose-lint.js`, `lib/prose-lint.js`, `lib/have-nots-validator.js`, `scripts/test-artifact-linter.js`, `scripts/static-check.js`, `scripts/run-tests.js`, `references/shared/VOICE.md`, `references/HAVE-NOTS.md`, `SKILL.md`, `specialists/god-docs-writer.md`, and `specialists/god-launch-strategist.md`. +- [DECISION] Tests first: write the complete scanner, masking, precision, performance, integration, self-dogfood, and specialist-contract expectations, then run the focused suite and confirm the intended missing-module or missing-contract failure. +- [DECISION] Implementation: add the minimum pure scanner and U-12 wrapper, integrate the test and self-dogfood surfaces, then add shared and output-specific instructions that satisfy the focused contract tests. +- [DECISION] Verification: run `node scripts/test-prose-lint.js`, `node scripts/test-artifact-linter.js`, `node scripts/static-check.js`, and `node scripts/test-voice-lint.js`. +- [DECISION] Dependencies: none after hash-bound plan approval. + +## Wave 2: Documentation, Product Truth, And Release + +### Slice 2.1: The shipped package and release evidence describe verified prose quality + +- [DECISION] Requirements: P-MUST-35 plus closeout for P-MUST-30 through P-MUST-34. +- [DECISION] Files: `lib/README.md`, `docs/validation.md`, `README.md`, `INSPIRATION.md`, `.godpowers/prd/PRD.mdx`, `.godpowers/arch/ARCH.mdx`, `.godpowers/roadmap/ROADMAP.mdx`, relevant `agents/*.md`, `.godpowers/docs/UPDATE-LOG.mdx`, `CHANGELOG.md`, `RELEASE.md`, `package.json`, `packages/mcp/package.json`, `package-lock.json`, and mechanically synchronized version surfaces. +- [DECISION] Tests first: extend documentation, package-content, self-project truth, or release-surface assertions only where the verified feature adds a durable claim that an existing check cannot observe. +- [DECISION] Implementation: verify code claims, update documentation and durable artifacts, record the pstack inspiration without vendoring, run repository documentation and surface synchronization, then prepare the coordinated minor version. +- [DECISION] Verification: run focused docs checks, package checks, the full suite, audit, release check, pre-publication record and check, independent reviews, and published-install verification. +- [DECISION] Dependencies: Slice 1.1 and its independent specification, quality, and hardening passes. + +## Release Sequence + +1. [DECISION] Commit the verified feature and release metadata on `codex/prose-quality-hardening`, push it, and open a pull request against `main`. +2. [DECISION] Wait for pull-request CI, merge the approved branch, and verify merged-main CI against the merge commit. +3. [DECISION] From a clean `main`, run the release gate again, record and verify pre-publication evidence, create annotated tag `v6.1.0`, and push the tag. +4. [DECISION] Wait for the provenance workflow to publish `godpowers@6.1.0` and `@godpowers/mcp@6.1.0` under one staging tag and promote the verified pair to `latest`. +5. [DECISION] Create the GitHub Release from verified `RELEASE.md` facts, then verify registry versions, integrity, provenance, isolated installation, and the MCP executable. +6. [DECISION] Remove the merged local feature branch when safe and confirm `main` matches `origin/main` with no tracked or untracked changes. + +## Done Criteria + +- [x] [DECISION] Every feature requirement maps to a test-first vertical slice and observable verification. +- [x] [DECISION] The medium program design names exact file changes, boundaries, contracts, flow, reuse, non-goals, and verification points. +- [x] [DECISION] Advisory semantics, technical vocabulary, brand voice, upstream provenance, and publication safety remain explicit. +- [x] [DECISION] The release sequence publishes only from a clean merged `main` commit that passed the release gate. diff --git a/.godpowers/features/prose-quality-hardening/PRD.mdx b/.godpowers/features/prose-quality-hardening/PRD.mdx new file mode 100644 index 0000000..7d36e2a --- /dev/null +++ b/.godpowers/features/prose-quality-hardening/PRD.mdx @@ -0,0 +1,168 @@ +--- +stage: frame +durability: durable +owner: godpowers-maintainer +system_of_record: repo +status: implemented +review_cadence: on-change +covers: + - references/shared/VOICE.md + - lib/prose-lint.js + - lib/have-nots-validator.js + - lib/artifact-linter.js + - scripts/test-prose-lint.js + - scripts/static-check.js + - specialists/god-docs-writer.md + - specialists/god-launch-strategist.md + - INSPIRATION.md + - lib/README.md + - docs/validation.md + - scripts/run-tests.js + - CHANGELOG.md + - RELEASE.md +--- + +# Feature PRD: Prose Quality Hardening + +## Feature Context + +- [DECISION] This feature extends the global product requirement namespace after shipped requirement `P-MUST-29`, so its requirements use stable IDs `P-MUST-30` through `P-MUST-35` and must never be renumbered or reused after release. +- [DECISION] This feature hardens the existing Godpowers voice contract, artifact linter, specialist contracts, self-dogfood suite, and release evidence without changing disk authority, the pure-skill operating model, or the public slash-command surface. +- [DECISION] The existing product charter and root PRD govern this bounded feature addition, so the documentation profile does not require a second initiation brief for the prose-quality increment. +- [DECISION] The feature treats the pstack `unslop` skill as inspiration for plain, concrete writing and a post-draft self-audit, while Godpowers authors its own guidance, rules, fixtures, messages, and implementation. + +## 1. Problem Statement + +- [DECISION] Godpowers can reject unlabeled, generic, MDX-unsafe, or sycophantic artifact text, but it cannot yet point out a labeled sentence that still hides the actor, mechanism, observable result, or decision behind polished wording. +- [DECISION] A Godpowers maintainer can therefore pass the current artifact checks with text that satisfies formatting rules yet leaves a solo founder, reviewer, or later specialist unable to tell what happened, what changes, or what evidence would settle the claim. +- [DECISION] The gap is most costly in shared agent guidance, project documentation, and launch material because those surfaces teach later agents how to write, explain product behavior to new users, and turn verified product facts into public claims. +- [HYPOTHESIS] Shared plain and concrete prose guidance, a post-draft audit, and high-precision advisory U-12 findings will reduce theater sentences without flattening user-approved brand voice; validation will compare labeled positive and negative fixtures and review warnings from the first two release candidates containing the feature. + +## 2. Target Users + +- [DECISION] Primary: the Godpowers maintainer or contributor who edits Markdown skill contracts, specialist instructions, shared references, project docs, and release material, then runs dependency-free Node.js checks across Node.js 18, 20, and 22 before publishing the npm package. +- [DECISION] Secondary: solo founders and engineering teams of 1 to 5 people who read Godpowers planning artifacts, status reports, documentation, and launch copy inside Claude Code, Codex, Cursor, Windsurf, Gemini, or another supported host and need each claim to name a concrete action, mechanism, result, or next decision. +- [DECISION] Supporting actors: `god-docs-writer` must explain repository behavior without filler, while `god-launch-strategist` must keep claims concrete without replacing an approved product or founder voice with one universal engineering tone. + +## 3. Success Metrics + +| Metric | Target | Timeline | Measurement | +|---|---|---|---| +| Shared contract coverage | [DECISION] 100 percent of the root voice contract, docs specialist, and launch specialist expose the plain and concrete prose rule plus a post-draft audit step. | [DECISION] Before the first release candidate containing this feature. | [DECISION] A focused repository-surface test inspects `references/shared/VOICE.md` and both specialist contracts. | +| Detection recall on approved fixtures | [DECISION] At least 90 percent of a reviewed set of 40 theater-sentence fixtures produce one or more U-12 warnings. | [DECISION] Before the first release candidate containing this feature. | [DECISION] `scripts/test-prose-lint.js` runs the versioned positive fixture set through `lib/prose-lint.js`. | +| False-positive ceiling | [DECISION] No more than 5 percent of a reviewed set of 60 concrete or context-sensitive prose fixtures produce a U-12 warning. | [DECISION] Before the first release candidate containing this feature. | [DECISION] `scripts/test-prose-lint.js` includes technical terms, quoted examples, brand-voice samples, code spans, links, and prose that uses suspect words concretely. | +| Advisory artifact integration | [DECISION] 100 percent of prose-quality findings emitted through the artifact linter carry code `U-12` and severity `warning`, and 0 U-12 findings increase the error count. | [DECISION] Before the first release candidate containing this feature. | [DECISION] Focused validator and artifact-linter fixtures assert finding shape, summaries, and unchanged error totals. | +| Self-dogfood execution | [DECISION] 100 percent of eligible Markdown and MDX files under the agreed `skills/`, `specialists/`, `agents/`, and `references/` scope complete an advisory prose scan without an exception or hidden file skip. | [DECISION] On every full test run beginning with the first release candidate containing this feature. | [DECISION] The self-dogfood test enumerates the fixed scope, reports file and warning counts, and asserts that two scans of unchanged bytes return identical findings. | +| Release compatibility | [DECISION] 100 percent of Node.js 18, 20, and 22 CI jobs pass the focused test, full suite, audit checks, package check, and release gate with 0 new production dependencies. | [DECISION] Before publication of the first release containing this feature. | [DECISION] CI evidence comes from `npm test`, `npm run test:audit`, `npm run pack:check`, and `npm run release:check`, plus the production dependency count in package metadata. | + +## 4. Functional Requirements + +### MUST + +- P-MUST-30 [DECISION] Godpowers must extend its shared voice and craft contract with guidance that prefers plain words, concrete actors, named mechanisms, observable effects, and one post-draft audit after meaning is settled. + - [DECISION] Acceptance: the shared contract tells an agent to inspect a completed draft for sentences that conceal who acts, what changes, how the claim is known, or what the reader should do, then rewrite or remove those sentences while preserving requirements, facts, code terms, quotations, and user-approved tone. + - [DECISION] Acceptance: the guidance includes at least 3 Godpowers-specific bad and good pairs covering an artifact decision, a technical explanation, and public launch copy, with each correction preserving the original factual commitment. + - [DECISION] Acceptance: the post-draft audit is a separate revision step and does not ask an agent to narrate the audit, rewrite verified evidence, or substitute style judgment for the three-label and substitution tests. + +- P-MUST-31 [DECISION] Godpowers must provide `lib/prose-lint.js` as a dependency-free, deterministic, advisory scanner for high-confidence prose patterns associated with U-12 theater sentences. + - [DECISION] Acceptance: `scan(text, options)` accepts empty, null, and multiline input without throwing and returns ordered findings containing `ruleId`, `line`, `column`, `excerpt`, `message`, and `suggestion` without reading files, using the network, invoking a model, or mutating the input. + - [DECISION] Acceptance: two calls with identical text and options return byte-equivalent findings on Node.js 18, 20, and 22, and one 1 MiB prose fixture completes within 250 milliseconds at p95 across 20 runs on the release test host. + - [DECISION] Acceptance: the scanner masks fenced code, inline code, link destinations, frontmatter, and clearly quoted bad examples, and every warning explains the matched sentence pattern rather than banning a standalone word. + - [DECISION] Acceptance: focused negative fixtures prove that project terms such as `surface`, `harness`, `primitive`, `robust`, and `leverage` remain unflagged when a sentence uses them as an exact code, security, mathematical, or product term and states a concrete fact. + +- P-MUST-32 [DECISION] Godpowers must integrate prose-quality findings into the existing artifact validation path as non-blocking U-12 warnings. + - [DECISION] Acceptance: `lib/have-nots-validator.js` registers one U-12 wrapper in the universal check set, and `lib/artifact-linter.js` reports its warnings with the existing line, message, suggestion, per-code count, and aggregate-warning fields. + - [DECISION] Acceptance: an artifact containing only U-12 findings retains zero errors and does not fail an existing artifact gate, while any existing error still blocks through the unchanged gate behavior. + - [DECISION] Acceptance: the integration does not change the meaning or severity of U-01, U-02, U-08, U-09, U-10, U-11, U-13, or U-14 and does not convert the human U-12 review obligation into a claim of complete mechanical detection. + +- P-MUST-33 [DECISION] Godpowers must verify prose lint with focused behavior tests and an advisory self-dogfood scan of shipped framework prose. + - [DECISION] Acceptance: `scripts/test-prose-lint.js` covers every rule identifier, exact line and column reporting, multiline ordering, null input, masked regions, context-sensitive non-matches, artifact integration, warning severity, deterministic output, and the positive and negative fixture thresholds in this PRD. + - [DECISION] Acceptance: the full test runner executes the focused suite, and the static self-dogfood path scans every eligible Markdown or MDX file in the fixed `skills/`, `specialists/`, `agents/`, and `references/` scope without treating advisory warnings as a user-artifact gate failure. + - [DECISION] Acceptance: self-dogfood output identifies every warning by relative path, line, rule identifier, and short excerpt, and the test fails only for scanner errors, nondeterministic results, unexplained scope omissions, malformed findings, or an unreviewed increase from the recorded baseline. + +- P-MUST-34 [DECISION] Godpowers must make `god-docs-writer` and `god-launch-strategist` apply the shared prose guidance and post-draft audit according to the output type they own. + - [DECISION] Acceptance: `god-docs-writer` prefers direct factual explanations, exact repository names, verified commands, and concrete before-and-after behavior while preserving required terminology, quoted source text, runbook steps, and evidence language. + - [DECISION] Acceptance: `god-launch-strategist` removes empty claims and decoration words but preserves explicit founder or product voice, approved positioning, channel constraints, and the existing human pause for brand tone or final headline approval. + - [DECISION] Acceptance: operational status and engineering artifacts default to direct and neutral language, public product copy follows its approved brand voice, and neither specialist presents the advisory scanner as proof that prose is human-authored or objectively good. + - [DECISION] Acceptance: a repository-surface test fails if either specialist loses its reference to the shared contract or its output-specific post-draft audit obligation. + +- P-MUST-35 [DECISION] Godpowers must acknowledge the upstream pstack `unslop` inspiration, preserve independent authorship, and carry the feature through the existing documentation, packaging, and release checks. + - [DECISION] Acceptance: `INSPIRATION.md` links to the upstream Cursor pstack `unslop` skill, names only the plain and concrete prose plus post-draft audit ideas that influenced Godpowers, and states that no upstream prose, rule catalog, code, fixture, or result is vendored. + - [DECISION] Acceptance: the implementation introduces no pstack runtime, model call, external service, Python requirement, new slash command, or new npm production dependency. + - [DECISION] Acceptance: `lib/README.md`, validation documentation, `CHANGELOG.md`, and `RELEASE.md` explain the advisory behavior, U-12 integration, false-positive boundary, and output-type voice treatment before publication. + - [DECISION] Acceptance: package-content verification includes `lib/prose-lint.js`, focused and full tests pass, `npm run test:audit` and `npm run pack:check` pass, and `npm run release:check` passes before a maintainer performs any tag, GitHub Release, or npm publish action. + +### SHOULD + +- [DECISION] This feature has no SHOULD requirements because partial delivery would either leave guidance unenforced, leave warnings unexplained, or ship a release surface without its tests and provenance record. + +### COULD + +- [DECISION] This feature has no COULD requirements because rewrite automation, personalized voice models, and additional commands are outside the bounded prose-quality increment. + +## 5. Non-Functional Requirements + +| Category | Requirement | Source | +|---|---|---| +| Latency | [DECISION] `lib/prose-lint.js` must scan a 1 MiB prose fixture within 250 milliseconds at p95 across 20 runs on the release test host. | [DECISION] P-MUST-31 local advisory scan. | +| Availability | [DECISION] Guidance, scanning, artifact integration, and self-dogfood must work offline in 100 percent of Node.js 18, 20, and 22 CI jobs without a model credential or external service. | [DECISION] Godpowers host and release contract. | +| Security | [DECISION] The scanner must treat input as inert text, execute no embedded content, make no network request, retain no input outside the caller-owned process, and return bounded excerpts of at most 160 characters. | [DECISION] Existing local validation trust boundary. | +| Scale | [DECISION] One scan must accept at least 1 MiB or 10,000 lines of UTF-8 text and return findings in source order without recursion over user-controlled structures. | [DECISION] Capacity above current planning and shared-reference artifacts. | +| Determinism | [DECISION] Identical text and options must produce byte-equivalent ordered findings after no timestamp, absolute path, locale, or environment field is added. | [DECISION] Disk-authoritative evidence posture. | +| Compatibility | [DECISION] The implementation must remain CommonJS, use Node.js built-ins only, preserve Node.js 18 or newer support, and add no npm production dependency. | [DECISION] ADR-002 and stack Pillar. | +| Advisory safety | [DECISION] U-12 findings must remain warnings in artifact summaries and must not fail existing artifact gates, mutate prose, or trigger an automatic rewrite. | [DECISION] User-authorized feature boundary. | +| Precision | [DECISION] Rules must match sentence patterns or structure with explanatory context and must not treat any standalone vocabulary item as a universal failure. | [DECISION] No-blanket-word-ban boundary. | + +## Scope and No-Gos + +### In Scope + +- [DECISION] Shared plain and concrete prose guidance plus one explicit post-draft audit in `references/shared/VOICE.md`. +- [DECISION] A pure dependency-free `lib/prose-lint.js` scanner with deterministic structured findings and context-sensitive exclusions. +- [DECISION] Universal U-12 warning integration through the existing have-nots validator and artifact-linter report path. +- [DECISION] Focused behavior, precision, performance, determinism, artifact-integration, and self-dogfood tests in the existing test runner and static-check surface. +- [DECISION] Output-specific adoption by the documentation and launch specialists, including preservation of verified technical language and user-approved brand voice. +- [DECISION] Upstream inspiration acknowledgement, library and validation docs, changelog and release notes, package verification, and the existing release gate. + +### Explicitly Not In Scope + +- [DECISION] This feature will not add `/god-unslop`, `/god-prose-lint`, or any other slash command, route, recipe, workflow, or specialist agent. +- [DECISION] This feature will not copy, vendor, translate, or lightly rewrite the upstream pstack `unslop` prose, pattern catalog, examples, code, tests, or results. +- [DECISION] This feature will not ban words such as `surface`, `harness`, `primitive`, `robust`, or `leverage` without sentence context and a concrete reason for the warning. +- [DECISION] This feature will not rewrite files, auto-apply suggestions, call a language model, infer human authorship, or score whether a person has soul, taste, or originality. +- [DECISION] This feature will not force one voice across planning artifacts, engineering docs, operational status, launch copy, quoted source material, and user-approved brand language. +- [DECISION] This feature will not make advisory U-12 warnings block user artifact gates or weaken existing blocking errors, security checks, package checks, or release approval boundaries. +- [DECISION] This feature will not add a production dependency, a Python runtime, a hosted prose service, analytics collection, or persistence for scanned text. + +## 7. Appetite + +- [DECISION] Time budget: implement, document, dogfood, review, and reach release-ready evidence within 5 working days and one minor-release cycle. +- [DECISION] Resource budget: one primary maintainer using existing Godpowers planning, execution, review, docs, and launch specialists, with no new paid service or standing operations role. +- [DECISION] Technical constraints: preserve CommonJS, Node.js 18, 20, and 22 compatibility, zero core production dependencies, the frozen slash-command surface, existing artifact-linter APIs, and advisory warning semantics. +- [DECISION] Delivery constraint: implementation must use focused tests first, requirement linkage annotations, independent specification and quality review, self-dogfood, full tests, audit checks, package verification, release notes, and `npm run release:check` before publication. + +## 8. Open Questions + +| Question | Owner | Due Date | Resolution | +|---|---|---|---| +| [OPEN QUESTION] Should any reviewed U-12 rule become blocking after two release candidates provide precision and maintainer-override evidence? | [OPEN QUESTION] Godpowers maintainer. | [OPEN QUESTION] 2026-11-30. | [OPEN QUESTION] Unresolved; the safe default keeps all prose-quality findings advisory. | +| [OPEN QUESTION] Should a future feature let repositories configure output-type voice rules after the fixed engineering, documentation, operational, and launch classes have two release cycles of use? | [OPEN QUESTION] Godpowers maintainer. | [OPEN QUESTION] 2026-11-30. | [OPEN QUESTION] Unresolved; the safe default keeps configuration out of this feature. | + +## Risks and Mitigations + +| Risk | Mitigation | +|---|---| +| [HYPOTHESIS] Context-free phrase matching could flag exact technical terms or user-approved language and train contributors to write around the checker. | [DECISION] Match sentence patterns, mask non-prose regions, require clean context fixtures, explain each warning, and keep findings advisory. | +| [HYPOTHESIS] One neutral engineering voice could erase a founder's approved launch tone or make every Godpowers output sound identical. | [DECISION] Scope voice by output type, preserve the launch specialist's human approval pauses, and treat plain and concrete as clarity constraints rather than a personality template. | +| [HYPOTHESIS] A self-dogfood baseline could hide existing warnings or turn every upstream reference update into unrelated cleanup. | [DECISION] Report the complete warning set, record reviewed baseline changes explicitly, and fail only on scanner defects, scope omissions, malformed findings, nondeterminism, or unexplained warning growth. | +| [HYPOTHESIS] An upstream acknowledgement could drift into copied wording or imply that Godpowers vendors pstack. | [DECISION] Keep acknowledgement in `INSPIRATION.md`, name the limited ideas adopted, state the no-vendoring boundary, and test that the runtime remains dependency-free and command-neutral. | + +## Have-Nots Checklist + +- [x] [DECISION] Every substantive artifact sentence carries exactly one decision, hypothesis, or open-question label. +- [x] [DECISION] The problem statement names Godpowers-specific validation, specialist, artifact, and reader failures and fails the substitution test. +- [x] [DECISION] Every success metric has a number, timeline, and measurement method. +- [x] [DECISION] Functional requirements use stable IDs `P-MUST-30` through `P-MUST-35`, and every requirement has observable acceptance criteria. +- [x] [DECISION] Scope explicitly excludes new commands, blanket word bans, copied upstream prose, automatic rewrites, universal voice flattening, blocking U-12 warnings, and new production dependencies. +- [x] [DECISION] Every open question has a role owner, exact due date, and safe default that does not block implementation. +- [x] [DECISION] The PRD preserves the root product PRD, current architecture, current roadmap, Pillars truth, pure-skill runtime, and release approval boundaries. diff --git a/.godpowers/launch/PREPUBLICATION.mdx b/.godpowers/launch/PREPUBLICATION.mdx index 2e92ace..d65699a 100644 --- a/.godpowers/launch/PREPUBLICATION.mdx +++ b/.godpowers/launch/PREPUBLICATION.mdx @@ -1,6 +1,6 @@ --- schema-version: 1 -checked_at: "2026-08-18T03:46:57.720Z" +checked_at: "2026-08-19T07:05:10.202Z" hardening_revision: "sha256:5f65a4de4bb0ab7dcce5e7fb11c182a77345f23b2e6f75077c549ccef4ce9268" hardening_updated_at: "2026-08-18T03:37:48.425Z" critical_total: 0 @@ -11,7 +11,7 @@ verdict: "pass" --- # Pre-Publication Gate -- [DECISION] Checked at: 2026-08-18T03:46:57.720Z. +- [DECISION] Checked at: 2026-08-19T07:05:10.202Z. - [DECISION] Hardening revision: sha256:5f65a4de4bb0ab7dcce5e7fb11c182a77345f23b2e6f75077c549ccef4ce9268. - [DECISION] Hardening updated at: 2026-08-18T03:37:48.425Z. - [DECISION] Critical findings: 0 total, 0 unresolved or accepted. diff --git a/.godpowers/links/LINKAGE-LOG.mdx b/.godpowers/links/LINKAGE-LOG.mdx index 293ed9e..3ca6d39 100644 --- a/.godpowers/links/LINKAGE-LOG.mdx +++ b/.godpowers/links/LINKAGE-LOG.mdx @@ -123,3 +123,21 @@ 2026-08-18T03:04:41.190Z + link: P-MUST-28 <-> lib/style-stats.js (via code-scanner) 2026-08-18T03:04:41.190Z + link: P-MUST-24 <-> scripts/run-tests.js (via code-scanner) 2026-08-18T03:04:41.190Z + link: P-MUST-24 <-> scripts/test-test-runner.js (via code-scanner) +2026-08-19T06:21:23.530Z + link: P-MUST-30 <-> SKILL.md (via code-scanner) +2026-08-19T06:21:23.530Z + link: P-MUST-32 <-> lib/have-nots-validator.js (via code-scanner) +2026-08-19T06:21:23.530Z + link: P-MUST-31 <-> lib/prose-lint.js (via code-scanner) +2026-08-19T06:21:23.530Z + link: P-MUST-33 <-> lib/prose-lint.js (via code-scanner) +2026-08-19T06:21:23.530Z + link: P-MUST-32 <-> references/HAVE-NOTS.md (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-30 <-> references/shared/VOICE.md (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-35 <-> scripts/check-package-contents.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-33 <-> scripts/run-tests.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-33 <-> scripts/static-check.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-32 <-> scripts/test-artifact-linter.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-30 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-31 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-32 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-33 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-34 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-35 <-> scripts/test-prose-lint.js (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-34 <-> specialists/god-docs-writer.md (via code-scanner) +2026-08-19T06:21:23.531Z + link: P-MUST-34 <-> specialists/god-launch-strategist.md (via code-scanner) diff --git a/.godpowers/links/artifact-to-code.json b/.godpowers/links/artifact-to-code.json index 5cf4ad8..818250c 100644 --- a/.godpowers/links/artifact-to-code.json +++ b/.godpowers/links/artifact-to-code.json @@ -249,5 +249,35 @@ "P-MUST-24": [ "scripts/run-tests.js", "scripts/test-test-runner.js" + ], + "P-MUST-30": [ + "SKILL.md", + "references/shared/VOICE.md", + "scripts/test-prose-lint.js" + ], + "P-MUST-32": [ + "lib/have-nots-validator.js", + "references/HAVE-NOTS.md", + "scripts/test-artifact-linter.js", + "scripts/test-prose-lint.js" + ], + "P-MUST-31": [ + "lib/prose-lint.js", + "scripts/test-prose-lint.js" + ], + "P-MUST-33": [ + "lib/prose-lint.js", + "scripts/run-tests.js", + "scripts/static-check.js", + "scripts/test-prose-lint.js" + ], + "P-MUST-35": [ + "scripts/check-package-contents.js", + "scripts/test-prose-lint.js" + ], + "P-MUST-34": [ + "scripts/test-prose-lint.js", + "specialists/god-docs-writer.md", + "specialists/god-launch-strategist.md" ] } diff --git a/.godpowers/links/code-to-artifact.json b/.godpowers/links/code-to-artifact.json index 141c78e..3daf212 100644 --- a/.godpowers/links/code-to-artifact.json +++ b/.godpowers/links/code-to-artifact.json @@ -36,7 +36,8 @@ "P-MUST-10" ], "lib/have-nots-validator.js": [ - "P-MUST-11" + "P-MUST-11", + "P-MUST-32" ], "lib/artifact-linter.js": [ "P-MUST-12" @@ -173,7 +174,8 @@ "P-MUST-01" ], "scripts/static-check.js": [ - "ADR-002" + "ADR-002", + "P-MUST-33" ], "scripts/test-integration.js": [ "P-MUST-01" @@ -291,9 +293,43 @@ "P-MUST-28" ], "scripts/run-tests.js": [ - "P-MUST-24" + "P-MUST-24", + "P-MUST-33" ], "scripts/test-test-runner.js": [ "P-MUST-24" + ], + "SKILL.md": [ + "P-MUST-30" + ], + "lib/prose-lint.js": [ + "P-MUST-31", + "P-MUST-33" + ], + "references/HAVE-NOTS.md": [ + "P-MUST-32" + ], + "references/shared/VOICE.md": [ + "P-MUST-30" + ], + "scripts/check-package-contents.js": [ + "P-MUST-35" + ], + "scripts/test-artifact-linter.js": [ + "P-MUST-32" + ], + "scripts/test-prose-lint.js": [ + "P-MUST-30", + "P-MUST-31", + "P-MUST-32", + "P-MUST-33", + "P-MUST-34", + "P-MUST-35" + ], + "specialists/god-docs-writer.md": [ + "P-MUST-34" + ], + "specialists/god-launch-strategist.md": [ + "P-MUST-34" ] } diff --git a/.godpowers/links/link-sources.json b/.godpowers/links/link-sources.json index 18d6b20..1602b5e 100644 --- a/.godpowers/links/link-sources.json +++ b/.godpowers/links/link-sources.json @@ -373,5 +373,59 @@ ], "P-MUST-24\u0000scripts/test-test-runner.js": [ "code-scanner" + ], + "P-MUST-30\u0000SKILL.md": [ + "code-scanner" + ], + "P-MUST-32\u0000lib/have-nots-validator.js": [ + "code-scanner" + ], + "P-MUST-31\u0000lib/prose-lint.js": [ + "code-scanner" + ], + "P-MUST-33\u0000lib/prose-lint.js": [ + "code-scanner" + ], + "P-MUST-32\u0000references/HAVE-NOTS.md": [ + "code-scanner" + ], + "P-MUST-30\u0000references/shared/VOICE.md": [ + "code-scanner" + ], + "P-MUST-35\u0000scripts/check-package-contents.js": [ + "code-scanner" + ], + "P-MUST-33\u0000scripts/run-tests.js": [ + "code-scanner" + ], + "P-MUST-33\u0000scripts/static-check.js": [ + "code-scanner" + ], + "P-MUST-32\u0000scripts/test-artifact-linter.js": [ + "code-scanner" + ], + "P-MUST-30\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-31\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-32\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-33\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-34\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-35\u0000scripts/test-prose-lint.js": [ + "code-scanner" + ], + "P-MUST-34\u0000specialists/god-docs-writer.md": [ + "code-scanner" + ], + "P-MUST-34\u0000specialists/god-launch-strategist.md": [ + "code-scanner" ] } diff --git a/.godpowers/prd/PRD.mdx b/.godpowers/prd/PRD.mdx index 5d017ae..737cabc 100644 --- a/.godpowers/prd/PRD.mdx +++ b/.godpowers/prd/PRD.mdx @@ -80,6 +80,12 @@ by `scripts/run-tests.js` and `npm run release:check`. - P-MUST-27 [DECISION] Derive a compact structured slice handoff from authoritative disk evidence on completion, pause, or ownership change -- Acceptance: the handoff remains at or below 8 KiB, protects requirements, blockers, failed verification, and next action, and never overrides conflicting current state. - P-MUST-28 [DECISION] Capture deterministic before-and-after maintainability evidence with signed deltas and sample counts for independent quality review -- Acceptance: source size, function lengths, comment density, markers, duplication, dependency edges, and cyclic components are reported through one exclusion policy and remain report-only for three release candidates. - P-MUST-29 [DECISION] Run a deterministic six-checkpoint evolution benchmark that reveals requirements one at a time and measures continued correctness and changeability -- Acceptance: every checkpoint records behavior, attempts, rework, changed lines, acceptance, handoff completeness, and maintainability deltas without network access, model credentials, or future-checkpoint visibility. +- P-MUST-30 [DECISION] Extend the shared voice contract with plain and concrete prose guidance plus a separate post-draft audit -- Acceptance: the contract tells agents to name actors, mechanisms, evidence, effects, and reader actions while preserving facts, requirements, code terms, quotations, and approved tone, and it includes at least three Godpowers-specific bad and good pairs. +- P-MUST-31 [DECISION] Provide a dependency-free deterministic advisory prose scanner -- Acceptance: `lib/prose-lint.js` returns ordered structured findings for high-confidence sentence patterns, masks non-prose Markdown regions, performs no file or network I/O, keeps excerpts at or below 160 characters, and scans a 1 MiB fixture within 250 milliseconds at p95 across 20 runs. +- P-MUST-32 [DECISION] Integrate prose findings into universal artifact validation as U-12 warnings -- Acceptance: prose-only findings leave the artifact error count at zero, existing blocking errors and universal severities remain unchanged, and the scanner never claims complete mechanical detection. +- P-MUST-33 [DECISION] Verify prose lint behavior, precision, performance, integration, and shipped-framework self-dogfood -- Acceptance: the focused 31-test suite passes, positive fixture recall is at least 90 percent, negative fixture false positives are at most 5 percent, and the full static path scans the fixed `skills/`, `specialists/`, `agents/`, and `references/` scope deterministically. +- P-MUST-34 [DECISION] Apply the shared prose contract through the documentation and launch specialists according to output type -- Acceptance: engineering documentation stays direct and evidence-based, launch copy preserves approved product voice and positioning, and both specialists run a separate post-draft audit without presenting warnings as proof of authorship or objective quality. +- P-MUST-35 [DECISION] Preserve independent authorship and release discipline for the pstack `unslop`-inspired prose-quality feature -- Acceptance: Godpowers records the limited upstream inspiration without vendoring prose, rules, code, fixtures, or results, adds no production dependency or command, packages the scanner, documents advisory behavior, and passes the full release gate before publication. ### SHOULD (V1 if time permits) - P-SHOULD-01 [DECISION] Set up a deploy pipeline that promotes the same artifact with tested rollback -- Acceptance: staging and production deploy the identical build. -- Validation: a rollback drill restores the prior version. @@ -111,6 +117,8 @@ by `scripts/run-tests.js` and `npm run release:check`. | Context economy | Agent-oriented passing output remains within 25 lines and 32 KiB, while context evidence stores identifiers and counts instead of source contents | [DECISION] | | Changeability evidence | Structured handoffs stay within 8 KiB and maintainability snapshots plus six-checkpoint benchmark summaries remain deterministic for identical inputs | [DECISION] | | Harness isolation | Compact verification, context planning, handoff generation, maintainability scanning, and the evolution benchmark run locally without network or model credentials | [DECISION] | +| Advisory prose quality | [DECISION] U-12 reports high-confidence sentence patterns as warnings without rewriting prose or weakening existing blocking artifact errors. | [DECISION] | +| Prose scan isolation | [DECISION] The dependency-free scanner treats caller input as inert text, performs no I/O, sanitizes control bytes, bounds excerpts to 160 characters, and remains deterministic for identical input. | [DECISION] | ## Scope and No-Gos @@ -157,6 +165,7 @@ Before declaring done, verify: ## PRD Changelog +- [DECISION] 2026-08-19: Added P-MUST-30 through P-MUST-35 because shared plain-language guidance, a dependency-free advisory U-12 scanner, output-specific specialist audits, focused self-dogfood evidence, and release provenance now form one verified prose-quality increment. - [DECISION] 2026-08-17: Added P-MUST-24 through P-MUST-29 because compact verification, explicit specialist context, conditional program design, structured handoffs, maintainability trajectories, and sequential evolution evidence now form one verified harness-quality increment. - [DECISION] 2026-08-17: Added P-MUST-23 and P-SHOULD-08 because the completed first-party provenance extension introduced an authorized external file-processing path, guarded output publication, and a separately operated upstream compatibility boundary. @@ -196,6 +205,12 @@ Before declaring done, verify: - **P-MUST-27** -> `lib/slice-handoff.js` - **P-MUST-28** -> `lib/maintainability-trajectory.js`, `lib/style-stats.js` - **P-MUST-29** -> `lib/evolution-benchmark.js` +- **P-MUST-30** -> `SKILL.md`, `references/shared/VOICE.md`, `scripts/test-prose-lint.js` +- **P-MUST-31** -> `lib/prose-lint.js`, `scripts/test-prose-lint.js` +- **P-MUST-32** -> `lib/have-nots-validator.js`, `references/HAVE-NOTS.md`, `scripts/test-artifact-linter.js`, `scripts/test-prose-lint.js` +- **P-MUST-33** -> `lib/prose-lint.js`, `scripts/run-tests.js`, `scripts/static-check.js`, `scripts/test-prose-lint.js` +- **P-MUST-34** -> `scripts/test-prose-lint.js`, `specialists/god-docs-writer.md`, `specialists/god-launch-strategist.md` +- **P-MUST-35** -> `scripts/check-package-contents.js`, `scripts/test-prose-lint.js` - **P-MUST-99** -> `scripts/test-linkage.js` ### P-SHOULD requirements diff --git a/.godpowers/roadmap/ROADMAP.mdx b/.godpowers/roadmap/ROADMAP.mdx index 544cf83..11158ea 100644 --- a/.godpowers/roadmap/ROADMAP.mdx +++ b/.godpowers/roadmap/ROADMAP.mdx @@ -1,18 +1,18 @@ # Roadmap -> Reconciled against the published Godpowers 5.5.0 baseline and current Godpowers 5.17.1 source. Increments carry a +> Reconciled against the published Godpowers 6.0.0 baseline and current Godpowers 6.1.0 source. Increments carry a > stable M-slug id, a Status, and the PRD requirement ids they deliver. Status is > derived from current artifacts, linkage, and executable evidence. ## Evidence Provenance -- [DECISION] Evidence generated at: `2026-08-17T15:03:08.771Z`. -- [DECISION] Source version: `6.0.0`. -- [DECISION] Source hash `.godpowers/prd/PRD.mdx`: `sha256:d70edef001750a67bab54c8ab5da3ccc15807c4db5cc81b5caceff8c259dc455`. -- [DECISION] Source hash `.godpowers/arch/ARCH.mdx`: `sha256:10ca122919058cf829dbd16649679adbb9d5d3b785ae1759e1028cf538ba5509`. +- [DECISION] Evidence generated at: `2026-08-19T06:45:21.095Z`. +- [DECISION] Source version: `6.1.0`. +- [DECISION] Source hash `.godpowers/prd/PRD.mdx`: `sha256:a9c6cc8ac62076152046d4885998527bfd77f1274b47dec1d1bc88a30f7ee475`. +- [DECISION] Source hash `.godpowers/arch/ARCH.mdx`: `sha256:ea1a27cfdcf250b7fd990d08cf7a0c9dc4b125f333f1490f3605b1f7a6834189`. - [DECISION] Source hash `.godpowers/stack/DECISION.mdx`: `sha256:e235b1b722f545a8907036c811ed52d68d90222978d2f2a37b4da1abb821473d`. - [DECISION] Planning completion is backed by passing PRD, design not-required, architecture, roadmap, and stack gates. -- [DECISION] Build, shipping, steady-state, advanced, and provenance-extension completion are backed by 35 linked requirements, the recorded final release gate for the published baseline, and the feature-scoped Stage 1, Stage 2, and hardening passes for current source. +- [DECISION] Build, shipping, steady-state, advanced, provenance-extension, harness-quality, and prose-quality completion are backed by 47 linked requirements, the recorded final release gate for the published baseline, and the current source's focused Stage 1, Stage 2, and hardening passes. ## Now (current source capabilities) @@ -185,6 +185,21 @@ - P-MUST-28 - P-MUST-29 +### Delivery Increment 15: Prose quality hardening +- **ID**: M-prose-quality-hardening +- **Status**: done +- **Goal**: [DECISION] Godpowers teaches plain and concrete prose, reports high-confidence theater sentences as advisory U-12 warnings, and preserves output-specific voice while keeping artifact gates and release safeguards intact. +- **Completion gate**: [DECISION] The focused 31-test prose suite, independent Stage 1 specification review, independent Stage 2 quality review, scoped hardening review, scanner package guard, and full release gate all pass before publication. +- **Size**: M +- **Depends on**: M-harness-quality-hardening, M-shipping +- **Features (from PRD)**: + - P-MUST-30 + - P-MUST-31 + - P-MUST-32 + - P-MUST-33 + - P-MUST-34 + - P-MUST-35 + ## Later (intent, not commitment) ### Theme: Deeper traceability and ecosystem @@ -208,6 +223,7 @@ ## Roadmap Changelog +- [DECISION] 2026-08-19: Added completed source increment M-prose-quality-hardening for P-MUST-30 through P-MUST-35 after the focused 31-test suite plus independent specification, quality, and hardening reviews passed, with package and full release gates required before publication. - [DECISION] 2026-08-17: Added completed source increment M-harness-quality-hardening for P-MUST-24 through P-MUST-29 after focused behavior suites and independent specification and quality reviews passed. - [DECISION] 2026-08-17: Added completed source increment M-authorized-ai-provenance-cleaning for P-MUST-23 and P-SHOULD-08 after independent specification, quality, and security reviews passed. diff --git a/.godpowers/runs/2026-08-19T05-19-58-295Z-024a364f/events.jsonl b/.godpowers/runs/2026-08-19T05-19-58-295Z-024a364f/events.jsonl new file mode 100644 index 0000000..769ea50 --- /dev/null +++ b/.godpowers/runs/2026-08-19T05-19-58-295Z-024a364f/events.jsonl @@ -0,0 +1,7 @@ +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","ts":"2026-08-19T05:19:58.296Z","name":"workflow.run","attrs":{"purpose":"prose-quality-hardening-program-design"},"prev":"genesis"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"user.resolve","attrs":{"subject":"program-design","decision":"approved","artifact":".godpowers/features/prose-quality-hardening/BUILD-PLAN.mdx","artifactHash":"sha256:cf4ba636609485c400e7f1c211db54cee1e1e7c0b0cb72fabf8953034e078790","reviewer":"user"},"ts":"2026-08-19T05:19:58.296Z","prev":"sha256:c5044752c0f722b40801cf3b94faeda6aa88fa82b5bec9a22f574f77e08087d5"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"gate.pass","attrs":{"gate":"stage-1-specification-review","feature":"prose-quality-hardening","verdict":"pass","evidence":"Independent specification review passed after Markdown fence and inline-code regressions were added."},"ts":"2026-08-19T06:24:23.959Z","prev":"sha256:e68c0c088a200ba4343b33c06ac69eeabdccb2e01366f6d8f6ff38afcc5d1706"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"gate.pass","attrs":{"gate":"stage-2-quality-review","feature":"prose-quality-hardening","verdict":"pass","evidence":"Independent quality review passed with bounded maintainability measures and no blocking finding."},"ts":"2026-08-19T06:24:23.960Z","prev":"sha256:7cd13dbdc204336966bc5f8bbe269fdc0f8bda02e8e9c83269e18c7bb00f65e0"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"gate.pass","attrs":{"gate":"scoped-hardening-review","feature":"prose-quality-hardening","verdict":"pass","criticalFindings":0,"evidence":"Scoped hardening review passed the inert-text, resource-bound, control-byte, and no-network checks."},"ts":"2026-08-19T06:24:23.960Z","prev":"sha256:93f4b36391613f9605d160a23bfdbb1933ab860f6871f24834502c409bfb2011"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"local-helper.complete","attrs":{"helper":"reverse-sync","feature":"prose-quality-hardening","filesScanned":840,"linksObserved":132,"linksAdded":18,"linksRemoved":0,"driftFindings":0,"reviewItems":0,"requirementsDone":47,"requirementsTotal":47},"ts":"2026-08-19T06:24:23.960Z","prev":"sha256:538a500888dc44e3d849c917fae35e0237e8b345b5f417ea9f76032c020f44d0"} +{"trace_id":"024a364fec655776d370866e1a912496","span_id":"3fade3516b3a8484","name":"workflow.complete","attrs":{"feature":"prose-quality-hardening","status":"source-complete-release-pending","releaseVersion":"6.1.0","requirements":["P-MUST-30","P-MUST-31","P-MUST-32","P-MUST-33","P-MUST-34","P-MUST-35"],"publicationComplete":false},"ts":"2026-08-19T06:24:23.960Z","prev":"sha256:2d1d657c8c3cdc2369cb0a04afff4b8f97fdcb3699f74fd3cfd751f5b3bad196"} diff --git a/.godpowers/state.json b/.godpowers/state.json index 55d2033..25e8d2d 100644 --- a/.godpowers/state.json +++ b/.godpowers/state.json @@ -69,18 +69,18 @@ "sync": { "status": "done", "artifact": "SYNC-LOG.mdx", - "artifact-hash": "sha256:c570ca8e8301fb96eafa74e9d807e01526a4039ae777de848cc6f78b58de578b", - "updated": "2026-08-18T04:04:11.227Z", - "notes": "Version 6.0.0 source, release evidence, npm integrity, GitHub identity, publication recovery, Pillars context, and authoritative deploy, observe, and launch state are synchronized." + "artifact-hash": "sha256:11ff31395e99c6b8b687391def43d3f7c85e7e903c6837ae52306cf5a6cd5fb2", + "updated": "2026-08-19T06:45:56.026Z", + "notes": "The 6.1.0 prose-quality source candidate, 47 requirement links, reviewed 31-test evidence, exact planning hashes, feature review evidence, and Pillars projections are synchronized; release and publication evidence remain pending." } }, "tier-1": { "prd": { "status": "done", "artifact": "prd/PRD.mdx", - "artifact-hash": "sha256:d70edef001750a67bab54c8ab5da3ccc15807c4db5cc81b5caceff8c259dc455", - "updated": "2026-08-18T03:37:48.425Z", - "notes": "P-MUST-24 through P-MUST-29 and the authorized provenance extension remain current for the 6.0.0 release." + "artifact-hash": "sha256:a9c6cc8ac62076152046d4885998527bfd77f1274b47dec1d1bc88a30f7ee475", + "updated": "2026-08-19T06:45:56.026Z", + "notes": "P-MUST-30 through P-MUST-35 define the completed prose-quality source candidate for 6.1.0; publication evidence remains pending." }, "design": { "status": "not-required", @@ -95,16 +95,16 @@ "arch": { "status": "done", "artifact": "arch/ARCH.mdx", - "artifact-hash": "sha256:10ca122919058cf829dbd16649679adbb9d5d3b785ae1759e1028cf538ba5509", - "updated": "2026-08-18T03:37:48.425Z", - "notes": "ADR-007 and ADR-008 cover pinned context, hash-bound design approval, state-authoritative handoffs, bounded measurements, benchmark isolation, and recoverable publication." + "artifact-hash": "sha256:ea1a27cfdcf250b7fd990d08cf7a0c9dc4b125f333f1490f3605b1f7a6834189", + "updated": "2026-08-19T06:24:23.963Z", + "notes": "C-prose-lint and ADR-009 define dependency-free inert scanning, warning-only U-12 integration, output-specific review, and promotion evidence." }, "roadmap": { "status": "done", "artifact": "roadmap/ROADMAP.mdx", - "artifact-hash": "sha256:738f36a99c6b31c9ef7707b68e8b16c8157358d28ac28022bc8e0692c7ffb0e6", - "updated": "2026-08-18T03:37:48.425Z", - "notes": "M-harness-quality-hardening is complete and source provenance is pinned to the final 6.0.0 planning artifacts." + "artifact-hash": "sha256:2ab406007e0f4185aade4b7943b0a94f98f7c08200981be614cb30c217981d34", + "updated": "2026-08-19T06:45:56.026Z", + "notes": "M-prose-quality-hardening is complete in source for P-MUST-30 through P-MUST-35; full release, CI, tag, registry, and install gates remain pending." }, "stack": { "status": "done", @@ -447,11 +447,11 @@ ], "lock": null, "deliverables": { - "updated": "2026-08-18T03:04:41.200Z", + "updated": "2026-08-19T06:21:23.536Z", "source": "PRD + ROADMAP + linkage + build state", "requirements": { - "total": 41, - "done": 41, + "total": 47, + "done": 47, "in-progress": 0, "untouched": 0, "percent": 100 @@ -569,6 +569,14 @@ "done": 6, "total": 6 }, + { + "id": "M-prose-quality-hardening", + "name": "Prose quality hardening", + "horizon": "next", + "status": "done", + "done": 6, + "total": 6 + }, { "id": "M-deeper-traceability-and-ecosystem", "name": "Deeper traceability and ecosystem", diff --git a/.godpowers/surface/REPO-SURFACE-SYNC.mdx b/.godpowers/surface/REPO-SURFACE-SYNC.mdx index 5de5d09..0e299a7 100644 --- a/.godpowers/surface/REPO-SURFACE-SYNC.mdx +++ b/.godpowers/surface/REPO-SURFACE-SYNC.mdx @@ -57,3 +57,9 @@ - [DECISION] Repo surface sync status before apply was fresh. - [DECISION] Repo surface sync status after apply is fresh. - [DECISION] No structural repository surface files were changed. + +## 2026-08-19T05:41:28.846Z + +- [DECISION] Repo surface sync status before apply was fresh. +- [DECISION] Repo surface sync status after apply is fresh. +- [DECISION] No structural repository surface files were changed. diff --git a/ARCHITECTURE-MAP.md b/ARCHITECTURE-MAP.md index 2b795cb..ec0fde4 100644 --- a/ARCHITECTURE-MAP.md +++ b/ARCHITECTURE-MAP.md @@ -642,7 +642,7 @@ godpowers/ ├── README.md, CHANGELOG.md, LICENSE, CONTRIBUTING.md, SECURITY.md, USERS.md ├── ARCHITECTURE.md <- Design doc ├── ARCHITECTURE-MAP.md <- This file -├── package.json (v6.0.0) +├── package.json (v6.1.0) ├── .github/workflows/ <- CI, npm publish, daily security audit │ ├── bin/install.js <- CLI installer (15 runtimes) @@ -675,7 +675,7 @@ godpowers/ │ ├── events.v1.json │ └── workflow.v1.json │ -├── lib/ <- Real JS runtime (112 modules) +├── lib/ <- Real JS runtime (113 modules) │ ├── state.js <- state model + drift detection │ ├── events.js <- OTel-shape event log + hash chain │ ├── router.js <- command routing @@ -692,6 +692,7 @@ godpowers/ │ ├── slice-handoff.js <- state-authoritative resume projection │ ├── maintainability-trajectory.js <- report-only code-shape deltas │ ├── evolution-benchmark.js <- six-checkpoint changeability evidence +│ ├── prose-lint.js <- dependency-free advisory prose scanner │ ├── dogfood-runner.js <- messy-repo dogfood gate │ ├── host-capabilities.js <- host guarantee detection │ ├── extension-authoring.js <- extension scaffold helper @@ -722,6 +723,7 @@ godpowers/ │ ├── test-dogfood-runner.js <- dogfood gate │ ├── test-host-capabilities.js <- host guarantee gate │ ├── test-extension-authoring.js <- extension scaffold gate +│ ├── test-prose-lint.js <- advisory prose scanner regression gate │ ├── test-runtime.js <- 13 unit tests for lib/ │ └── check-package-contents.js <- npm payload gate │ @@ -746,7 +748,7 @@ godpowers/ --- -## Numbers (as of v6.0.0) +## Numbers (as of v6.1.0) | Component | Count | |-----------|-------| @@ -757,16 +759,16 @@ godpowers/ | Specialist agents | 41 | | Workflows (core YAMLs) | 13 | | Intent recipes | 45 | -| Have-nots | 183 documented + 25 mechanically validated by linter | +| Have-nots | 183 documented + 26 mechanically validated by linter | | Templates | 15 | | Reference documents | 53 | | JSON Schemas | 7 | -| **JS runtime modules** | **112** | +| **JS runtime modules** | **113** | | **External integrations** | **5** (all detect-and-delegate; none vendored): Google Labs design.md, Impeccable, awesome-design-md, SkillUI, vercel-labs/agent-browser + Playwright | | Hooks | 2 | | Dogfood scenarios | 5 | | Documentation pages | 36 under docs/ plus reference material | -| **Test suites** | **110 script files plus integration tests** | +| **Test suites** | **111 script files plus integration tests** | | **Tests** | **Full behavioral suite gated by npm test** | | Supported AI runtimes | 15+ | | Verification axes | **3**: static (lint, design-spec, have-nots), linkage (drift, reverse-sync), runtime (headless browser audit + functional test) | diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 64953a9..d4365a6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,6 +1,6 @@ # Godpowers Architecture (v3 Design Target) -> Status: STABLE v6.0.0 published release (Godplans 1.1 two-artifact contracts, lifecycle-safe dispatch, complete GP and requirement traceability, and the existing production runtime surface) +> Status: STABLE v6.1.0 release candidate (Godplans 1.1 two-artifact contracts, lifecycle-safe dispatch, complete GP and requirement traceability, and the existing production runtime surface) > Authors: Godpowers Team > Last updated: 2026-08-06 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec1ec9..60ffd14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.1.0] - 2026-08-19 + +Prose-quality hardening release. Godpowers now separates meaning-preserving +post-draft review from its existing three-label and substitution checks, and +reports sentence-pattern findings through the universal artifact validator +without turning writing preferences into blocking errors. + +### Added + +- Shared plain and concrete post-draft audit in `references/shared/VOICE.md`. + The audit asks for named actors, mechanisms, evidence, observable effects, + and reader actions after meaning is settled, while preserving requirements, + verified facts, code terms, quotations, and user-approved tone. +- Dependency-free `lib/prose-lint.js` advisory scanner. Seven + context-sensitive rules cover filler, vague attribution, stacked hedging, + stock framing, inflated phrasing, empty conclusions, and dense sentences; + findings include stable rule ids, source locations, bounded excerpts, + explanations, and review suggestions. +- Universal U-12 integration in `lib/have-nots-validator.js`. Prose findings + remain warnings, do not increase the artifact error count, and do not weaken + existing blocking severities. +- Thirty-one focused regression tests plus a static self-dogfood gate with a + reviewed baseline of zero warnings across 233 shipped Markdown and MDX files + under `skills/`, `specialists/`, `agents/`, and `references/`. + +### Changed + +- Documentation review now favors direct factual explanations, exact repository + names, verified commands, and preserved runbook evidence. Launch review keeps + approved founder or product voice, positioning, channel constraints, and + brand decisions while engineering evidence stays direct and neutral. +- Public validation and runtime documentation now explains the advisory + boundary, masking behavior, false-positive limits, and 160-character excerpt + cap. `INSPIRATION.md` acknowledges pstack's unslop skill and records that no + upstream prose, rule catalog, code, fixture, or result is vendored. +- The npm package guard explicitly requires `lib/prose-lint.js`, and the full + test runner includes its focused suite. This release adds no slash command + and no root production dependency. + +### Security + +- Scanner input stays inert. The scanner performs no file-system write, + network call, subprocess launch, or dynamic evaluation. +- Markdown hardening masks opening YAML frontmatter, matching fenced code, + inline code, link destinations, and marked bad examples before matching. + Regression coverage includes nested delimiter lengths, malformed fence + closers, CRLF input, indentation boundaries, and double-backtick spans. +- Finding excerpts replace terminal control bytes and stop at 160 characters. + Adversarial delimiter scans and a 1 MiB fixture remain under the focused + 250-millisecond p95 bounds on the release test host. + ## [6.0.0] - 2026-08-17 Harness-quality and MCP v2 release. Godpowers now bounds the information an diff --git a/INSPIRATION.md b/INSPIRATION.md index 102aaa6..83db6a9 100644 --- a/INSPIRATION.md +++ b/INSPIRATION.md @@ -107,6 +107,17 @@ Beyond what was inherited, godpowers added: disk-authoritative substrate with dependency-free CommonJS helpers, bounded projections, independent reviews, and release evidence. +- **Meaning-preserving post-draft prose review** + (`references/shared/VOICE.md`, `lib/prose-lint.js`, and the U-12 integration + in `lib/have-nots-validator.js`). The scan, targeted rewrite, preservation of + meaning and intended tone, and final self-audit sequence were influenced by + pstack's unslop skill + ([github.com/cursor/plugins/blob/main/pstack/skills/unslop/SKILL.md](https://github.com/cursor/plugins/blob/main/pstack/skills/unslop/SKILL.md)). + Godpowers implements its own seven-rule advisory scanner, masking rules, + documentation and launch treatments, fixtures, performance bound, and + zero-warning self-dogfood gate. No upstream prose, rule catalog, code, + fixture, or result is vendored, and there is no runtime dependency. + ## Why this is the only mention Acknowledging influences once, in a single dedicated file, keeps the diff --git a/README.md b/README.md index 996652f..a1f4fdd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![CI](https://github.com/hannsxpeter/godpowers/actions/workflows/ci.yml/badge.svg)](https://github.com/hannsxpeter/godpowers/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -[![Version](https://img.shields.io/badge/version-6.0.0-blue)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-6.1.0-blue)](CHANGELOG.md) [![npm](https://img.shields.io/npm/v/godpowers.svg)](https://www.npmjs.com/package/godpowers) ### Your AI writes code fast. Godpowers makes it accountable. @@ -341,6 +341,7 @@ Every document and every change clears these automatic checks before it counts: | Substitution test | Generic filler that would read the same for any product | | Three-label test | Guesses quietly presented as decisions | | Have-nots | A named list of known failure modes, checked mechanically | +| Prose-pattern review | Filler, vague attribution, stacked hedges, stock framing, inflated phrasing, empty conclusions, and dense sentences | | Artifact-on-disk | The AI claiming "done" when the file was never written | | Critical-finding gate | Shipping with a known security hole | | TDD enforcement | Code without tests | @@ -352,6 +353,16 @@ every check and still be the wrong plan. The point is to eliminate generic, missing, and untraceable work, so that whatever human judgment is left is visible and yours to make. +The prose-pattern review reports advisory U-12 warnings. Those warnings never +block an artifact by themselves and never authorize an automatic rewrite. The +scanner looks for seven sentence patterns, not standalone words, so technical +uses of terms such as `surface`, `harness`, `primitive`, `robust`, and `leverage` +remain valid when the sentence states a concrete fact. + +Pattern matching can produce false positives and miss prose that needs +revision. A clean scan does not prove correctness, human authorship, or +objective quality. + ### It writes things down where you can find them Godpowers keeps its work in a `.godpowers/` folder inside your project, in files diff --git a/RELEASE.md b/RELEASE.md index 5815ca8..0fa694e 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,67 +1,133 @@ -# Godpowers 6.0.0 Release +# Godpowers 6.1.0 Release -> Status: Published and verified -> Date: 2026-08-17 +> Status: Release candidate +> Date: 2026-08-19 -- [DECISION] Godpowers 6.0.0 hardens the complete coding-agent harness: verification output, specialist context, larger-change design, slice resume, maintainability interpretation, and sequential changeability evidence now have executable contracts. -- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, 13 workflows, and 45 recipes; no command, specialist, workflow, or recipe was added, removed, or renamed. -- [DECISION] The core package contains 112 runtime library modules, supports Node.js 18 or newer, and keeps zero production dependencies. -- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.0.0, uses the MCP v2 server package, and requires Node.js 20 or newer. -- [DECISION] The package contains 110 focused test scripts, including the new harness-quality and authorized provenance suites. +- [DECISION] Godpowers 6.1.0 adds a shared post-draft prose audit, a pure + advisory scanner, and universal non-blocking U-12 findings without changing + the existing three-label, substitution, or blocking artifact checks. +- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, + 13 workflows, and 45 recipes; this release adds, removes, or renames + none of those surfaces. +- [DECISION] The core package contains 113 runtime library modules, supports + Node.js 18 or newer, and keeps zero production dependencies. +- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.1.0 and + requires Node.js 20 or newer. +- [DECISION] The repository contains 111 focused test scripts, and the current + root package-content check reports 646 files. -## Harness Quality +## Shared Prose Contract -- [DECISION] `npm test -- --agent-output` retains complete child bytes in a private log while presenting bounded aggregate success or focused first-failure evidence; normal output remains unchanged without the flag. -- [DECISION] All 41 specialists declare required context, optional context, inline inputs, and a positive token cap or an explicit no-project-context contract; file sources reject symlinks and retain pinned bytes, and every loadout event path preserves complete counts but no source contents. -- [DECISION] Medium and large Build plans require a program design approved by a hash-bound `user.resolve` event, while small plans require a recorded size and skip rationale; plan text cannot authorize itself. -- [DECISION] Slice handoffs stay at or below 8 KiB, preserve the recovery-critical fields, and remain projections under `.godpowers/state.json` authority. -- [DECISION] Maintainability trajectories report separate measures, signed deltas, and sample counts without turning one score into a build gate during the first three release candidates. -- [DECISION] The packaged evolution benchmark reveals exactly six requirements in order, runs behavior plus maintainability checks offline, isolates Git configuration and hooks, bounds inputs, baselines, traversal, and evidence, retains partial interruption evidence, and removes temporary state. +- [DECISION] `references/shared/VOICE.md` now runs one post-draft audit after + the draft's meaning, requirements, and evidence are settled. +- [DECISION] The audit checks each claim for a named actor, action or decision, + mechanism or source, observable effect, and reader action when one is needed. +- [DECISION] The audit preserves requirements, verified facts, code terms, + quotations, and user-approved tone; it does not replace the three-label rule + or substitution test. +- [DECISION] Godpowers-specific before-and-after pairs cover artifact decisions, + technical explanations, and public launch copy. -## Authorized Provenance Extension +## Advisory Scanner And Validation -- [DECISION] `@godpowers/provenance-pack` provides an optional skill, specialist, responsible-use contract, and dependency-free client for content the user owns or is authorized to process. -- [DECISION] Loopback is the default. Remote HTTPS and internal-network transfers require separate grants matching the exact normalized origin, credentials remain in environment variables, service responses are bounded and sanitized, and source bytes are preserved by default. -- [DECISION] The root package does not install or start the external inspection service, and the extension remains inactive until the user installs it. +- [DECISION] `lib/prose-lint.js` is a dependency-free CommonJS scanner that + treats input as inert text and returns ordered findings without file-system + writes, network access, subprocesses, or dynamic evaluation. +- [DECISION] Seven context-sensitive rules cover filler, vague attribution, + stacked hedging, stock framing, inflated phrasing, empty conclusions, and + dense sentences. +- [DECISION] Each finding contains a rule id, line, column, sanitized excerpt, + explanation, and review suggestion; excerpts stop at 160 characters. +- [DECISION] `lib/have-nots-validator.js` maps scanner findings to universal + U-12 warnings, and U-12 warnings never increase an artifact's error count. +- [DECISION] Existing artifact errors retain their blocking severities, and + the npm package guard explicitly requires `lib/prose-lint.js`. -## MCP v2 And Compatibility +## Output-Specific Review -- [DECISION] `@godpowers/mcp` moved from the legacy MCP SDK production server to `@modelcontextprotocol/server` v2 and `zod` 4.2. -- [DECISION] Protocol tests exercise the current v2 client and the legacy v1 client against the same nine read-only tools. -- [DECISION] Every MCP tool is pinned to the server-configured project root, and artifact lint paths reject symbolic links before canonical containment is verified. -- [DECISION] The MCP companion now requires Node.js 20 or newer, which is the breaking change that requires the 6.0.0 major version; the root CLI retains Node.js 18 support. -- [DECISION] First-party extension manifests and peer dependencies accept the Godpowers 6.x line. -- [DECISION] Root and MCP packages publish first under one staging tag, verify as an exact pair, and only then promote `latest`; reruns recover a missing half without republishing the existing version. -- [DECISION] First-party extension packs publish only from a matching version tag whose commit is already merged into `main`. +- [DECISION] The documentation specialist favors direct factual explanations, + exact repository names, verified commands, concrete behavior, runbook steps, + and preserved evidence language. +- [DECISION] The launch specialist may retain approved founder or product voice, + positioning, and channel constraints while operational status and + engineering evidence remain direct and neutral. +- [DECISION] Both specialists treat U-12 findings as human review prompts and + preserve the shared audit's meaning, evidence, and tone boundaries. +- [DECISION] `INSPIRATION.md` acknowledges the pstack unslop skill as an + influence on the scan, targeted rewrite, meaning and tone preservation, and + final self-audit sequence. +- [DECISION] No upstream prose, rule catalog, code, fixture, or result is + vendored, and no runtime dependency on the pstack plugin exists. + +## Safety And Parser Hardening + +- [DECISION] The scanner masks opening YAML frontmatter, matching backtick or + tilde fences, inline code, Markdown link destinations, and marked bad, avoid, + or wrong examples before applying prose rules. +- [DECISION] Fence closing requires the same delimiter character, at least the + opener's length, and whitespace-only trailing content; indentation and CRLF + behavior have focused regressions. +- [DECISION] Double-backtick spans may contain a single backtick, and adversarial + unique delimiter runs stay inside the focused 250-millisecond p95 limit. +- [DECISION] Finding excerpts replace terminal control bytes before formatting, + which keeps artifact reports safe for terminal display. + +## Advisory Boundaries + +- [DECISION] U-12 is advisory and non-blocking; a finding does not authorize an + automatic rewrite or prove that the original sentence is wrong. +- [DECISION] The scanner matches sentence patterns rather than standalone word + bans, so concrete technical uses of `surface`, `harness`, `primitive`, + `robust`, and `leverage` remain valid. +- [DECISION] Pattern matching can produce false positives or miss prose that + needs revision; a clean scan does not prove that text is human-authored, + correct, or objectively good. +- [DECISION] Masking handles the documented Markdown structures but is not a + complete Markdown parser, so human judgment remains the final authority for + prose changes. ## Validation -- [DECISION] Independent specification and quality reviews passed for compact verification, context loadouts, program design, slice handoffs, and maintainability trajectory behavior. -- [DECISION] The evolution benchmark quality review exposed and drove repairs for symlink containment, network guard bypasses, interruption cleanup, evidence bounds, Git metadata and hooks, baseline resource limits, invalid numeric evidence, canonical handoff validation, falsy handoff substitution, and test-temporary cleanup; the repaired focused suite passes 18 checks. -- [DECISION] The release hardening review exposed and drove repairs for MCP root containment, authoritative plan approval, context identity pinning, exact-origin consent, universal event bounds, resource-bounded scans, recoverable pair publication, and merged-tag pack publication. -- [DECISION] Provenance client and pack suites pass 20 and 14 checks, the extension publication suite passes 65 checks, and the MCP protocol suite passes with modern and legacy clients. -- [DECISION] The final local release gate passes 114 test commands and 3,113 checks, 94.64 percent line coverage, 79.8 percent branch coverage, the 70 percent per-file floor across 110 included runtime modules, zero dependency vulnerabilities, 140 self-project truth checks, synchronized Mythify 5.6.0 evidence provenance, and root plus MCP package-content verification. -- [DECISION] The pre-publication gate passes against hardening revision `sha256:5f65a4de4bb0ab7dcce5e7fb11c182a77345f23b2e6f75077c549ccef4ce9268` with zero unresolved or accepted Critical findings. -- [DECISION] Pull-request CI, merged-main CI, exact package publication, registry integrity, `latest` promotion, GitHub Release creation, and isolated published installation are complete. -- [DECISION] The tag workflow published both immutable packages with npm provenance under `release-6-0-0`; its immediate exact-version read encountered registry propagation delay, so the documented recovery path verified both versions and promoted MCP first and root second without republishing either artifact. -- [DECISION] The publication workflow now retries exact-version reads for up to 120 seconds before treating registry propagation as a failed pair verification. +- [DECISION] Independent Stage 1 specification review, Stage 2 quality review, + and scoped hardening review passed for the prose-quality feature. +- [DECISION] `node scripts/test-prose-lint.js` passes 31 of 31 focused tests. +- [DECISION] `node scripts/test-artifact-linter.js` passes 73 of 73 tests. +- [DECISION] `node scripts/static-check.js` passes 35 of 35 checks and reports + zero prose warnings across 233 shipped Markdown and MDX files. +- [DECISION] `node scripts/test-voice-lint.js` passes 11 of 11 tests. +- [DECISION] The current package-content check reports 646 root package files + and includes `lib/prose-lint.js` in the required payload. +- [DECISION] The feature-branch full release gate passes every test command in + 83 seconds with 94.68 percent line coverage and zero production dependency + vulnerabilities. +- [DECISION] Pull-request CI, merged-main CI, the tag workflow, registry + verification, and the isolated published-install check remain pending and + are not claimed by this release candidate. ## Upgrade -- [DECISION] Install the root CLI with `npm install -g godpowers@6.0.0` or run it with `npx godpowers@6.0.0`. -- [DECISION] Root CLI users have no state migration, artifact migration, command rename, or production dependency change. -- [DECISION] MCP users must run Node.js 20 or newer before upgrading `@godpowers/mcp` to 6.0.0. -- [DECISION] Third-party extension maintainers should validate against 6.0.0 and widen any `<6.0.0` peer range deliberately. - -## Publication Evidence - -- [DECISION] Pull request 91 passed Node.js 18, 20, and 22 plus the package gate in CI run 32096760451 and merged as `main` commit `9eb6a5cbdff3399e6d65a5cc660bf135814de7b7`. -- [DECISION] Merged-main CI run 32097014555 passed the same Node.js matrix and package gate against the exact merge commit. -- [DECISION] Annotated tag `v6.0.0` resolves to merge commit `9eb6a5cbdff3399e6d65a5cc660bf135814de7b7`. -- [DECISION] Provenance workflow 32097275283 passed release identity, the full release gate, and the fresh pre-publication gate, then published `godpowers@6.0.0` and `@godpowers/mcp@6.0.0` under `release-6-0-0` with npm provenance. -- [DECISION] The workflow encountered an npm registry propagation delay during its immediate exact-version read and stopped before promotion; recovery verified both staged artifacts, promoted `@godpowers/mcp@6.0.0` first and `godpowers@6.0.0` second, and confirmed both `latest` tags resolve to 6.0.0. -- [DECISION] Root registry integrity is `sha512-R7tLOkMP9JhXZzYLIGOhXwgB6YIXKi5RjiiY1t7uNRvCpd2RlhexyoCImtu3zSOA2BgqrpF8R6cBKbkNOT6cnQ==` with shasum `e6f63897d83b06b21da20659202fe0614b24809e`. -- [DECISION] MCP registry integrity is `sha512-hfwyLGgjuPsh6yJeNq/SYgNZ3s8h5xxoil/R+288VmgFrXHqTzBLWfgAc361gKPG2VTLoVFMbC3mNk56FQJomA==` with shasum `6c70dc38f938a7852da0cc7ea570d1d7cc0b1395`. -- [DECISION] Isolated exact-version verification with `node scripts/verify-published-install.js godpowers@6.0.0` passes Quick Proof, read-only project inspection, dashboard, next route, Claude install, and Codex install checks. -- [DECISION] The published MCP executable resolves through `npx -y -p @godpowers/mcp@6.0.0 godpowers-mcp --help` on Node.js 20 or newer. -- [DECISION] GitHub Release `v6.0.0` is published at `https://github.com/hannsxpeter/godpowers/releases/tag/v6.0.0` as the notes and tag record; npm remains the authoritative package artifact source. +- [DECISION] After publication, install the root CLI with + `npm install -g godpowers@6.1.0` or run it with `npx godpowers@6.1.0`. +- [DECISION] Root CLI users need no state migration, artifact migration, + command rename, or production dependency change for this upgrade. +- [DECISION] MCP users must run Node.js 20 or newer before upgrading + `@godpowers/mcp` to 6.1.0; the root CLI retains Node.js 18 support. +- [DECISION] Existing automation may continue treating artifact errors as its + blocking signal because the new U-12 findings remain warnings. + +## Pending Publication Evidence + +- [OPEN QUESTION] Pull-request number, review state, and CI run remain pending. + Owner: release operator. Due: before merge. +- [OPEN QUESTION] Clean-main full release-gate and pre-publication evidence + remain pending. Owner: release operator. Due: before tag creation. +- [OPEN QUESTION] Merge commit and merged-main CI run remain pending. Owner: + release operator. Due: before tag publication. +- [OPEN QUESTION] Annotated tag identity and provenance workflow run remain + pending. Owner: release operator. Due: before npm promotion. +- [OPEN QUESTION] Root and MCP registry integrity, shasums, and `latest` tag + verification remain pending. Owner: release operator. Due: before marking + this release published and verified. +- [OPEN QUESTION] GitHub Release URL and isolated exact-version install checks + remain pending. Owner: release operator. Due: before replacing this section + with completed publication evidence. diff --git a/SECURITY.md b/SECURITY.md index 45f0e2a..f95ce25 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -79,6 +79,7 @@ describe things that look like security boundaries and are not. | Version | Supported | |---------|-----------| +| 6.1.x | Release candidate | | 6.0.x | Yes | | 5.17.x | Security fixes only | | 5.16.x | Security fixes only | diff --git a/SKILL.md b/SKILL.md index 6d7eb34..0162e98 100644 --- a/SKILL.md +++ b/SKILL.md @@ -14,12 +14,13 @@ description: | license: MIT compatibility: "Works with Agent Skills compatible file-system agents. Supported hosts include Claude Code, Codex, Cursor, Windsurf, Gemini, OpenCode, Copilot, Augment, Trae, Cline, Kilo, Antigravity, Qwen, CodeBuddy, and Pi." metadata: - version: "6.0.0" + version: "6.1.0" updated: "2026-07-13" changelog: "CHANGELOG.md" tier: "full-arc" --- + # Godpowers You are Godpowers, an AI development system that takes projects from raw idea to @@ -397,6 +398,10 @@ rule binds, alongside the mechanical have-nots: scope uncertainty instead of guessing. - **Minimal formatting**: human-facing output is prose; reach for a list only when the content is a list. Artifacts keep the three-label structure. +- **Plain and concrete prose**: after meaning is settled, run the post-draft + audit in `references/shared/VOICE.md`. Prefer named actors, mechanisms, + evidence, observable effects, and clear reader actions while preserving + requirements, verified facts, code terms, quotations, and approved tone. - **Silent memory**: apply recalled memory and lessons by doing the right thing, not by narrating the retrieval. diff --git a/USERS.md b/USERS.md index 0db99eb..fed6e58 100644 --- a/USERS.md +++ b/USERS.md @@ -1,6 +1,6 @@ # Users and Community -The current source version is v6.0.0, and the latest published release is v6.0.0. +The current source version is v6.1.0, and the latest published release is v6.0.0. ## Track record: the honest version diff --git a/agents/arch.md b/agents/arch.md index 0c93dc7..3becdad 100644 --- a/agents/arch.md +++ b/agents/arch.md @@ -31,6 +31,7 @@ see_also: [quality, deploy] - [DECISION] Workflow plans use canonical helper IDs such as `source-sync-back` and `pillars-sync-plan`, while `/god-sync` output may show the shorter aliases `source-sync` and `pillars-sync`. - [DECISION] Godaudits 2.x interoperability reads `.godaudits/AUDIT.json` as canonical machine state, imports explicit check outcomes, evidence metadata, compliance, accepted risks, open questions, score caps, coverage, findings, and typed GA tasks, and uses generated or legacy AUDIT.mdx only as a fallback. - [DECISION] Godplans 1.1 interoperability treats `.godplans/PLAN.mdx` plus the pinned executable `.godplans/validate-plan.sh` as one contract, mirrors structural validation without executing repository shell during import, blocks GP dispatch outside `approved` or `executing`, and requires the official validator to pass immediately before work. +- [DECISION] `lib/prose-lint.js` stays inside the existing artifact-quality boundary as a dependency-free inert-text scanner with no I/O, bounded sanitized excerpts, and warning-only U-12 integration through `lib/have-nots-validator.js`. - [DECISION] The current executable audit status is fresh for repo surface, route quality, recipe coverage, and workflow planning. ## Rules @@ -46,6 +47,7 @@ see_also: [quality, deploy] - [HYPOTHESIS] Runtime behavior depends on host AI tools exposing skill and agent capabilities consistently. - [HYPOTHESIS] Local helper work must stay visible in closeouts so automatic work does not become hidden orchestration. - [HYPOTHESIS] A future Godplans validator hash requires an explicit Godpowers compatibility update so new shell bytes cannot become trusted silently. +- [HYPOTHESIS] A prose rule can become blocking only after release-candidate precision evidence and a maintainer-approved override design justify changing ADR-009. ## Touchpoints diff --git a/agents/context.md b/agents/context.md index eab2375..32f2166 100644 --- a/agents/context.md +++ b/agents/context.md @@ -15,7 +15,7 @@ see_also: [arch, quality, deploy] ## Context - [DECISION] Godpowers is an AI-powered development system delivered as slash commands and specialist agents inside AI coding tools. -- [DECISION] The package name is `godpowers`, and the current repository version is `6.0.0`. +- [DECISION] The package name is `godpowers`, and the current repository version is `6.1.0`. - [DECISION] The primary audience is solo founders and small engineering teams using AI coding tools who need accountable production workflow discipline without enterprise process. - [DECISION] The product promise is one slash-command arc from idea to hardened, observable, launch-ready software with traceable artifacts on disk. - [DECISION] Godpowers uses a pure-skill model where `npx godpowers` installs runtime files and in-tool slash commands perform work. @@ -54,6 +54,8 @@ see_also: [arch, quality, deploy] ### Godpowers artifact sources - Sync mode: auto-applied by yolo. +- Related artifact: `.godpowers/prd/PRD.mdx`. +- Related artifact: `.godpowers/roadmap/ROADMAP.mdx`. - Related artifact: `.godpowers/state.json`. - Related artifact: `RELEASE.md`. - Rule: keep this pillar aligned when these artifacts change durable context truth. @@ -61,12 +63,32 @@ see_also: [arch, quality, deploy] ### Extracted durable signals From `RELEASE.md`: -- [DECISION] Godpowers 6.0.0 hardens the complete coding-agent harness: verification output, specialist context, larger-change design, slice resume, maintainability interpretation, and sequential changeability evidence now have executable contracts. -- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, 13 workflows, and 45 recipes; no command, specialist, workflow, or recipe was added, removed, or renamed. -- [DECISION] The core package contains 112 runtime library modules, supports Node.js 18 or newer, and keeps zero production dependencies. -- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.0.0, uses the MCP v2 server package, and requires Node.js 20 or newer. -- [DECISION] The package contains 110 focused test scripts, including the new harness-quality and authorized provenance suites. -- [DECISION] `npm test -- --agent-output` retains complete child bytes in a private log while presenting bounded aggregate success or focused first-failure evidence; normal output remains unchanged without the flag. -- [DECISION] All 41 specialists declare required context, optional context, inline inputs, and a positive token cap or an explicit no-project-context contract; file sources reject symlinks and retain pinned bytes, and every loadout event path preserves complete counts but no source contents. -- [DECISION] Medium and large Build plans require a program design approved by a hash-bound `user.resolve` event, while small plans require a recorded size and skip rationale; plan text cannot authorize itself. +- [DECISION] Godpowers 6.1.0 adds a shared post-draft prose audit, a pure advisory scanner, and universal non-blocking U-12 findings without changing the existing three-label, substitution, or blocking artifact checks. +- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, 13 workflows, and 45 recipes; this release adds, removes, or renames none of those surfaces. +- [DECISION] The core package contains 113 runtime library modules, supports Node.js 18 or newer, and keeps zero production dependencies. +- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.1.0 and requires Node.js 20 or newer. +- [DECISION] The repository contains 111 focused test scripts, and the current root package-content check reports 646 files. +- [DECISION] `references/shared/VOICE.md` now runs one post-draft audit after the draft's meaning, requirements, and evidence are settled. +- [DECISION] The audit checks each claim for a named actor, action or decision, mechanism or source, observable effect, and reader action when one is needed. +- [DECISION] The audit preserves requirements, verified facts, code terms, quotations, and user-approved tone; it does not replace the three-label rule or substitution test. + +From `.godpowers/prd/PRD.mdx`: +- [DECISION] AI coding agents like Claude Code can write code, but a single prompt cannot carry a project from raw idea to hardened production without losing the plan, skipping review, or forgetting what was already decided across sessions. +- [DECISION] Teams that adopt Claude Code hit 3 recurring failures: the agent narrates progress it did not actually make, the agent re-asks questions it already answered, and the produced artifacts (PRD, architecture, code) drift out of sync with each other within days. +- [DECISION] Primary: solo founders and small engineering teams (1 to 5 people) who use Claude Code or a compatible agent CLI daily and want to ship a real product, not a prototype, without hiring a separate planning function. +- [DECISION] Secondary: engineers inheriting a brownfield repository who need to reconstruct planning artifacts, map technical debt, and onboard an AI agent onto existing code without rewriting it from scratch. +- [HYPOTHESIS] A disk-authoritative workflow that re-derives state from files on every turn, gates every artifact against named failure modes, and traces each requirement to the code that satisfies it will remove most of that drift. +- [DECISION] Within 30 minutes of a fresh install, a first-time user can run one command (`/god-mode`) and reach a committed, test-green vertical slice, measured on the shipped dogfood fixtures. +- [DECISION] Within 10 minutes after a build completes, at least 95 percent of declared requirements trace to implementing code, measured by the linkage coverage percentage that the Godpowers dashboard reports. +- [DECISION] For every release candidate, all release-gate checks reach zero failures within the 60-minute verification window before publication, measured by `scripts/run-tests.js` and `npm run release:check`. + +From `.godpowers/roadmap/ROADMAP.mdx`: +- [DECISION] Evidence generated at: `2026-08-19T06:22:48.578Z`. +- [DECISION] Source version: `6.1.0`. +- [DECISION] Source hash `.godpowers/prd/PRD.mdx`: `sha256:7ac0f025625e6a182f31b0014dec0f2985e5791f1aa99b50dfa69db06e68aec2`. +- [DECISION] Source hash `.godpowers/arch/ARCH.mdx`: `sha256:ea1a27cfdcf250b7fd990d08cf7a0c9dc4b125f333f1490f3605b1f7a6834189`. +- [DECISION] Source hash `.godpowers/stack/DECISION.mdx`: `sha256:e235b1b722f545a8907036c811ed52d68d90222978d2f2a37b4da1abb821473d`. +- [DECISION] Planning completion is backed by passing PRD, design not-required, architecture, roadmap, and stack gates. +- [DECISION] Build, shipping, steady-state, advanced, provenance-extension, harness-quality, and prose-quality completion are backed by 47 linked requirements, the recorded final release gate for the published baseline, and the current source's focused Stage 1, Stage 2, and hardening passes. +- [DECISION] 2026-08-19: Added completed source increment M-prose-quality-hardening for P-MUST-30 through P-MUST-35 after the focused 31-test suite plus independent specification, quality, and hardening reviews passed, with package and full release gates required before publication. diff --git a/agents/deploy.md b/agents/deploy.md index 99a84d3..d2b7f0f 100644 --- a/agents/deploy.md +++ b/agents/deploy.md @@ -64,12 +64,12 @@ see_also: [security, observe] ### Extracted durable signals From `RELEASE.md`: -- [DECISION] Godpowers 6.0.0 hardens the complete coding-agent harness: verification output, specialist context, larger-change design, slice resume, maintainability interpretation, and sequential changeability evidence now have executable contracts. -- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, 13 workflows, and 45 recipes; no command, specialist, workflow, or recipe was added, removed, or renamed. -- [DECISION] The core package contains 112 runtime library modules, supports Node.js 18 or newer, and keeps zero production dependencies. -- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.0.0, uses the MCP v2 server package, and requires Node.js 20 or newer. -- [DECISION] The package contains 110 focused test scripts, including the new harness-quality and authorized provenance suites. -- [DECISION] `npm test -- --agent-output` retains complete child bytes in a private log while presenting bounded aggregate success or focused first-failure evidence; normal output remains unchanged without the flag. -- [DECISION] All 41 specialists declare required context, optional context, inline inputs, and a positive token cap or an explicit no-project-context contract; file sources reject symlinks and retain pinned bytes, and every loadout event path preserves complete counts but no source contents. -- [DECISION] Medium and large Build plans require a program design approved by a hash-bound `user.resolve` event, while small plans require a recorded size and skip rationale; plan text cannot authorize itself. +- [DECISION] Godpowers 6.1.0 adds a shared post-draft prose audit, a pure advisory scanner, and universal non-blocking U-12 findings without changing the existing three-label, substitution, or blocking artifact checks. +- [DECISION] The public surface contains 124 slash commands, 41 specialist agents, 13 workflows, and 45 recipes; this release adds, removes, or renames none of those surfaces. +- [DECISION] The core package contains 113 runtime library modules, supports Node.js 18 or newer, and keeps zero production dependencies. +- [DECISION] The read-only `@godpowers/mcp` companion shares version 6.1.0 and requires Node.js 20 or newer. +- [DECISION] The repository contains 111 focused test scripts, and the current root package-content check reports 646 files. +- [DECISION] `references/shared/VOICE.md` now runs one post-draft audit after the draft's meaning, requirements, and evidence are settled. +- [DECISION] The audit checks each claim for a named actor, action or decision, mechanism or source, observable effect, and reader action when one is needed. +- [DECISION] The audit preserves requirements, verified facts, code terms, quotations, and user-approved tone; it does not replace the three-label rule or substitution test. diff --git a/agents/quality.md b/agents/quality.md index 9d27046..d001301 100644 --- a/agents/quality.md +++ b/agents/quality.md @@ -21,6 +21,7 @@ see_also: [security, deploy] - [DECISION] `npm run test:quick-proof` checks README, Quick Proof, release verification, runtime expectations, and adoption canary alignment. - [DECISION] `npm run test:audit` runs dependency audit, `git diff --check`, and documentation surface count tests. - [DECISION] `npm run pack:check` verifies the npm package contains required runtime files and excludes local-only files. +- [DECISION] `node scripts/test-prose-lint.js` runs the focused 31-test prose-quality suite, including rule shape, masking, control-byte sanitization, precision thresholds, performance, U-12 integration, specialist contracts, package guard, and fixed-scope self-dogfood. - [DECISION] `npm run release:check` combines official Agent Skills validation, Pillars 1.1 behavior and conformance fixtures, per-file library coverage, the full test suite, audit checks, self-project truth checks, and package contents checks. - [DECISION] `npm run test:self-truth` blocks stale version, public surface, lifecycle, artifact, requirement, generated progress, and roadmap provenance claims. - [DECISION] The full test suite includes quick proof docs, repo-doc sync, repo-surface sync, automation surface sync, host capabilities, extension authoring, dogfood, Mode D, installer smoke, workflow runner, OTel, and extension publish-readiness checks. @@ -32,6 +33,7 @@ see_also: [security, deploy] - [DECISION] Medium and large Build plans require mechanically valid program-design sections plus affirmative human or YOLO approval; small plans require explicit sizing and skip rationales. - [DECISION] Independent quality review receives before-and-after maintainability measures with signed deltas and sample counts, but those values remain report-only for the first three release candidates. - [DECISION] `lib/evolution-benchmark.js` runs the packaged six-checkpoint scenario without network access or model credentials and retains deterministic JSON plus Markdown evidence. +- [DECISION] The full static path scans eligible Markdown and MDX under `skills/`, `specialists/`, `agents/`, and `references/` with the dependency-free prose scanner and requires any reviewed baseline increase to be explicit. ## Decisions @@ -40,6 +42,7 @@ see_also: [security, deploy] ## Rules - [DECISION] Artifact linter checks must catch em or en dashes, emojis, unlabeled paragraphs, phantom references, future-dated body timestamps, and selected PRD or ARCH failures. +- [DECISION] U-12 prose findings remain advisory warnings, never automatic rewrites or proof of human authorship, and never weaken an existing blocking artifact error. - [DECISION] CI tests Node `18`, Node `20`, and Node `22`. - [DECISION] Full release work must keep `CHANGELOG.md`, `README.md`, `RELEASE.md`, package metadata, GitHub release notes, npm version, and local installed runtime aligned. @@ -63,6 +66,18 @@ see_also: [security, deploy] ### Godpowers artifact sources - Sync mode: auto-applied by yolo. -- Related artifact: `docs/ROADMAP.md`. +- Related artifact: `.godpowers/roadmap/ROADMAP.mdx`. - Rule: keep this pillar aligned when these artifacts change durable quality truth. + +### Extracted durable signals + +From `.godpowers/roadmap/ROADMAP.mdx`: +- [DECISION] Evidence generated at: `2026-08-19T06:22:48.578Z`. +- [DECISION] Source version: `6.1.0`. +- [DECISION] Source hash `.godpowers/prd/PRD.mdx`: `sha256:7ac0f025625e6a182f31b0014dec0f2985e5791f1aa99b50dfa69db06e68aec2`. +- [DECISION] Source hash `.godpowers/arch/ARCH.mdx`: `sha256:ea1a27cfdcf250b7fd990d08cf7a0c9dc4b125f333f1490f3605b1f7a6834189`. +- [DECISION] Source hash `.godpowers/stack/DECISION.mdx`: `sha256:e235b1b722f545a8907036c811ed52d68d90222978d2f2a37b4da1abb821473d`. +- [DECISION] Planning completion is backed by passing PRD, design not-required, architecture, roadmap, and stack gates. +- [DECISION] Build, shipping, steady-state, advanced, provenance-extension, harness-quality, and prose-quality completion are backed by 47 linked requirements, the recorded final release gate for the published baseline, and the current source's focused Stage 1, Stage 2, and hardening passes. +- [DECISION] 2026-08-19: Added completed source increment M-prose-quality-hardening for P-MUST-30 through P-MUST-35 after the focused 31-test suite plus independent specification, quality, and hardening reviews passed, with package and full release gates required before publication. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index b538714..cbe94d2 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -3,7 +3,7 @@ > Status: ACTIVE > Model: Pure-skill for durable work. CLI provides install plus read-only status helpers. > Last updated: 2026-07-13 -> Current source: v6.0.0. Latest published: v6.0.0. +> Current source: v6.1.0. Latest published: v6.0.0. This roadmap tracks releases, what's shipped, and what is frozen during the 3.x public adoption window. Everything user-facing remains slash-command based. diff --git a/docs/concepts.md b/docs/concepts.md index 9068035..fa74f53 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -157,7 +157,7 @@ which. ### Have-nots A **have-not** is a named, specific way a document can be bad. There are -183 named failure modes. 25 are mechanical (regex-checkable); +183 named failure modes. 26 are mechanical (regex-checkable); the rest need judgment. A few examples: | Code | The failure | @@ -169,7 +169,7 @@ the rest need judgment. A few examples: | L-04 | A launch with no source attribution | | H-07 | A critical security finding recorded with no remediation options | -The full catalog lives in `references/HAVE-NOTS.md`. The mechanical 25 are wired +The full catalog lives in `references/HAVE-NOTS.md`. The mechanical 26 are wired into `lib/have-nots-validator.js` and enforced by `/god-lint`, which means they are not opinions. They either pass or they do not. diff --git a/docs/reference.md b/docs/reference.md index 5d8a8a6..ff8e1db 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -1,6 +1,6 @@ # Godpowers Reference -Complete command, agent, and artifact reference for v6.0.0. +Complete command, agent, and artifact reference for v6.1.0. **This page is a dictionary, not a tutorial.** It lists everything, which makes it useful for looking things up and a poor place to start. If you are new, read diff --git a/docs/validation.md b/docs/validation.md index 446abd1..e5641b9 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -134,6 +134,40 @@ Universal (apply to all artifacts): - **U-10** phantom reference (link to nonexistent file) - **U-11** future-dated timestamp in body - **U-01** generic claim (substitution test risk) +- **U-12** theater sentence pattern (advisory warning only) + +#### U-12 advisory prose scan + +`lib/prose-lint.js` is a pure, dependency-free scanner. It treats its input as +inert text and returns ordered findings with a rule id, line, column, excerpt, +message, and suggested review action. `lib/have-nots-validator.js` maps those +findings into universal U-12 warnings. A U-12 warning increments the warning +count but never the error count, so it does not block artifact advancement by +itself. + +The scanner has seven context-sensitive sentence-pattern rules: filler, vague +attribution, stacked hedging, stock framing, inflated phrasing, empty +conclusions, and dense sentences. Matching is bounded to one finding per rule +per line. It does not ban standalone words, and a clean scan does not prove that +prose is human-authored, correct, or objectively good. + +Before matching, the scanner masks opening YAML frontmatter, fenced code, +inline code, Markdown link destinations, and marked bad, avoid, or wrong +examples. It sanitizes terminal control characters from excerpts and limits +each excerpt to 160 characters. This masking is structural pattern matching, +not a complete Markdown parser, so findings remain prompts for human judgment. + +`scripts/static-check.js` also scans every Markdown and MDX file under +`skills/`, `specialists/`, `agents/`, and `references/`. The checked-in baseline +is zero warnings; warning growth fails that repository self-dogfood check until +the new finding is reviewed. + +Documentation and launch work share the post-draft audit in +`references/shared/VOICE.md`, then apply different output rules. Documentation +keeps engineering explanations direct and preserves exact repository names, +verified commands, runbook steps, and evidence language. Launch copy may keep +an approved founder or product voice, positioning, and channel constraints, +while operational status and engineering evidence stay direct and neutral. PRD-specific: - **P-04** success metric without timeline @@ -158,10 +192,10 @@ DESIGN-specific (via `lib/design-spec`): ### Mechanical vs interpretive Of the 183 documented have-nots in `references/HAVE-NOTS.md`: -- **25 are mechanical** (regex-checkable; in `lib/have-nots-validator.js`) -- **158 are interpretive** (judgment-required; documented for human + AI review) +- **26 are mechanical** (regex-checkable; in `lib/have-nots-validator.js`) +- **157 are interpretive** (judgment-required; documented for human + AI review) -The mechanical 25 are caught by `/god-lint`. The interpretive checks are +The mechanical 26 are caught by `/god-lint`. The interpretive checks are the responsibility of `god-auditor` (retroactive scoring) and the two-stage code review (`god-spec-reviewer` + `god-quality-reviewer`). @@ -200,7 +234,7 @@ Returns structured findings: ``` Errors block agent advancement (cannot auto-resolve, even under --yolo). -Warnings surface but don't block. +Warnings surface but don't block. This includes U-12 prose-pattern findings. ## Linkage axis diff --git a/lib/README.md b/lib/README.md index 63224db..cd80fe3 100644 --- a/lib/README.md +++ b/lib/README.md @@ -85,11 +85,20 @@ package-level integrations. | `evolution-benchmark.js` | Run the offline six-checkpoint changeability fixture and retain deterministic machine and human evidence. | | `findings-verdict.js` | Shared verdict authority for harden FINDINGS.mdx: one parser, two named policies (launch honors human-accepted risk, publication never does); no auditor-authored summary line satisfies a gate. | | `have-nots-validator.js` | Check artifacts against known failure modes. | +| `prose-lint.js` | Scan inert text for seven context-sensitive prose patterns and return ordered advisory findings without dependencies or file-system writes. | | `voice-lint.js` | Detect sycophancy and gratitude-loop filler (have-not U-14); backs the artifact linter and the shipped-prose self-dogfood. | | `meta-linter.js` | Validate Godpowers documentation and skill metadata. | | `story-validator.js` | Validate story artifacts and story lifecycle state. | | `style-stats.js` | Measure the style genome: comment density, naming-casing histograms, and function-length distribution per language, so `CODEDNA.md` carries measured numbers instead of estimates. | +`have-nots-validator.js` maps prose findings to advisory U-12 warnings, which +do not block an artifact by themselves. Pattern matching can produce false +positives and miss prose that needs revision. A clean scan does not prove +correctness, human authorship, or objective quality. + +Documentation defaults to direct, verified engineering language. Launch copy +may preserve an approved founder or product voice. + ## Design, context, and integrations | Module | Purpose | diff --git a/lib/have-nots-validator.js b/lib/have-nots-validator.js index e8749a4..840e978 100644 --- a/lib/have-nots-validator.js +++ b/lib/have-nots-validator.js @@ -1,4 +1,6 @@ /** + * Implements: P-MUST-32 + * * Have-Nots Validator * * Registry of mechanical checks against the 183 named have-nots from @@ -16,6 +18,7 @@ * U-02 unlabeled sentence mechanical (sentence scan + label check) * U-10 phantom reference mechanical (link scan + filesystem check) * U-11 future-dated timestamp mechanical (date parse vs today) + * U-12 theater sentence partial mechanical (prose-lint patterns) * U-14 sycophancy/gratitude loop mechanical (phrase scan via voice-lint) * P-04 metric without timeline mechanical (metric + time-word scan) * P-05 metric without method mechanical (metric + measurement-word) @@ -43,6 +46,7 @@ const fs = require('fs'); const path = require('path'); +const proseLint = require('./prose-lint'); const voiceLint = require('./voice-lint'); const GENERIC_NOUNS = [ @@ -864,6 +868,18 @@ function extractSection(content, headingRegex) { // Public API // ============================================================================ +/** U-12: theater prose (advisory sentence-pattern scan via prose-lint) */ +function checkTheaterProse(content, opts = {}) { + return proseLint.scan(content, opts.prose || opts).map((hit) => ({ + code: 'U-12', + severity: 'warning', + line: hit.line, + column: hit.column, + message: `${hit.message} Excerpt: "${hit.excerpt}"`, + suggestion: hit.suggestion + })); +} + /** U-14: sycophancy or gratitude loop (mechanical phrase scan via voice-lint) */ function checkSycophancy(content) { return voiceLint.scan(content).map((hit) => ({ @@ -972,6 +988,7 @@ const UNIVERSAL_CHECKS = [ { code: 'U-10', fn: checkPhantomRef }, { code: 'U-11', fn: checkFutureDate }, { code: 'U-01', fn: checkSubstitution }, + { code: 'U-12', fn: checkTheaterProse }, { code: 'U-14', fn: checkSycophancy } ]; @@ -1059,6 +1076,7 @@ module.exports = { checkPhantomRef, checkFutureDate, checkSubstitution, + checkTheaterProse, checkSycophancy, checkPrdMetricTimeline, checkPrdMetricMethod, diff --git a/lib/prose-lint.js b/lib/prose-lint.js new file mode 100644 index 0000000..87ffb1b --- /dev/null +++ b/lib/prose-lint.js @@ -0,0 +1,263 @@ +// Implements: P-MUST-31, P-MUST-33 +/** + * Pure advisory prose scanner. Input is inert text; output is an ordered list + * of source findings. The rules match sentence patterns, not standalone words. + */ + +const RULES = [ + { + id: 'filler', + re: /\b(?:it is important to note that|it should be noted that|it is worth noting that|needless to say|at the end of the day|in today'?s fast-paced world)\b/gi, + message: 'Filler pattern delays the claim without adding evidence or a decision.', + suggestion: 'Remove the setup and state the concrete claim directly.' + }, + { + id: 'vague-attribution', + re: /\b(?:experts agree|studies show|research suggests|industry observers say|many believe|it is widely believed|according to (?:some|many|various) (?:reports|experts|observers|sources))\b/gi, + message: 'Vague-attribution pattern makes a claim without naming the source or evidence.', + suggestion: 'Name the source and result, or state the claim as a hypothesis.' + }, + { + id: 'stacked-hedging', + match: matchStackedHedging, + message: 'Stacked-hedging pattern obscures whether the sentence is a claim or an open question.', + suggestion: 'Keep one necessary uncertainty marker and name the evidence that would settle it.' + }, + { + id: 'stock-framing', + re: /\b(?:game-changing|revolutionary|cutting-edge|world-class|best-in-class|next-generation)\s+(?:solution|platform|experience|capabilit(?:y|ies)|technology|tool|system|approach|workflow|product)\b/gi, + message: 'Stock-framing pattern praises a generic offering without an observable differentiator.', + suggestion: 'Replace the promotional frame with a named mechanism and verified effect.' + }, + { + id: 'inflated-phrasing', + match: matchInflatedPhrasing, + message: 'Inflated-phrasing pattern uses an indirect construction where a direct verb would be clearer.', + suggestion: 'Use the direct verb and keep the same factual commitment.' + }, + { + id: 'empty-conclusion', + re: /\b(?:this (?:highlights the importance of|underscores the need for|demonstrates the (?:power|value|importance) of)|overall,\s+this is a significant step forward|ultimately,\s+this paves the way for)\b/gi, + message: 'Empty-conclusion pattern announces significance without naming a result or next action.', + suggestion: 'State the observed result, decision, or next action instead.' + }, + { + id: 'dense-sentence', + match: matchDenseSentence, + message: 'Dense-sentence pattern combines many clauses with vague referents, making the action unclear.', + suggestion: 'Split the sentence and name the actor, mechanism, and observable result.' + } +]; + +function matchStackedHedging(line) { + const hedge = /\b(?:may|might|could|perhaps|possibly|likely|seems?|appears?|potentially|maybe)\b/gi; + const matches = [...line.matchAll(hedge)]; + return matches.length >= 3 ? matches[0] : null; +} + +function matchDenseSentence(line) { + const words = line.match(/[A-Za-z0-9][A-Za-z0-9'-]*/g) || []; + if (words.length < 45) return null; + const connectors = line.match(/\b(?:which|while|although|because|whereas|despite|thereby|that|when|how)\b/gi) || []; + if (connectors.length < 4) return null; + if (!/\b(?:this|it|they|thing|things|outcome|outcomes|way|ways)\b/i.test(line)) return null; + const index = line.search(/\S/); + return index === -1 ? null : { 0: line.slice(index), index }; +} + +function matchInflatedPhrasing(line) { + const indirect = /\b(?:is able to|has the ability to|serves to|in order to|functions as a way to)\b/i.exec(line); + if (indirect) return indirect; + return /^\s*(?:[-*]\s*)?(?:\[[^\]]+\]\s*)?(the fact that\b.*\b(?:is|was|remains)\s+(?:important|meaningful|significant|notable)\b)/i.exec(line); +} + +function spaces(text) { + return ' '.repeat(text.length); +} + +function leadingIndent(line) { + let index = 0; + let columns = 0; + while (index < line.length) { + if (line[index] === ' ') { + columns++; + index++; + continue; + } + if (line[index] === '\t') { + columns += 4 - (columns % 4); + index++; + continue; + } + break; + } + return { columns, index }; +} + +function maskInlineCode(line) { + const masked = line.split(''); + const runs = []; + let cursor = 0; + while (cursor < line.length) { + if (line[cursor] !== '`') { + cursor++; + continue; + } + const start = cursor; + while (cursor < line.length && line[cursor] === '`') cursor++; + runs.push({ start, end: cursor, length: cursor - start }); + } + + const nextSameLength = new Array(runs.length).fill(-1); + const nextByLength = new Map(); + for (let index = runs.length - 1; index >= 0; index--) { + const run = runs[index]; + if (nextByLength.has(run.length)) nextSameLength[index] = nextByLength.get(run.length); + nextByLength.set(run.length, index); + } + + let runIndex = 0; + while (runIndex < runs.length) { + const closerIndex = nextSameLength[runIndex]; + if (closerIndex === -1) { + runIndex++; + continue; + } + const opener = runs[runIndex]; + const closer = runs[closerIndex]; + for (let index = opener.start; index < closer.end; index++) masked[index] = ' '; + runIndex = closerIndex + 1; + } + return masked.join(''); +} + +function maskLinkDestinations(line) { + return line.replace(/\]\((?:[^()\\]|\\.)*\)/g, (destination) => { + return ']' + spaces(destination.slice(1)); + }); +} + +function maskedLines(text) { + const lines = text.split('\n'); + const masked = []; + const frontmatterEnd = lines[0] && /^\uFEFF?---[ \t]*\r?$/.test(lines[0]) + ? lines.findIndex((line, index) => index > 0 && /^---[ \t]*\r?$/.test(line)) + : -1; + let inFrontmatter = frontmatterEnd > 0; + let fence = null; + let badExampleIndent = null; + + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + const parseLine = line.endsWith('\r') ? line.slice(0, -1) : line; + const trimmed = parseLine.trim(); + + if (inFrontmatter) { + masked.push(spaces(line)); + if (index === frontmatterEnd) { + inFrontmatter = false; + } + continue; + } + + const indentation = leadingIndent(parseLine); + const content = parseLine.slice(indentation.index); + + if (fence !== null) { + const closingFenceMatch = indentation.columns <= 3 + ? content.match(/^(`{3,}|~{3,})[ \t]*$/) + : null; + if (closingFenceMatch && closingFenceMatch[1][0] === fence.character && + closingFenceMatch[1].length >= fence.length) { + fence = null; + } + masked.push(spaces(line)); + continue; + } + + if (indentation.columns >= 4 && /^(?:`{3,}|~{3,})/.test(content)) { + masked.push(spaces(line)); + continue; + } + + const fenceMatch = indentation.columns <= 3 + ? content.match(/^(`{3,}|~{3,})(.*)$/) + : null; + if (fenceMatch && !(fenceMatch[1][0] === '`' && fenceMatch[2].includes('`'))) { + fence = { character: fenceMatch[1][0], length: fenceMatch[1].length }; + masked.push(spaces(line)); + continue; + } + + const indent = (line.match(/^\s*/) || [''])[0].length; + const badMarker = /^\s*(?:[-*>]\s*)?\*{0,2}(?:bad|avoid|wrong)(?:\s+example)?\*{0,2}(?:\s*\([^)]*\))?\s*:/i.test(line); + if (badMarker) { + badExampleIndent = indent; + masked.push(spaces(line)); + continue; + } + if (badExampleIndent !== null) { + if (!trimmed) { + badExampleIndent = null; + } else if (indent > badExampleIndent) { + masked.push(spaces(line)); + continue; + } else { + badExampleIndent = null; + } + } + + masked.push(maskLinkDestinations(maskInlineCode(line))); + } + + return masked; +} + +function firstMatch(rule, line) { + if (rule.match) return rule.match(line); + rule.re.lastIndex = 0; + return rule.re.exec(line); +} + +function excerpt(line) { + const safe = line.replace(/[\u0000-\u001F\u007F-\u009F]/g, ' '); + const compact = safe.trim().replace(/\s+/g, ' '); + return compact.length <= 160 ? compact : compact.slice(0, 157) + '...'; +} + +function scan(text, options = {}) { + void options; + const source = String(text == null ? '' : text); + if (!source) return []; + const original = source.split('\n'); + const masked = maskedLines(source); + const findings = []; + + for (let lineIndex = 0; lineIndex < masked.length; lineIndex++) { + const line = masked[lineIndex]; + for (let ruleIndex = 0; ruleIndex < RULES.length; ruleIndex++) { + const rule = RULES[ruleIndex]; + const match = firstMatch(rule, line); + if (!match) continue; + findings.push({ + ruleId: rule.id, + line: lineIndex + 1, + column: match.index + 1, + excerpt: excerpt(original[lineIndex]), + message: rule.message, + suggestion: rule.suggestion, + _ruleIndex: ruleIndex + }); + } + } + + findings.sort((left, right) => { + return left.line - right.line || left.column - right.column || left._ruleIndex - right._ruleIndex; + }); + return findings.map(({ _ruleIndex, ...finding }) => finding); +} + +module.exports = { + RULES, + scan +}; diff --git a/lib/repo-doc-sync.js b/lib/repo-doc-sync.js index d7cda43..7a9d87b 100644 --- a/lib/repo-doc-sync.js +++ b/lib/repo-doc-sync.js @@ -4,6 +4,7 @@ * Keeps mechanical public repository claims aligned with the actual runtime * surface. Narrative docs remain human or specialist-agent owned. */ +// Implements: P-MUST-35 const fs = require('fs'); const path = require('path'); @@ -34,6 +35,31 @@ function packageVersion(projectRoot) { return readPackage(projectRoot).version || 'unknown'; } +function publishedVersion(projectRoot, currentVersion) { + const stateText = read(projectRoot, '.godpowers/state.json'); + if (stateText) { + try { + const state = JSON.parse(stateText); + const launch = state.tiers && state.tiers['tier-3'] && state.tiers['tier-3'].launch; + if (launch && /^\d+\.\d+\.\d+$/.test(launch['release-version'] || '')) { + return launch['release-version']; + } + } catch (err) { + // Fall through to the durable public marker when state is unavailable. + } + } + + for (const [relPath, regex] of [ + ['USERS.md', /latest published release is v(\d+\.\d+\.\d+)/i], + ['docs/ROADMAP.md', /Latest published: v(\d+\.\d+\.\d+)/], + ['USERS.md', /Godpowers is at v(\d+\.\d+\.\d+)\. Stable release\./] + ]) { + const match = read(projectRoot, relPath).match(regex); + if (match) return match[1]; + } + return currentVersion; +} + function counts(projectRoot) { return { skills: countFiles(projectRoot, 'skills', /^god.*\.md$/), @@ -45,18 +71,19 @@ function counts(projectRoot) { function expectedSurface(projectRoot) { const version = packageVersion(projectRoot); + const latestPublished = publishedVersion(projectRoot, version); const surfaceCounts = counts(projectRoot); - const published = read(projectRoot, 'USERS.md') - .includes(`latest published release is v${version}`); return { version, - published, + publishedVersion: latestPublished, + published: latestPublished === version, counts: surfaceCounts, surface: `${surfaceCounts.skills} skills, ${surfaceCounts.agents} agents`, commandSurface: `${surfaceCounts.skills} slash commands`, workflowSurface: `${surfaceCounts.workflows} workflows`, recipeSurface: `${surfaceCounts.recipes} recipes`, - minorSeries: version.split('.').slice(0, 2).join('.') + minorSeries: version.split('.').slice(0, 2).join('.'), + publishedMinorSeries: latestPublished.split('.').slice(0, 2).join('.') }; } @@ -89,18 +116,22 @@ function checkDefinitions(projectRoot) { { safeFix: true, reason: 'README command reference count mirrors files on disk' }), makeCheck('users-version', 'USERS.md', `current source version is v${expected.version}`, { safeFix: true, reason: 'user support source version mirrors package version' }), + makeCheck('users-published-version', 'USERS.md', + `latest published release is v${expected.publishedVersion}`, + { safeFix: true, reason: 'user support publication marker mirrors launch evidence' }), makeCheck('architecture-version', 'ARCHITECTURE.md', `STABLE v${expected.version}`, { safeFix: true, reason: 'architecture release marker mirrors package version' }), - ...(expected.published - ? [makeCheck('architecture-publication-status', 'ARCHITECTURE.md', - `STABLE v${expected.version} published release`, - { safeFix: true, reason: 'published versions must not retain release-candidate status' })] - : []), + makeCheck('architecture-publication-status', 'ARCHITECTURE.md', + `STABLE v${expected.version} ${expected.published ? 'published release' : 'release candidate'}`, + { safeFix: true, reason: 'architecture status mirrors source and published version equality' }), makeCheck('architecture-surface', 'ARCHITECTURE.md', `Core: ${expected.surface}, ${expected.workflowSurface}`, { safeFix: true, reason: 'architecture surface mirrors repository counts' }), makeCheck('roadmap-version', 'docs/ROADMAP.md', `Current source: v${expected.version}`, { safeFix: true, reason: 'roadmap current source marker mirrors package version' }), + makeCheck('roadmap-published-version', 'docs/ROADMAP.md', + `Latest published: v${expected.publishedVersion}`, + { safeFix: true, reason: 'roadmap publication marker mirrors launch evidence' }), makeCheck('roadmap-command-count', 'docs/ROADMAP.md', `**${expected.commandSurface}**`, { safeFix: true, reason: 'roadmap command count mirrors skills directory' }), makeCheck('roadmap-agent-count', 'docs/ROADMAP.md', @@ -127,8 +158,14 @@ function checkDefinitions(projectRoot) { { reason: 'release notes are narrative and should be reviewed before publish' }), makeCheck('changelog-version', 'CHANGELOG.md', `## [${expected.version}]`, { reason: 'changelog entries are narrative and should be curated' }), - makeCheck('security-supported-series', 'SECURITY.md', `${expected.minorSeries}.x`, - { reason: 'supported versions are release policy and should be reviewed' }), + makeCheck('security-published-series', 'SECURITY.md', + `| ${expected.publishedMinorSeries}.x | Yes |`, + { safeFix: true, reason: 'published series mirrors launch evidence' }), + ...(expected.published || expected.minorSeries === expected.publishedMinorSeries + ? [] + : [makeCheck('security-candidate-series', 'SECURITY.md', + `| ${expected.minorSeries}.x | Release candidate |`, + { safeFix: true, reason: 'unpublished source series remains a release candidate' })]), makeCheck('contributing-release-sync', 'CONTRIBUTING.md', 'repo documentation sync', { reason: 'contributor release guidance is narrative policy' }) ]; @@ -190,17 +227,20 @@ function safeFixContent(relPath, text, expected) { `all ${expected.counts.skills} skills + ${expected.counts.agents} agents` ); case 'USERS.md': + if (/Godpowers is at v[0-9]+\.[0-9]+\.[0-9]+\. Stable release\./.test(text)) { + return replaceOnce(text, + /Godpowers is at v[0-9]+\.[0-9]+\.[0-9]+\. Stable release\./, + `The current source version is v${expected.version}, and the latest published release is v${expected.publishedVersion}.`); + } return replaceOnce(text, - /(?:Godpowers is at|The current source version is) v[0-9]+\.[0-9]+\.[0-9]+(?:\. Stable release\.)?/g, - `The current source version is v${expected.version}`); + /The current source version is v[0-9]+\.[0-9]+\.[0-9]+, and the latest published release is v[0-9]+\.[0-9]+\.[0-9]+\./, + `The current source version is v${expected.version}, and the latest published release is v${expected.publishedVersion}.`); case 'ARCHITECTURE.md': return replaceOnce( replaceOnce( text, /STABLE v[0-9]+\.[0-9]+\.[0-9]+(?: (?:release candidate|published release))?/g, - expected.published - ? `STABLE v${expected.version} published release` - : `STABLE v${expected.version}` + `STABLE v${expected.version} ${expected.published ? 'published release' : 'release candidate'}` ), /Core: [0-9]+ skills, [0-9]+ agents, [0-9]+ workflows/g, `Core: ${expected.surface}, ${expected.workflowSurface}` @@ -208,14 +248,17 @@ function safeFixContent(relPath, text, expected) { case 'docs/ROADMAP.md': return replaceOnce( replaceOnce( - replaceOnce(text, /Current (?:shipped|source): v[0-9]+\.[0-9]+\.[0-9]+/g, - `Current source: v${expected.version}`), + replaceOnce(text, + /Current (?:shipped|source): v[0-9]+\.[0-9]+\.[0-9]+(?:\. Latest published: v[0-9]+\.[0-9]+\.[0-9]+\.)?/g, + `Current source: v${expected.version}. Latest published: v${expected.publishedVersion}.`), /\*\*[0-9]+ slash commands\*\*/g, `**${expected.commandSurface}**` ), /\*\*[0-9]+ specialist agents\*\*/g, `**${expected.counts.agents} specialist agents**` ); + case 'SECURITY.md': + return fixSecurityVersions(text, expected); case 'docs/reference.md': return replaceOnce( replaceOnce( @@ -243,6 +286,33 @@ function safeFixContent(relPath, text, expected) { } } +function fixSecurityVersions(text, expected) { + const publishedMinor = `${expected.publishedMinorSeries}.x`; + const candidateMinor = expected.published || expected.minorSeries === expected.publishedMinorSeries + ? null + : `${expected.minorSeries}.x`; + const desired = new Map([[publishedMinor, 'Yes']]); + if (candidateMinor) desired.set(candidateMinor, 'Release candidate'); + + let next = text.replace(/\|\s*([0-9]+\.[0-9]+\.x)\s*\|\s*([^|]+?)\s*\|/g, + (match, minor, status) => { + const replacement = desired.get(minor); + if (replacement) return `| ${minor} | ${replacement} |`; + if (/^(?:Yes|Release candidate)$/.test(status.trim())) { + return `| ${minor} | Security fixes only |`; + } + return match; + }); + + const missing = [...desired.entries()].filter(([minor]) => + !new RegExp(`\\|\\s*${minor.replace(/\./g, '\\.')}\\s*\\|`).test(next)); + if (missing.length > 0) { + const rows = missing.map(([minor, status]) => `| ${minor} | ${status} |\n`).join(''); + next = next.replace(/(\|\s*Version\s*\|\s*Supported\s*\|\n\|[-\s|]+\|\n)/, `$1${rows}`); + } + return next; +} + function fixPackageDescription(text, expected) { try { const parsed = JSON.parse(text); diff --git a/package-lock.json b/package-lock.json index 9387993..cfabbf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "godpowers", - "version": "6.0.0", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "godpowers", - "version": "6.0.0", + "version": "6.1.0", "license": "MIT", "workspaces": [ "packages/mcp" @@ -1726,7 +1726,7 @@ }, "packages/mcp": { "name": "@godpowers/mcp", - "version": "6.0.0", + "version": "6.1.0", "license": "MIT", "dependencies": { "@modelcontextprotocol/server": "^2.0.0", diff --git a/package.json b/package.json index 14ce234..2197e86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "godpowers", - "version": "6.0.0", + "version": "6.1.0", "description": "AI-powered development system: 124 slash commands and 41 specialist agents that take a project from raw idea to hardened production, then run it as an autonomous loop. Runs inside Claude Code, Codex, Cursor, Windsurf, Gemini, and 10+ other AI coding tools.", "bin": { "godpowers": "./bin/install.js" diff --git a/packages/mcp/package.json b/packages/mcp/package.json index a06e9ea..69a4e7c 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@godpowers/mcp", - "version": "6.0.0", + "version": "6.1.0", "description": "Read-only MCP server for Godpowers runtime status, routing, gates, artifact linting, and requirement tracing.", "bin": { "godpowers-mcp": "./bin/godpowers-mcp.js" diff --git a/references/HAVE-NOTS.md b/references/HAVE-NOTS.md index 7c10ba2..c617dbf 100644 --- a/references/HAVE-NOTS.md +++ b/references/HAVE-NOTS.md @@ -1,4 +1,5 @@ # Godpowers Have-Nots Catalog + > Named failure modes that disqualify an artifact. Each is grep-testable. > Spawned agents check their tier's have-nots before declaring done. @@ -91,7 +92,12 @@ Fail. ### U-12 Theater sentences Sentences that read fine but say nothing measurable, decidable, or testable. -Fail. +Human review fails the sentence. `lib/prose-lint.js` detects only a bounded set +of high-confidence sentence patterns, and `lib/have-nots-validator.js` reports +those findings as advisory U-12 warnings. A U-12 warning does not increase the +artifact error count, rewrite prose, or claim complete mechanical detection. +Review the sentence in context, then name the actor, mechanism, evidence, +observable result, or next action that is missing. ### U-13 MDX-unsafe artifact content Artifact body contains content that breaks MDX compilation or violates the diff --git a/references/shared/VOICE.md b/references/shared/VOICE.md index 90939a8..75c82e9 100644 --- a/references/shared/VOICE.md +++ b/references/shared/VOICE.md @@ -1,4 +1,5 @@ # Voice and Craft Contract + Cross-tier contract for how Godpowers agents communicate and constrain. Every agent adopts this alongside the have-nots. The have-nots catch what an output @@ -57,7 +58,49 @@ The pair resolves the ambiguity faster than a longer rule. Format: The canonical worked examples live in `references/HAVE-NOTS.md` on the highest-traffic have-nots (substitution, three-label, rubber-stamp). -## 5. Silent application of memory and lessons +## 5. Plain and concrete prose + +Prefer plain words, concrete actors, named mechanisms, and observable effects. +Keep exact code and product terms when they carry real meaning. A familiar word +is not a defect by itself; a sentence fails when it hides who acts, what changes, +how the claim is known, or what the reader should do. + +### Post-draft prose audit + +Run this audit once after the draft's meaning, requirements, and evidence are +settled: + +1. Inspect each claim for a named actor, action or decision, mechanism or source, + observable effect, and reader action when one is required. +2. Rewrite or remove only sentences that conceal those details. Do not narrate + the audit in the output. +3. Preserve requirements, verified facts, code terms, quotations, and + user-approved tone. Do not rewrite verified evidence to satisfy a style + preference. +4. Run the three-label rule and substitution test separately. This audit does + not replace either test. + +Godpowers-specific examples: + +- **Bad**: Artifact decision: "It is important to note that the storage approach + will support future needs." +- **Good**: Artifact decision: "Use local JSON state for offline inspection; + reconsider SQLite when concurrent writers exceed the state lock's capacity." + The decision, reason, and flip point preserve the original storage commitment. +- **Bad**: Technical explanation: "The validation harness provides robust + capabilities that help ensure quality." +- **Good**: Technical explanation: "`scripts/run-tests.js` invokes every + `scripts/test-*.js` suite, and `scripts/static-check.js` fails when a suite is + missing from that runner." The mechanism and failure behavior preserve the + original validation commitment. +- **Bad**: Public launch copy: "Godpowers is a revolutionary platform that + unlocks world-class engineering." +- **Good**: Public launch copy: "One `/god-mode` run leaves a PRD, architecture, + tested slices, deployment evidence, and hardening findings on disk for the next + coding-agent session." The product promise remains, now as an observable + outcome that can retain an approved brand voice. + +## 6. Silent application of memory and lessons Recalled memory and lessons (the `lib/evidence.js` memory store, lessons store, and reflections under `.godpowers/ledger/`) shape the work silently. They are diff --git a/scripts/check-package-contents.js b/scripts/check-package-contents.js index febf75e..d722808 100644 --- a/scripts/check-package-contents.js +++ b/scripts/check-package-contents.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +// Implements: P-MUST-35 /** * Assert that the npm package contains the load-bearing Godpowers runtime * surface and excludes local-only development files. @@ -38,6 +39,7 @@ const REQUIRED_FILES = [ 'lib/workflow-helper-groups.js', 'lib/artifact-map.js', 'lib/artifact-linter.js', + 'lib/prose-lint.js', 'lib/gate.js', 'lib/program-design.js', 'lib/slice-handoff.js', diff --git a/scripts/run-tests.js b/scripts/run-tests.js index bb932a4..f529b86 100644 --- a/scripts/run-tests.js +++ b/scripts/run-tests.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -// Implements: P-MUST-24 +// Implements: P-MUST-24, P-MUST-33 /** * Full test runner for the Godpowers release gate. */ @@ -44,6 +44,7 @@ const TEST_COMMANDS = [ [node, ['scripts/test-pillars.js']], [node, ['scripts/test-pillars-conformance.js']], [node, ['scripts/test-artifact-linter.js']], + [node, ['scripts/test-prose-lint.js']], [node, ['scripts/test-eval-set.js']], [node, ['scripts/test-voice-lint.js']], [node, ['scripts/test-artifact-diff.js']], diff --git a/scripts/static-check.js b/scripts/static-check.js index e29bd39..be82afe 100644 --- a/scripts/static-check.js +++ b/scripts/static-check.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +// Implements: P-MUST-33 /** * Dependency-free static checks for release-sensitive JavaScript surfaces. */ @@ -6,6 +7,7 @@ const fs = require('fs'); const path = require('path'); const { spawnSync } = require('child_process'); +const proseLint = require('../lib/prose-lint'); const ROOT = path.resolve(__dirname, '..'); const CHECK_DIRS = ['bin', 'lib', 'scripts', 'tests', 'packages']; @@ -357,6 +359,51 @@ test('shipped skill, specialist, and Pillars prose has no sycophancy filler (U-1 } }); +const PROSE_SCOPE = ['skills', 'specialists', 'agents', 'references']; +const PROSE_WARNING_BASELINE = 0; + +test('P-MUST-33: prose self-dogfood scans skills, specialists, agents, and references', () => { + const files = []; + for (const directory of PROSE_SCOPE) { + const base = path.join(ROOT, directory); + if (!fs.existsSync(base)) throw new Error(`prose scope missing: ${directory}`); + const scoped = walkMatching(base, file => /\.mdx?$/.test(file)).sort(); + if (scoped.length === 0) throw new Error(`prose scope has no eligible files: ${directory}`); + files.push(...scoped); + } + + const warnings = []; + for (const file of files.sort()) { + const content = fs.readFileSync(file, 'utf8'); + const first = proseLint.scan(content); + const second = proseLint.scan(content); + if (JSON.stringify(first) !== JSON.stringify(second)) { + throw new Error(`nondeterministic prose findings: ${path.relative(ROOT, file)}`); + } + for (const finding of first) { + const valid = finding && typeof finding.ruleId === 'string' && + Number.isInteger(finding.line) && finding.line > 0 && + Number.isInteger(finding.column) && finding.column > 0 && + typeof finding.excerpt === 'string' && finding.excerpt.length <= 160 && + typeof finding.message === 'string' && typeof finding.suggestion === 'string'; + if (!valid) { + throw new Error(`malformed prose finding: ${path.relative(ROOT, file)} ${JSON.stringify(finding)}`); + } + warnings.push({ file: path.relative(ROOT, file), ...finding }); + } + } + + console.log(` Prose self-dogfood baseline: ${PROSE_WARNING_BASELINE} warnings across ${files.length} files.`); + for (const warning of warnings) { + console.log(` Prose warning ${warning.file}:${warning.line} ${warning.ruleId}: ${warning.excerpt}`); + } + if (warnings.length > PROSE_WARNING_BASELINE) { + throw new Error( + `unreviewed prose warning growth: baseline ${PROSE_WARNING_BASELINE}, actual ${warnings.length}` + ); + } +}); + test('state-backed gates do not require markdown STATE view artifacts', () => { const artifactMap = require('../lib/artifact-map'); const expected = { diff --git a/scripts/test-artifact-linter.js b/scripts/test-artifact-linter.js index 4fa6fdd..553de3b 100644 --- a/scripts/test-artifact-linter.js +++ b/scripts/test-artifact-linter.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +// Implements: P-MUST-32 /** * Behavioral tests for lib/have-nots-validator.js + lib/artifact-linter.js. * @@ -188,6 +189,33 @@ test('U-01 accepts sentence with specific numbers', () => { if (findings.length !== 0) throw new Error(`expected 0, got ${findings.length}`); }); +// ============================================================================ +// U-12 theater prose advisory +// ============================================================================ + +test('P-MUST-32: U-12 maps prose findings to warnings with remediation', () => { + const findings = validator.runChecks( + '[DECISION] It is important to note that the release provides value.', + null + ); + const u12 = findingsByCode(findings, 'U-12'); + if (u12.length !== 1) throw new Error(`expected one U-12 finding, got ${u12.length}`); + if (u12[0].severity !== 'warning') throw new Error(`expected warning, got ${u12[0].severity}`); + if (!u12[0].message || !u12[0].suggestion) throw new Error('U-12 remediation is incomplete'); +}); + +test('P-MUST-32: U-12-only artifact retains zero errors and a warning count', () => { + const tmp = mkTmp(); + const file = path.join(tmp, 'NOTES.md'); + fs.writeFileSync(file, '[DECISION] Overall, this is a significant step forward.\n'); + const result = linter.lintFile(file, { projectRoot: tmp }); + if (result.summary.errors !== 0) throw new Error(`expected 0 errors, got ${result.summary.errors}`); + if (result.summary.byCode['U-12'] !== 1) throw new Error('U-12 per-code count missing'); + if (!linter.formatReport(result).includes('[U-12] WARNING line 1')) { + throw new Error('formatted report omitted the U-12 warning and line'); + } +}); + // ============================================================================ // P-04 metric without timeline // ============================================================================ diff --git a/scripts/test-prose-lint.js b/scripts/test-prose-lint.js new file mode 100644 index 0000000..198962e --- /dev/null +++ b/scripts/test-prose-lint.js @@ -0,0 +1,702 @@ +#!/usr/bin/env node +// Implements: P-MUST-30, P-MUST-31, P-MUST-32, P-MUST-33, P-MUST-34, P-MUST-35 + +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const proseLint = require('../lib/prose-lint'); +const validator = require('../lib/have-nots-validator'); +const artifactLinter = require('../lib/artifact-linter'); +const { test, assert, report } = require('./test-harness'); + +const ROOT = path.resolve(__dirname, '..'); + +function releaseTruthExpectations(sourceVersion, publishedVersion) { + const mode = sourceVersion === publishedVersion ? 'published' : 'candidate'; + const sourceMinor = `${sourceVersion.split('.').slice(0, 2).join('.')}.x`; + const publishedMinor = `${publishedVersion.split('.').slice(0, 2).join('.')}.x`; + const securityRows = [[publishedMinor, 'Yes']]; + if (sourceMinor !== publishedMinor) securityRows.push([sourceMinor, 'Release candidate']); + return { + mode, + usersMarker: `current source version is v${sourceVersion}, and the latest published release is v${publishedVersion}`, + roadmapMarker: `Current source: v${sourceVersion}. Latest published: v${publishedVersion}.`, + architectureStatus: `STABLE v${sourceVersion} ${mode === 'published' ? 'published release' : 'release candidate'}`, + releaseHeading: `# Godpowers ${sourceVersion} Release`, + releaseStatus: `Status: ${mode === 'published' ? 'Published and verified' : 'Release candidate'}`, + securityRows + }; +} + +const EXPECTED_RULE_IDS = [ + 'filler', + 'vague-attribution', + 'stacked-hedging', + 'stock-framing', + 'inflated-phrasing', + 'empty-conclusion', + 'dense-sentence' +]; + +const POSITIVE_FIXTURES = [ + 'It is important to note that the workflow provides value.', + 'It should be noted that this approach improves the process.', + 'It is worth noting that the system offers useful capabilities.', + 'Needless to say, this change matters for the future.', + 'At the end of the day, this solution is what teams need.', + "In today's fast-paced world, teams need better tools.", + + 'Experts agree that this platform will transform delivery.', + 'Studies show that the new workflow improves outcomes.', + 'Research suggests that this approach is more effective.', + 'Industry observers say that this capability will become essential.', + 'Many believe that this change will reshape engineering.', + 'It is widely believed that the system improves productivity.', + + 'The command may perhaps possibly improve the result.', + 'It seems likely that the workflow could perhaps help.', + 'The service might possibly perhaps become more reliable.', + 'We could perhaps maybe see better outcomes.', + 'It appears to potentially perhaps reduce risk.', + 'This likely may perhaps lead to improvement.', + + 'Godpowers provides a game-changing solution for modern teams.', + 'This revolutionary platform unlocks a new era of productivity.', + 'The release delivers a cutting-edge experience for developers.', + 'The product offers world-class capabilities for every workflow.', + 'This best-in-class solution changes how work gets done.', + 'Our next-generation platform creates unparalleled value.', + + 'The scanner is able to identify unclear prose.', + 'The workflow has the ability to improve delivery.', + 'The command serves to simplify the overall process.', + 'In order to improve quality, teams should review the output.', + 'The fact that the test passes is meaningful.', + 'The system functions as a way to enable better outcomes.', + + 'This highlights the importance of thoughtful engineering.', + 'This underscores the need for continued innovation.', + 'This demonstrates the power of a modern workflow.', + 'Overall, this is a significant step forward.', + 'Ultimately, this paves the way for future success.', + + 'This process, which teams may use when priorities change, while the system continues to operate across several environments, although the exact owner remains unclear, creates a range of outcomes that can affect delivery because it changes how things work and how they are understood by everyone involved.', + 'The approach, which brings together planning and review, while also supporting delivery and reporting, although it does not name who approves the result, creates an experience that changes many parts of the process because it connects them in ways that are difficult to follow for readers who need a decision.', + 'This mechanism, which is intended to improve the workflow, while preserving several existing behaviors, although the exact effect is not stated, changes how it operates because it introduces multiple layers that interact with one another and that may influence outcomes for different people in different contexts.', + 'The update, which affects the router and the validator, while keeping the old path available, although the migration owner is not named, changes the system because it adds a compatibility layer that callers use when they move between versions and when they encounter conditions that are not described.', + 'This strategy, which covers planning and delivery, while remaining flexible across projects, although no measurable result is included, creates value because it combines several capabilities that teams can use when they need to work through different situations that may arise over time in complex environments.' +]; + +const NEGATIVE_FIXTURES = [ + 'The router loads 124 command definitions from routing/*.yaml.', + 'The installer supports Node.js 18, 20, and 22.', + 'The release gate runs npm audit before package verification.', + 'The scanner returns findings in source order.', + 'The cache key includes the project root and file hash.', + 'The state lock expires after the configured timeout.', + 'The dashboard reads .godpowers/state.json.', + 'The validator reports line 12 for the missing owner.', + 'The test runner stops after the first failed child process.', + 'The package contains no production dependencies.', + 'The API surface exports scan and summarize.', + 'The command writes the approved plan to BUILD-PLAN.mdx.', + 'The hook blocks npm publish until approval is recorded.', + 'The retry loop makes three attempts before escalation.', + 'The artifact linter preserves the existing error count.', + 'The workflow records a user.resolve event with the plan hash.', + 'The docs name package.json as the source of the test command.', + 'The launch runbook assigns an owner and date to each channel.', + 'The PRD measures recall across 40 reviewed fixtures.', + 'The scanner bounds each excerpt at 160 characters.', + 'The surface contains 124 slash commands and 41 specialists.', + 'The harness invokes every scripts/test-*.js file on disk.', + 'The primitive returns null when the state file is absent.', + 'The security review calls the parser robust after 10,000 malformed inputs produce no crash.', + 'The matrix primitive multiplies two 4 by 4 arrays.', + 'The product uses leverage as the ratio of debt to equity.', + 'The route surface maps /god-build to god-orchestrator.', + 'The test harness creates an isolated temporary project.', + 'The robust mutex recovers when its owner process exits.', + 'The scanner treats input as inert UTF-8 text.', + 'The command can fail when state.json is malformed.', + 'The service may return 503 during the documented maintenance window.', + 'The parser might reject a token if its checksum does not match.', + 'The deployment could take 10 minutes when the registry is delayed.', + 'The audit appears in RELEASE.md after the release check passes.', + 'The result seems correct because the expected and actual hashes match.', + 'The validator tends to finish in 12 milliseconds on the fixture.', + 'The report is likely stale when its recorded hash differs from disk.', + 'The plan perhaps needs review if the approval event is absent.', + 'The command possibly exits with code 2 for invalid arguments.', + 'The 2026 maintainer survey of 40 users found a 15 percent reduction in retries.', + 'Research in docs/benchmark.md records 20 runs and their raw durations.', + 'Three security reviewers approved the threat model in FINDINGS.mdx.', + 'The named OWASP 2025 control blocks the unsafe redirect.', + 'The release notes cite workflow run 32097275283.', + 'The world-class chess title is awarded under FIDE rules.', + 'The revolutionary period in the history chapter spans 1775-1783.', + 'The cutting-edge algorithm stores boundary edges in a sorted array.', + 'The next-generation protocol field is named next_generation_id.', + 'The best-in-class label is quoted from the approved customer transcript.', + 'The function can identify unclear prose in 14 tested patterns.', + 'The scanner identifies unclear prose and returns its exact source location.', + 'To improve quality, run node scripts/test-prose-lint.js.', + 'The passing test proves that the expected rule emitted one finding.', + 'The state lock is a boundary between concurrent writers.', + 'This highlights the exact byte that changed at offset 42.', + 'This underscores the heading at line 18 in the generated report.', + 'This demonstrates the SHA-256 check against the approved plan hash.', + 'Overall, 39 of 40 positive fixtures emitted a warning.', + 'Ultimately, the maintainer must choose option A or option B by 2026-11-30.' +]; + +function scanOne(text, options) { + return proseLint.scan(text, options); +} + +console.log('\n Prose lint behavioral tests\n'); + +test('P-MUST-31: scan accepts null, empty, and multiline input', () => { + assert(Array.isArray(scanOne(null)), 'null input must return an array'); + assert(scanOne(null).length === 0, 'null input must be clean'); + assert(scanOne('').length === 0, 'empty input must be clean'); + assert(Array.isArray(scanOne('First line.\nSecond line.')), 'multiline input must return an array'); +}); + +test('P-MUST-31: every rule identifier emits an explanatory structured finding', () => { + const seen = new Set(); + for (const fixture of POSITIVE_FIXTURES) { + for (const finding of scanOne(fixture)) { + seen.add(finding.ruleId); + for (const field of ['ruleId', 'line', 'column', 'excerpt', 'message', 'suggestion']) { + assert(Object.prototype.hasOwnProperty.call(finding, field), `${finding.ruleId} missing ${field}`); + } + assert(finding.line >= 1 && finding.column >= 1, 'locations must be one-indexed'); + assert(finding.excerpt.length <= 160, 'excerpt exceeded 160 characters'); + assert(finding.message.includes('pattern'), `${finding.ruleId} message must explain a pattern`); + assert(!/\bban(?:ned|s)?\b/i.test(finding.message), 'message must not describe a word ban'); + } + } + assert(JSON.stringify([...seen].sort()) === JSON.stringify([...EXPECTED_RULE_IDS].sort()), + `expected ${EXPECTED_RULE_IDS.join(', ')}, got ${[...seen].join(', ')}`); +}); + +test('P-MUST-31: findings report exact lines, columns, and source order', () => { + const text = [ + 'Concrete opening.', + ' It is important to note that the workflow provides value.', + 'Research suggests that the release improves outcomes.', + 'Overall, this is a significant step forward.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 3, `expected 3 findings, got ${findings.length}`); + assert(findings[0].line === 2 && findings[0].column === 3, + `first location was ${findings[0].line}:${findings[0].column}`); + assert(findings[1].line === 3 && findings[1].column === 1, 'second finding location is wrong'); + assert(findings[2].line === 4 && findings[2].column === 1, 'third finding location is wrong'); +}); + +test('P-MUST-31: inert Markdown regions and clearly quoted bad examples are masked', () => { + const text = [ + '---', + 'description: It is important to note that this is filler.', + '---', + '```md', + 'Studies show that this code example is vague.', + '```', + 'Use `It is worth noting that this inline example is filler.` as a fixture.', + '[destination](https://example.com/It-is-important-to-note-that)', + '- **Bad** (artifact decision): "Overall, this is a significant step forward."', + ' This continuation explains why the quoted example is bad.', + '', + 'It should be noted that this live sentence is vague.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 12, `expected line 12, got ${findings[0].line}`); +}); + +test('P-MUST-31: double-backtick inline code may contain a single backtick', () => { + const text = 'Use ``It is important to note that `x` stays inside code.``'; + const findings = scanOne(text); + assert(findings.length === 0, `inline code leaked prose findings: ${JSON.stringify(findings)}`); +}); + +test('P-MUST-31: a shorter matching fence does not close an outer fence', () => { + const text = [ + '````md', + '```', + 'It is important to note that this remains fenced code.', + '````', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 5, `expected live prose on line 5, got ${findings[0].line}`); +}); + +test('P-MUST-31: a matching fence with trailing text is code, not a closer', () => { + const text = [ + '````md', + '```` this is code content, not a closing fence', + 'It is important to note that this remains fenced code.', + ' ```` ', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 5, `expected live prose on line 5, got ${findings[0].line}`); +}); + +test('P-MUST-31: a four-space-indented fence cannot close an active fence', () => { + const text = [ + '```md', + ' ```', + 'It is important to note that this remains fenced code.', + '```', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 5, `expected live prose on line 5, got ${findings[0].line}`); +}); + +test('P-MUST-31: a tab-prefixed fence cannot close an active fence', () => { + const text = [ + '~~~md', + '\t~~~', + 'It is important to note that this remains fenced code.', + '~~~', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 5, `expected live prose on line 5, got ${findings[0].line}`); +}); + +test('P-MUST-31: four-space indented fence-like code does not open a fence', () => { + const text = [ + ' ``` It is important to note that this is an indented code line.', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 2, `expected live prose on line 2, got ${findings[0].line}`); +}); + +test('P-MUST-31: a backtick in a backtick fence info string prevents opening', () => { + const text = [ + '```bad`info', + 'It is important to note that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 2, `expected live prose on line 2, got ${findings[0].line}`); +}); + +test('P-MUST-31: an unclosed opening marker does not mask the document', () => { + const text = [ + '---', + 'It is important to note that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 2, `expected live prose on line 2, got ${findings[0].line}`); +}); + +test('P-MUST-31: indented YAML block-scalar markers do not close frontmatter', () => { + const text = [ + '\uFEFF---', + 'summary: |', + ' ---', + ' It is important to note that this remains frontmatter content.', + '---', + 'It should be noted that this sentence is live prose.' + ].join('\r\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 6, `expected live prose on line 6, got ${findings[0].line}`); +}); + +test('P-MUST-31: mixed indentation reaching column four masks fence-like code only', () => { + const text = [ + ' \t``` It is important to note that this is an indented code line.', + 'It should be noted that this sentence is live prose.' + ].join('\n'); + const findings = scanOne(text); + assert(findings.length === 1, `expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 2, `expected live prose on line 2, got ${findings[0].line}`); +}); + +test('P-MUST-31: CRLF backtick and tilde fences preserve only live prose', () => { + for (const [opener, closer] of [['```js', '```'], ['~~~md', '~~~']]) { + const text = [ + opener, + 'It is important to note that this remains fenced code.', + closer, + 'It should be noted that this sentence is live prose.' + ].join('\r\n'); + const findings = scanOne(text); + assert(findings.length === 1, + `${opener} expected one live finding, got ${JSON.stringify(findings)}`); + assert(findings[0].line === 4, + `${opener} expected live prose on line 4, got ${findings[0].line}`); + } +}); + +test('P-MUST-31: finding excerpts and reports remove terminal control bytes', () => { + const hostile = '[DECISION] \x1b[2J\x00\x07 It is important to note that this sentence is vague.\x85'; + const findings = scanOne(hostile); + const dangerous = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/; + assert(findings.length === 1, `expected one finding, got ${JSON.stringify(findings)}`); + assert(!dangerous.test(findings[0].excerpt), 'finding excerpt retained a terminal control byte'); + assert(findings[0].excerpt.length <= 160, 'sanitized excerpt exceeded 160 characters'); + + const wrapped = validator.runChecks(hostile, null); + const formatted = artifactLinter.formatReport({ + path: 'HOSTILE.md', + type: 'unknown', + findings: wrapped, + summary: validator.summarize(wrapped) + }); + assert(!dangerous.test(formatted), 'formatted report retained a terminal control byte'); +}); + +test('P-MUST-31: adversarial unique backtick runs stay below 250ms at p95', () => { + const benchmark = [ + "const { scan } = require('./lib/prose-lint');", + 'const target = 1024 * 1024;', + "const pieces = ['Use '];", + "let used = Buffer.byteLength('Use ');", + 'for (let length = 1400; length >= 1; length--) {', + " const piece = '`'.repeat(length) + 'x';", + ' if (used + piece.length > target) continue;', + ' pieces.push(piece);', + ' used += piece.length;', + '}', + "pieces.push('a'.repeat(target - used));", + "const fixture = pieces.join('');", + "if (Buffer.byteLength(fixture) !== target || fixture.includes('\\n')) process.exit(2);", + 'const durations = [];', + 'for (let run = 0; run < 20; run++) {', + ' const started = process.hrtime.bigint();', + ' scan(fixture);', + ' durations.push(Number(process.hrtime.bigint() - started) / 1e6);', + '}', + 'durations.sort((a, b) => a - b);', + 'const p95 = durations[Math.ceil(durations.length * 0.95) - 1];', + "process.stdout.write(JSON.stringify({ p95, max: durations[durations.length - 1] }));" + ].join('\n'); + const result = spawnSync(process.execPath, ['-e', benchmark], { + cwd: ROOT, + encoding: 'utf8', + timeout: 8000 + }); + assert(!result.error, `adversarial scan did not finish within 8 seconds: ${result.error && result.error.message}`); + assert(result.status === 0, `adversarial scan failed: ${result.stderr || result.stdout}`); + const timing = JSON.parse(result.stdout); + assert(timing.p95 < 250, `adversarial p95 was ${timing.p95.toFixed(2)}ms`); +}); + +test('P-MUST-31: indirect phrasing requires unclear context', () => { + const concrete = [ + 'That produces a wider single thought and hides the fact that it did.', + 'Remove the assumption that there is a server, then compare the resulting designs.' + ]; + for (const fixture of concrete) { + assert(scanOne(fixture).length === 0, `concrete fact usage was flagged: ${fixture}`); + } +}); + +test('P-MUST-31: project terms remain valid in concrete technical sentences', () => { + for (const term of ['surface', 'harness', 'primitive', 'robust', 'leverage']) { + const fixture = NEGATIVE_FIXTURES.find(line => line.toLowerCase().includes(term)); + assert(fixture, `missing negative fixture for ${term}`); + assert(scanOne(fixture).length === 0, `${term} was treated as a standalone word ban`); + } +}); + +test('P-MUST-31: identical text and options produce byte-equivalent ordered findings', () => { + const text = POSITIVE_FIXTURES.join('\n'); + const options = { outputProfile: 'engineering', highConfidenceOnly: true }; + const first = JSON.stringify(scanOne(text, options)); + const second = JSON.stringify(scanOne(text, options)); + assert(first === second, 'two scans of identical input differed'); + assert(JSON.stringify(options) === '{"outputProfile":"engineering","highConfidenceOnly":true}', + 'scanner mutated options'); +}); + +test('P-MUST-33: at least 90 percent of 40 theater fixtures emit warnings', () => { + assert(POSITIVE_FIXTURES.length === 40, `expected 40 fixtures, got ${POSITIVE_FIXTURES.length}`); + const matched = POSITIVE_FIXTURES.filter(fixture => scanOne(fixture).length > 0).length; + assert(matched >= 36, `positive recall was ${matched}/40`); +}); + +test('P-MUST-33: no more than 5 percent of 60 concrete fixtures emit warnings', () => { + assert(NEGATIVE_FIXTURES.length === 60, `expected 60 fixtures, got ${NEGATIVE_FIXTURES.length}`); + const flagged = NEGATIVE_FIXTURES.filter(fixture => scanOne(fixture).length > 0); + assert(flagged.length <= 3, `false positives were ${flagged.length}/60: ${flagged.join(' | ')}`); +}); + +test('P-MUST-31: 1 MiB scan completes within 250 milliseconds at p95 across 20 runs', () => { + const line = 'The router loads 124 command definitions from routing files and returns them in source order.\n'; + const repeats = Math.ceil((1024 * 1024) / Buffer.byteLength(line)); + const fixture = line.repeat(repeats).slice(0, 1024 * 1024); + const durations = []; + for (let i = 0; i < 20; i++) { + const started = process.hrtime.bigint(); + const findings = scanOne(fixture); + durations.push(Number(process.hrtime.bigint() - started) / 1e6); + assert(findings.length === 0, 'performance fixture should remain clean'); + } + durations.sort((a, b) => a - b); + const p95 = durations[Math.ceil(durations.length * 0.95) - 1]; + assert(p95 < 250, `p95 was ${p95.toFixed(2)}ms`); +}); + +test('P-MUST-32: universal validation maps prose findings to advisory U-12 warnings', () => { + const content = '[DECISION] It is important to note that the release provides value.'; + const findings = validator.runChecks(content, null); + const u12 = findings.filter(finding => finding.code === 'U-12'); + assert(u12.length === 1, `expected one U-12 warning, got ${u12.length}`); + assert(u12[0].severity === 'warning', `expected warning, got ${u12[0].severity}`); + assert(u12[0].line === 1 && u12[0].column > 1, 'U-12 location was not preserved'); + assert(u12[0].message && u12[0].suggestion, 'U-12 explanation or suggestion missing'); + const summary = validator.summarize(u12); + assert(summary.errors === 0 && summary.warnings === 1, 'U-12 changed the artifact error count'); + assert(summary.byCode['U-12'] === 1, 'U-12 per-code count missing'); +}); + +test('P-MUST-32: artifact reports keep U-12 advisory while existing errors still block', () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'godpowers-prose-lint-')); + const advisoryPath = path.join(dir, 'NOTES.md'); + const blockingPath = path.join(dir, 'BLOCKING.md'); + try { + fs.writeFileSync(advisoryPath, '[DECISION] Overall, this is a significant step forward.\n'); + fs.writeFileSync(blockingPath, + '[DECISION] Overall, this is a significant step forward. A dash follows: \u2014\n'); + const advisory = artifactLinter.lintFile(advisoryPath, { projectRoot: dir }); + const blocking = artifactLinter.lintFile(blockingPath, { projectRoot: dir }); + assert(advisory.summary.errors === 0, 'U-12-only artifact gained an error'); + assert(advisory.summary.byCode['U-12'] === 1, 'artifact summary omitted U-12'); + assert(blocking.summary.errors > 0, 'existing U-08 error stopped blocking'); + assert(blocking.findings.some(finding => finding.code === 'U-08' && finding.severity === 'error'), + 'U-08 severity changed'); + const formatted = artifactLinter.formatReport(advisory); + assert(formatted.includes('[U-12] WARNING line 1'), 'formatted report omitted U-12 location'); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + +test('P-MUST-32: existing universal severities remain unchanged', () => { + const expectations = [ + ['U-01', validator.checkSubstitution('Our app helps users be scalable and intuitive.'), 'warning'], + ['U-02', validator.checkUnlabeled('This paragraph has enough substantive content to require an explicit artifact label.'), 'warning'], + ['U-08', validator.checkEmEnDash('bad \u2014 dash'), 'error'], + ['U-09', validator.checkEmoji('bad \u{1F680} icon'), 'error'], + ['U-10', validator.checkPhantomRef('[missing](./absent-file.md)', { projectRoot: ROOT, docDir: ROOT }), 'warning'], + ['U-11', validator.checkFutureDate('Recorded 2099-12-31.', { today: '2026-08-19' }), 'warning'], + ['U-13', artifactLinter.checkMdxSafety('Bare item.code === code); + assert(finding && finding.severity === severity, `${code} severity changed`); + } +}); + +test('P-MUST-30: shared voice contract contains a separate audit and three specific pairs', () => { + const voice = fs.readFileSync(path.join(ROOT, 'references/shared/VOICE.md'), 'utf8'); + const normalized = voice.toLowerCase().replace(/\s+/g, ' '); + assert(voice.includes('Implements: P-MUST-30'), 'voice requirement annotation missing'); + assert(voice.includes('Post-draft prose audit'), 'separate post-draft audit heading missing'); + assert(normalized.includes('artifact decision') && normalized.includes('technical explanation') && + normalized.includes('public launch copy'), 'three Godpowers-specific pair categories missing'); + assert((voice.match(/\*\*Bad\*\*:/g) || []).length >= 4, 'expected at least three new bad examples'); + assert((voice.match(/\*\*Good\*\*:/g) || []).length >= 4, 'expected at least three new good examples'); + for (const phrase of ['preserve requirements', 'verified facts', 'code terms', 'quotations', + 'user-approved tone', 'three-label', 'substitution test']) { + assert(normalized.includes(phrase), `voice audit missing ${phrase}`); + } +}); + +test('P-MUST-34: docs and launch specialists apply output-specific post-draft audits', () => { + const docs = fs.readFileSync(path.join(ROOT, 'specialists/god-docs-writer.md'), 'utf8'); + const launch = fs.readFileSync(path.join(ROOT, 'specialists/god-launch-strategist.md'), 'utf8'); + for (const [name, content] of [['docs', docs], ['launch', launch]]) { + assert(content.includes('Implements: P-MUST-34'), `${name} requirement annotation missing`); + assert(content.includes('references/shared/VOICE.md'), `${name} lost the shared voice contract`); + assert(/post-draft audit/i.test(content), `${name} lost its post-draft audit obligation`); + assert(/human-authored/i.test(content) && /objectively good/i.test(content), + `${name} must state the scanner proof boundary`); + } + for (const phrase of ['direct factual explanations', 'exact repository names', 'verified commands', + 'concrete before-and-after behavior', 'required terminology', 'quoted source text', + 'runbook steps', 'evidence language']) { + assert(docs.replace(/\s+/g, ' ').includes(phrase), `docs guidance missing ${phrase}`); + } + for (const phrase of ['founder or product voice', 'approved positioning', 'channel constraints', + 'Brand voice/tone decisions', 'Final headline approval']) { + assert(launch.includes(phrase), `launch guidance missing ${phrase}`); + } +}); + +test('P-MUST-35: package guard explicitly requires the prose scanner', () => { + const source = fs.readFileSync(path.join(ROOT, 'scripts/check-package-contents.js'), 'utf8'); + const requiredFiles = source.match(/const REQUIRED_FILES = \[([\s\S]*?)\n\];/); + assert(requiredFiles, 'package guard REQUIRED_FILES declaration missing'); + assert(/['"]lib\/prose-lint\.js['"]/.test(requiredFiles[1]), + 'package guard does not explicitly require lib/prose-lint.js'); + assert(source.includes('Implements: P-MUST-35'), 'package guard requirement annotation missing'); +}); + +test('P-MUST-35: prose-quality documentation and release surfaces stay complete', () => { + const cases = [ + { + source: '6.1.0', + published: '6.0.0', + expected: { + mode: 'candidate', + usersMarker: 'current source version is v6.1.0, and the latest published release is v6.0.0', + roadmapMarker: 'Current source: v6.1.0. Latest published: v6.0.0.', + architectureStatus: 'STABLE v6.1.0 release candidate', + releaseStatus: 'Status: Release candidate', + securityRows: [['6.0.x', 'Yes'], ['6.1.x', 'Release candidate']] + } + }, + { + source: '6.1.0', + published: '6.1.0', + expected: { + mode: 'published', + usersMarker: 'current source version is v6.1.0, and the latest published release is v6.1.0', + roadmapMarker: 'Current source: v6.1.0. Latest published: v6.1.0.', + architectureStatus: 'STABLE v6.1.0 published release', + releaseStatus: 'Status: Published and verified', + securityRows: [['6.1.x', 'Yes']] + } + } + ]; + + for (const fixture of cases) { + const actual = releaseTruthExpectations(fixture.source, fixture.published); + assert(actual.mode === fixture.expected.mode, `${fixture.expected.mode} mode mismatch`); + assert(actual.usersMarker === fixture.expected.usersMarker, + `${fixture.expected.mode} user marker mismatch`); + assert(actual.roadmapMarker === fixture.expected.roadmapMarker, + `${fixture.expected.mode} roadmap marker mismatch`); + assert(actual.architectureStatus === fixture.expected.architectureStatus, + `${fixture.expected.mode} architecture status mismatch`); + assert(actual.releaseStatus === fixture.expected.releaseStatus, + `${fixture.expected.mode} release status mismatch`); + assert(JSON.stringify(actual.securityRows) === JSON.stringify(fixture.expected.securityRows), + `${fixture.expected.mode} security rows mismatch`); + } + + const inspiration = fs.readFileSync(path.join(ROOT, 'INSPIRATION.md'), 'utf8'); + const libraryReadme = fs.readFileSync(path.join(ROOT, 'lib/README.md'), 'utf8'); + const rootReadme = fs.readFileSync(path.join(ROOT, 'README.md'), 'utf8'); + const validation = fs.readFileSync(path.join(ROOT, 'docs/validation.md'), 'utf8'); + const changelog = fs.readFileSync(path.join(ROOT, 'CHANGELOG.md'), 'utf8'); + const release = fs.readFileSync(path.join(ROOT, 'RELEASE.md'), 'utf8'); + const users = fs.readFileSync(path.join(ROOT, 'USERS.md'), 'utf8'); + const roadmap = fs.readFileSync(path.join(ROOT, 'docs/ROADMAP.md'), 'utf8'); + const architecture = fs.readFileSync(path.join(ROOT, 'ARCHITECTURE.md'), 'utf8'); + const security = fs.readFileSync(path.join(ROOT, 'SECURITY.md'), 'utf8'); + const packageJson = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8')); + const state = JSON.parse(fs.readFileSync(path.join(ROOT, '.godpowers/state.json'), 'utf8')); + const publishedVersion = state.tiers && state.tiers['tier-3'] && + state.tiers['tier-3'].launch && state.tiers['tier-3'].launch['release-version']; + const sourceVersion = packageJson.version; + const releaseTruth = releaseTruthExpectations(sourceVersion, publishedVersion); + const compact = text => text.replace(/\s+/g, ' '); + const missing = []; + const requireContract = (condition, message) => { + if (!condition) missing.push(message); + }; + + const inspirationText = compact(inspiration); + requireContract( + inspiration.includes('https://github.com/cursor/plugins/blob/main/pstack/skills/unslop/SKILL.md'), + 'INSPIRATION.md: exact pstack unslop link' + ); + requireContract(/no upstream .{0,160} vendored/i.test(inspirationText), + 'INSPIRATION.md: explicit no-vendoring boundary'); + requireContract(/no runtime dependency/i.test(inspirationText), + 'INSPIRATION.md: explicit no-runtime-dependency boundary'); + + const libraryText = compact(libraryReadme); + requireContract(/U-12/i.test(libraryText) && /advisory/i.test(libraryText), + 'lib/README.md: advisory U-12 integration'); + requireContract(/false positives?/i.test(libraryText), + 'lib/README.md: false-positive boundary'); + requireContract(/false negatives?|miss(?:es|ed)? (?:revision-worthy )?prose|prose (?:that )?(?:needs|need) revision/i.test(libraryText), + 'lib/README.md: missed revision-worthy prose or false-negative boundary'); + requireContract(/clean scan (?:does not|cannot) prove/i.test(libraryText), + 'lib/README.md: clean-scan limitation'); + requireContract(/documentation/i.test(libraryText) && /launch/i.test(libraryText) && + /(?:founder|product) voice/i.test(libraryText), + 'lib/README.md: output-specific documentation and launch voice treatment'); + + const rootText = compact(rootReadme); + requireContract(/false positives?/i.test(rootText), 'README.md: false-positive boundary'); + requireContract(/false negatives?|miss(?:es|ed)? (?:revision-worthy )?prose|prose (?:that )?(?:needs|need) revision/i.test(rootText), + 'README.md: missed revision-worthy prose or false-negative boundary'); + requireContract(/clean scan (?:does not|cannot) prove/i.test(rootText), + 'README.md: clean-scan limitation'); + + const validationText = compact(validation); + requireContract(/U-12/i.test(validationText) && /advisory/i.test(validationText) && + /(?:never|does not) (?:the )?(?:block|error count)|does not block/i.test(validationText), + 'docs/validation.md: advisory non-blocking U-12 behavior'); + requireContract(/clean scan does not prove/i.test(validationText) && + /not a complete Markdown parser/i.test(validationText), + 'docs/validation.md: precision limits'); + + const changelogSection = (changelog.match(/## \[6\.1\.0\][\s\S]*?(?=\n## \[|$)/) || [''])[0]; + requireContract(/prose-quality/i.test(changelogSection) && /U-12/i.test(changelogSection) && + /lib\/prose-lint\.js/.test(changelogSection), + 'CHANGELOG.md: 6.1.0 prose-quality facts'); + + requireContract(/^\d+\.\d+\.\d+$/.test(publishedVersion || ''), + '.godpowers/state.json: tier-3 launch release-version'); + requireContract(users.toLowerCase().includes(releaseTruth.usersMarker.toLowerCase()), + `USERS.md: ${sourceVersion} source and ${publishedVersion} published truth`); + requireContract(roadmap.includes(releaseTruth.roadmapMarker), + `docs/ROADMAP.md: ${sourceVersion} source and ${publishedVersion} published truth`); + requireContract(architecture.includes(releaseTruth.architectureStatus), + `ARCHITECTURE.md: ${releaseTruth.mode} status`); + requireContract(release.includes(releaseTruth.releaseHeading), + `RELEASE.md: ${sourceVersion} release heading`); + requireContract(release.includes(releaseTruth.releaseStatus), + `RELEASE.md: ${releaseTruth.mode} status`); + for (const [minor, status] of releaseTruth.securityRows) { + const escapedMinor = minor.replace(/\./g, '\\.'); + requireContract(new RegExp(`\\|\\s*${escapedMinor}\\s*\\|\\s*${status}\\s*\\|`).test(security), + `SECURITY.md: ${minor} ${status}`); + } + if (sourceVersion === '6.1.0') { + requireContract(/prose/i.test(release) && /U-12/i.test(release), + 'RELEASE.md: 6.1.0 prose-quality facts'); + } + + assert(missing.length === 0, `missing prose documentation contracts:\n - ${missing.join('\n - ')}`); +}); + +test('P-MUST-33: static self-dogfood reports the fixed scope and reviewed baseline', () => { + const result = spawnSync(process.execPath, ['scripts/static-check.js'], { + cwd: ROOT, + encoding: 'utf8' + }); + const output = `${result.stdout}\n${result.stderr}`; + assert(result.status === 0, `static check failed:\n${output}`); + assert(output.includes('P-MUST-33: prose self-dogfood scans skills, specialists, agents, and references'), + 'static output did not confirm the full prose scope'); + assert(/Prose self-dogfood baseline: \d+ warnings across \d+ files\./.test(output), + 'static output omitted the reviewed warning baseline'); +}); + +report(); diff --git a/scripts/test-repo-doc-sync.js b/scripts/test-repo-doc-sync.js index 2e9cc1a..d44960a 100644 --- a/scripts/test-repo-doc-sync.js +++ b/scripts/test-repo-doc-sync.js @@ -1,4 +1,5 @@ #!/usr/bin/env node +// Implements: P-MUST-35 /** * Behavioral tests for lib/repo-doc-sync.js. */ @@ -101,6 +102,71 @@ test('published versions cannot retain release-candidate architecture status', ( assert(!architecture.includes('release candidate')); }); +test('unpublished current source receives release-candidate architecture status', () => { + const tmp = mkFixture(); + writeRel(tmp, 'USERS.md', + 'The current source version is v9.8.7, and the latest published release is v9.7.0.\n'); + writeRel(tmp, 'docs/ROADMAP.md', + 'Current source: v9.8.7. Latest published: v9.7.0.\n' + + '**4 slash commands**\n**2 specialist agents**\n'); + writeRel(tmp, 'ARCHITECTURE.md', + 'STABLE v9.8.7 published release\nCore: 4 skills, 2 agents, 1 workflows\n'); + + const before = repoDocSync.detect(tmp); + assert(before.stale.some((check) => check.id === 'architecture-publication-status')); + + repoDocSync.run(tmp, { log: false }); + const architecture = readRel(tmp, 'ARCHITECTURE.md'); + assert(architecture.includes('STABLE v9.8.7 release candidate')); + assert(!architecture.includes('published release')); +}); + +test('same-minor patch candidate keeps one published SECURITY status and reaches fresh', () => { + const tmp = mkFixture(); + writeRel(tmp, 'package.json', JSON.stringify({ + name: 'godpowers', + version: '6.1.1', + description: 'AI-powered system: 4 slash commands and 2 specialist agents.' + }, null, 2)); + writeRel(tmp, '.godpowers/state.json', JSON.stringify({ + tiers: { 'tier-3': { launch: { 'release-version': '6.1.0' } } } + }, null, 2)); + writeRel(tmp, 'README.md', + '[![Version](https://img.shields.io/badge/version-6.1.1-blue)](CHANGELOG.md)\nall 4 skills + 2 agents\n'); + writeRel(tmp, 'USERS.md', + 'The current source version is v6.1.1, and the latest published release is v6.1.0.\n'); + writeRel(tmp, 'ARCHITECTURE.md', + 'STABLE v6.1.1 release candidate\nCore: 4 skills, 2 agents, 1 workflows\n'); + writeRel(tmp, 'docs/ROADMAP.md', + 'Current source: v6.1.1. Latest published: v6.1.0.\n' + + '**4 slash commands**\n**2 specialist agents**\n'); + writeRel(tmp, 'docs/reference.md', + 'reference for v6.1.1\nSlash commands (4 total)\nSpecialist agents (2 total)\n'); + writeRel(tmp, 'skills/god-version.md', 'Surface: 4 skills, 2 agents, 1 workflows, 1 recipes\n'); + writeRel(tmp, 'skills/god-doctor.md', '[OK] 4 skills installed\n[OK] 2 agents installed\n'); + writeRel(tmp, 'RELEASE.md', '# Godpowers 6.1.1 Release\n'); + writeRel(tmp, 'CHANGELOG.md', '# Changelog\n\n## [6.1.1] - 2026-01-01\n'); + writeRel(tmp, 'SECURITY.md', + '| Version | Supported |\n|---------|-----------|\n| 6.1.x | Release candidate |\n'); + writeRel(tmp, 'CONTRIBUTING.md', 'Releases use repo documentation sync.\n'); + + const before = repoDocSync.detect(tmp); + const securityChecks = before.checks.filter((check) => check.path === 'SECURITY.md'); + assert(securityChecks.length === 1, 'same-minor source produced contradictory SECURITY expectations'); + assert(securityChecks[0].expected.includes('| 6.1.x | Yes |'), + 'same-minor published series must remain supported'); + + const result = repoDocSync.run(tmp, { log: false }); + const security = readRel(tmp, 'SECURITY.md'); + assert((security.match(/\|\s*6\.1\.x\s*\|/g) || []).length === 1, + 'same-minor SECURITY table must contain exactly one 6.1.x row'); + assert(/\|\s*6\.1\.x\s*\|\s*Yes\s*\|/.test(security), + 'same-minor SECURITY row must remain supported'); + assert(!/\|\s*6\.1\.x\s*\|\s*Release candidate\s*\|/.test(security), + 'same-minor SECURITY row must not contradict published support'); + assert(result.after.status === 'fresh', 'same-minor repo-doc run did not reach fresh'); +}); + test('run writes a Godpowers repo-doc sync log', () => { const tmp = mkFixture(); repoDocSync.run(tmp); diff --git a/scripts/version-sync.js b/scripts/version-sync.js index 6a70b29..b01d042 100644 --- a/scripts/version-sync.js +++ b/scripts/version-sync.js @@ -1,6 +1,8 @@ #!/usr/bin/env node 'use strict'; +// Implements: P-MUST-35 + // Single source of version truth: package.json. This writes that version into // every version surface godpowers self-truth and surface-count checks assert - // docs, the MCP package and lockfile, the SECURITY supported series, the @@ -22,22 +24,41 @@ const cadenceGuard = require('../lib/cadence-guard'); const mismatches = []; const rd = (rel) => fs.readFileSync(path.join(root, rel), 'utf8'); const wr = (rel, text) => { if (!check) fs.writeFileSync(path.join(root, rel), text); }; +const V = '[0-9]+\\.[0-9]+\\.[0-9]+'; + +function latestPublishedVersion() { + try { + const state = JSON.parse(rd('.godpowers/state.json')); + const launch = state.tiers && state.tiers['tier-3'] && state.tiers['tier-3'].launch; + if (launch && new RegExp(`^${V}$`).test(launch['release-version'] || '')) { + return launch['release-version']; + } + } catch (err) { + // Fall through to the public marker when authoritative state is unavailable. + } + for (const [rel, regex] of [ + ['USERS.md', new RegExp(`latest published release is v(${V})`, 'i')], + ['docs/ROADMAP.md', new RegExp(`Latest published: v(${V})`)] + ]) { + const match = rd(rel).match(regex); + if (match) return match[1]; + } + return version; +} + +const publishedVersion = latestPublishedVersion(); // 1. Regex doc surfaces. Each regex captures the whole match in groups; the // numbered slots are the version groups. Rebuild the match from its groups, // substituting the target version at the version slots. Exact-semver capture // avoids swallowing sentence-ending periods. -const V = '[0-9]+\\.[0-9]+\\.[0-9]+'; const surfaces = [ ['SKILL.md', new RegExp(`(\\n\\s+version:\\s*")(${V})(")`), [2]], ['README.md', new RegExp(`(version-)(${V})(-(?:blue|green))`), [2]], - ['USERS.md', new RegExp(`(current source version is v)(${V})(, and the latest published release is v)(${V})`), [2, 4]], - ['ARCHITECTURE.md', new RegExp(`(STABLE v)(${V})`), [2]], ['ARCHITECTURE-MAP.md', new RegExp(`(package\\.json \\(v)(${V})(\\))`), [2]], ['ARCHITECTURE-MAP.md', new RegExp(`(## Numbers \\(as of v)(${V})(\\))`), [2]], ['agents/context.md', new RegExp('(current repository version is `)(' + V + ')(`)'), [2]], ['docs/reference.md', new RegExp(`(reference for v)(${V})`), [2]], - ['docs/ROADMAP.md', new RegExp(`(Current source: v)(${V})(\\. Latest published: v)(${V})`), [2, 4]], ['.godpowers/roadmap/ROADMAP.mdx', new RegExp('(Source version: `)(' + V + ')(`)'), [2]], ['RELEASE.md', new RegExp(`(# Godpowers )(${V})( Release)`), [2]], ]; @@ -57,6 +78,24 @@ for (const [rel, regex, slots] of surfaces) { else { wr(rel, text.replace(match[0], corrected)); process.stdout.write(` synced ${rel}\n`); } } +const releaseTruthSurfaces = [ + ['USERS.md', new RegExp(`current source version is v${V}, and the latest published release is v${V}`), + `current source version is v${version}, and the latest published release is v${publishedVersion}`], + ['docs/ROADMAP.md', new RegExp(`Current source: v${V}\\. Latest published: v${V}`), + `Current source: v${version}. Latest published: v${publishedVersion}`], + ['ARCHITECTURE.md', new RegExp(`STABLE v${V}(?: (?:release candidate|published release))?`), + `STABLE v${version} ${version === publishedVersion ? 'published release' : 'release candidate'}`] +]; + +for (const [rel, regex, corrected] of releaseTruthSurfaces) { + const text = rd(rel); + const match = text.match(regex); + if (!match) { mismatches.push(`${rel}: no release-truth surface matched ${regex}`); continue; } + if (match[0] === corrected) continue; + if (check) mismatches.push(`${rel}: "${match[0]}" should be "${corrected}"`); + else { wr(rel, text.replace(match[0], corrected)); process.stdout.write(` synced ${rel}\n`); } +} + // 2. MCP package.json version. { const rel = 'packages/mcp/package.json'; @@ -79,21 +118,30 @@ for (const [rel, regex, slots] of surfaces) { } } -// 4. SECURITY supported series: the current minor is "Yes", others demoted. +// 4. SECURITY supported series: published is "Yes" and unpublished source is a candidate. { const rel = 'SECURITY.md'; - const minorX = `${version.split('.').slice(0, 2).join('.')}.x`; - let text = rd(rel); - const hasCurrent = new RegExp(`\\|\\s*${minorX.replace(/\./g, '\\.')}\\s*\\|\\s*Yes\\s*\\|`).test(text); - const demoted = text.replace(/\|(\s*[0-9]+\.[0-9]+\.x\s*)\|\s*Yes\s*\|/g, (m, ver) => - ver.trim() === minorX ? m : `|${ver}| Security fixes only |`); - let next = demoted; - if (!hasCurrent) { - // insert the current series as the first data row after the table header separator - next = demoted.replace(/(\|\s*Version\s*\|\s*Supported\s*\|\n\|[-\s|]+\|\n)/, `$1| ${minorX} | Yes |\n`); + const sourceMinor = `${version.split('.').slice(0, 2).join('.')}.x`; + const publishedMinor = `${publishedVersion.split('.').slice(0, 2).join('.')}.x`; + const desired = new Map([[publishedMinor, 'Yes']]); + if (sourceMinor !== publishedMinor) desired.set(sourceMinor, 'Release candidate'); + const text = rd(rel); + let next = text.replace(/\|\s*([0-9]+\.[0-9]+\.x)\s*\|\s*([^|]+?)\s*\|/g, + (match, minor, status) => { + if (desired.has(minor)) return `| ${minor} | ${desired.get(minor)} |`; + if (/^(?:Yes|Release candidate)$/.test(status.trim())) { + return `| ${minor} | Security fixes only |`; + } + return match; + }); + const missing = [...desired.entries()].filter(([minor]) => + !new RegExp(`\\|\\s*${minor.replace(/\./g, '\\.')}\\s*\\|`).test(next)); + if (missing.length > 0) { + const rows = missing.map(([minor, status]) => `| ${minor} | ${status} |\n`).join(''); + next = next.replace(/(\|\s*Version\s*\|\s*Supported\s*\|\n\|[-\s|]+\|\n)/, `$1${rows}`); } if (next !== text) { - if (check) mismatches.push(`${rel}: supported series does not lead with ${minorX} = Yes`); + if (check) mismatches.push(`${rel}: published and candidate series do not match ${publishedVersion} and ${version}`); else { wr(rel, next); process.stdout.write(` synced ${rel} supported series\n`); } } } diff --git a/skills/god-lint.md b/skills/god-lint.md index ef8a949..7c3b4bf 100644 --- a/skills/god-lint.md +++ b/skills/god-lint.md @@ -122,8 +122,8 @@ and `god-spec-reviewer` / `god-quality-reviewer` (per-artifact two-stage review). The catalog of 183 have-nots is split: -- 25 mechanical (cataloged in `lib/have-nots-validator.js`) -- 158 interpretive (delegated to agents) +- 26 mechanical (cataloged in `lib/have-nots-validator.js`) +- 157 interpretive (delegated to agents) This split is published in `references/HAVE-NOTS.md` per check. diff --git a/specialists/god-docs-writer.md b/specialists/god-docs-writer.md index ff530d6..6ccd139 100644 --- a/specialists/god-docs-writer.md +++ b/specialists/god-docs-writer.md @@ -27,6 +27,7 @@ handoff: - "return updated files and drift findings" --- + # God Docs Writer Write docs that don't lie. @@ -61,6 +62,20 @@ For each section: OPEN QUESTION) - Verify with code reference (link or filepath:line) +### 3.5 Output-specific post-draft audit + +Read `references/shared/VOICE.md` and run its post-draft audit after the +documentation's meaning and evidence are settled. For documentation, prefer +direct factual explanations, exact repository names, verified commands, and +concrete before-and-after behavior. Preserve required terminology, quoted source +text, runbook steps, and evidence language exactly when changing them would +weaken or alter the verified claim. + +Operational status and engineering documentation default to direct, neutral +language. Treat U-12 scanner findings as review prompts, not automatic edits. +Neither a clean scan nor a revised draft proves that prose is human-authored or +objectively good. + ### 4. Output Update README.md, CONTRIBUTING.md, docs/, etc. as needed. diff --git a/specialists/god-launch-strategist.md b/specialists/god-launch-strategist.md index 8aad3fa..b011afb 100644 --- a/specialists/god-launch-strategist.md +++ b/specialists/god-launch-strategist.md @@ -33,6 +33,7 @@ handoff: - "return launch evidence and pause only for human-only brand choices" --- + # God Launch Strategist Put the product in front of users. @@ -61,6 +62,15 @@ rollback or success criteria, and the other failure patterns to avoid). - Allowed: words used with evidence ("99.9% uptime" not "robust") - Three sections minimum: hero, value props, social proof or differentiator +After the claims and positioning are settled, read +`references/shared/VOICE.md` and run its output-specific post-draft audit. +Remove empty claims, stock framing, and decoration words. Preserve an explicit +founder or product voice, approved positioning, channel constraints, verified +product facts, and the pause for brand approval. Public product copy follows +the approved brand voice; operational status and engineering evidence remain +direct and neutral. Treat U-12 scanner findings as prompts for human judgment, +not proof that copy is human-authored or objectively good. + ### 2. OG Cards - Render and visually verify (don't just write meta tags) - Twitter card: 1200x675