Skip to content

feat(spec+define): lintSpecQuality diagnostic helper + DEFINE warning surface + prd-taskmaster comparison#25

Merged
omerakben merged 8 commits into
mainfrom
worktree-m-spec1-prd-taskmaster-borrow
May 11, 2026
Merged

feat(spec+define): lintSpecQuality diagnostic helper + DEFINE warning surface + prd-taskmaster comparison#25
omerakben merged 8 commits into
mainfrom
worktree-m-spec1-prd-taskmaster-borrow

Conversation

@omerakben
Copy link
Copy Markdown
Owner

Summary

Adds the M-SPEC1 prd-taskmaster borrow: a lintSpecQuality diagnostic helper for SPEC artifacts plus DEFINE-phase surfacing, with the underlying vague-language vocabulary and Goals sufficiency heuristic pinned in the SPEC contract.

  • lintSpecQuality (src/artifacts/spec.ts): pure diagnostic helper, returns warnings only; never throws, never blocks gate writes, never enters SpecLoadErrorCode.
  • DEFINE completion surfaces warnings to the operator after spec parse (src/phases/define.ts).
  • docs/references/spec-contract.md pins the 15-term vague-language vocabulary, the AND-arm exemption rules (explicit metric OR named-control allow-list), and the Goals sufficiency heuristic (QH2).
  • NAMED_CONTROL_RE is the contract-pinned allow-list verbatim (OAuth, OIDC, SAML, JWT, MFA, TOTP, RBAC, ABAC, ACL, TLS, mTLS, HMAC, AES, RSA, ECDSA, HKDF, PBKDF2, bcrypt, argon2, scrypt, SOC2, HIPAA, GDPR, PCI, CSP, CORS, CSRF); the prior generic-uppercase arm was dropped after the R1 round flagged it as over-permissive on bullets like "REST API should be fast".
  • Companion comparison docs: docs/comparison/08-prd-taskmaster/{COMPARISON,CODEX_BRIEFING,CODEX_RESPONSE,SYNTHESIS}.md capture the borrow analysis + Codex accept-with-modifications verdict.

Authority footprint (Rule 20)

Zero new authority. lintSpecQuality is a diagnostic outside SpecLoadError; it does not write gate files, does not emit new events, does not enter approval-blocking paths, and is not config-driven. Vague-vocabulary is contract-pinned (not a config knob) so the deterministic validation surface cannot drift across runs.

Review history

  • Opus review (pre-merge): F1+F2+F3 closed in ea5593b (regex clarity, AND-arm test, header comment).
  • Codex R1 review (pre-merge): closed in eaa0cf2 — companion docs added, QH2 healthy-arm test added, NAMED_CONTROL_RE narrowed to allow-list, SYNTHESIS.md closure block updated.

Merge with main

Merged origin/main (11 PRs landed today). No conflicts. lintSpecQuality surface, spec-contract additions, and 08-prd-taskmaster comparison docs all sit alongside the new content from those PRs without touching the same files.

Test plan

  • bun test — 3189 pass, 2 skip (xai live), 0 fail
  • bun run typecheck — clean
  • Vague-language: positive test (warns on "fast"), negative test with explicit metric (200ms), negative test with allow-listed token (OAuth), AND-arm test (generic REST acronym does NOT suppress)
  • Goals sufficiency (QH2): underspecified (1 bullet, <15 words) warns; healthy (2+ bullets, 15+ words) does not warn
  • DEFINE completion surfaces warnings to operator output without changing exit codes

omerakben added 8 commits May 10, 2026 14:20
…narrow NAMED_CONTROL_RE

R1 review closure for M-SPEC1 prd-taskmaster borrow:

- Add CODEX_BRIEFING.md, CODEX_RESPONSE.md, COMPARISON.md (companion docs missing from prior commits)
- Narrow NAMED_CONTROL_RE to the contract-pinned allow-list (drop generic uppercase acronym arm that over-suppressed warnings on bullets like 'REST API should be fast')
- Add QH2 healthy-arm test: 2 bullets + 15+ words does NOT warn
- Add AND-arm test: generic uppercase acronym does NOT suppress vague-language
- Pin allow-list verbatim in spec-contract.md (OAuth, OIDC, SAML, JWT, MFA, TOTP, RBAC, ABAC, ACL, TLS, mTLS, HMAC, AES, RSA, ECDSA, HKDF, PBKDF2, bcrypt, argon2, scrypt, SOC2, HIPAA, GDPR, PCI, CSP, CORS, CSRF)
- Update SYNTHESIS.md closure block with R1 commit + file list
- README index update deferred to a separate cleanup commit on main (parallel-session safety)
Copilot AI review requested due to automatic review settings May 11, 2026 02:53
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Warning

Rate limit exceeded

@omerakben has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 48 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f37f73b-1d33-4894-bc0a-c248c7d39b3c

📥 Commits

Reviewing files that changed from the base of the PR and between 075af4a and 4b37f6c.

📒 Files selected for processing (8)
  • docs/comparison/08-prd-taskmaster/CODEX_BRIEFING.md
  • docs/comparison/08-prd-taskmaster/CODEX_RESPONSE.md
  • docs/comparison/08-prd-taskmaster/COMPARISON.md
  • docs/comparison/08-prd-taskmaster/SYNTHESIS.md
  • docs/references/spec-contract.md
  • src/artifacts/spec.ts
  • src/phases/define.ts
  • tests/artifacts-spec.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-m-spec1-prd-taskmaster-borrow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new diagnostic-only quality linter for SPEC artifacts, borrowing mechanics from the prd-taskmaster skill. It adds a vague-language detector and a goals-sufficiency check, implemented as a non-blocking helper in src/artifacts/spec.ts and surfaced during the DEFINE phase. Feedback focuses on improving the efficiency and robustness of the regex-based suppression logic, specifically regarding case-sensitivity and pre-compilation of patterns.

Comment thread src/artifacts/spec.ts
// or a named-control identifier from the contract-pinned allow-list.
// The intent is the source comparison's "explicit metric or named control" rule.
const METRIC_RE = /\d+\s*(?:ms|s|m|h|%|MB|GB|KB|kb|req|rps|qps|hz|min|sec|seconds?|minutes?|hours?|days?|users?|requests?|rows?|bytes?|tokens?)\b/i
const NAMED_CONTROL_RE = /\b(?:OAuth|OIDC|SAML|JWT|MFA|TOTP|RBAC|ABAC|ACL|TLS|mTLS|HMAC|AES|RSA|ECDSA|HKDF|PBKDF2|bcrypt|argon2|scrypt|SOC2|HIPAA|GDPR|PCI|CSP|CORS|CSRF)\b/
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The NAMED_CONTROL_RE is currently case-sensitive, which differs from the METRIC_RE above and the vague terms check itself. This may lead to false positive warnings if a user specifies a named control using lowercase (e.g., "jwt" or "mtls"). Adding the i flag would make the suppression logic more robust and consistent.

Suggested change
const NAMED_CONTROL_RE = /\b(?:OAuth|OIDC|SAML|JWT|MFA|TOTP|RBAC|ABAC|ACL|TLS|mTLS|HMAC|AES|RSA|ECDSA|HKDF|PBKDF2|bcrypt|argon2|scrypt|SOC2|HIPAA|GDPR|PCI|CSP|CORS|CSRF)\b/
const NAMED_CONTROL_RE = /\b(?:OAuth|OIDC|SAML|JWT|MFA|TOTP|RBAC|ABAC|ACL|TLS|mTLS|HMAC|AES|RSA|ECDSA|HKDF|PBKDF2|bcrypt|argon2|scrypt|SOC2|HIPAA|GDPR|PCI|CSP|CORS|CSRF)\b/i

Comment thread src/artifacts/spec.ts
Comment on lines +630 to +646
function findVagueTerms(bullet: string): readonly string[] {
// Match the prd-taskmaster regex: optional `should be|must be|need(s) to be` lead-in,
// then any of the 15 terms as a whole word, case-insensitive.
const pattern = new RegExp(
String.raw`\b(?:should\s+be\s+|must\s+be\s+|needs?\s+to\s+be\s+)?(` +
VAGUE_TERMS.join('|') +
String.raw`)\b`,
'gi',
)
if (METRIC_RE.test(bullet) || NAMED_CONTROL_RE.test(bullet)) return []
const found: string[] = []
let m: RegExpExecArray | null
while ((m = pattern.exec(bullet)) !== null) {
found.push(m[1]!.toLowerCase())
}
return found
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The vague terms regex is being re-compiled on every call to findVagueTerms. Since this function is executed for every bullet in every section of the SPEC, it is more efficient to pre-compile the pattern as a constant. Additionally, using matchAll provides a cleaner way to iterate over global matches compared to a while loop with exec.

const VAGUE_PATTERN = new RegExp(\n  String.raw`\\b(?:should\\s+be\\s+|must\\s+be\\s+|needs?\\s+to\\s+be\\s+)?(` +\n    VAGUE_TERMS.join('|') +\n    String.raw`)\\b`,\n  'gi',\n)\n\nfunction findVagueTerms(bullet: string): readonly string[] {\n  // Match the prd-taskmaster regex: optional `should be|must be|need(s) to be` lead-in,\n  // then any of the 15 terms as a whole word, case-insensitive.\n  if (METRIC_RE.test(bullet) || NAMED_CONTROL_RE.test(bullet)) return []\n  return Array.from(bullet.matchAll(VAGUE_PATTERN), (m) => m[1]!.toLowerCase())\n}

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b37f6c6d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/artifacts/spec.ts
// or a named-control identifier from the contract-pinned allow-list.
// The intent is the source comparison's "explicit metric or named control" rule.
const METRIC_RE = /\d+\s*(?:ms|s|m|h|%|MB|GB|KB|kb|req|rps|qps|hz|min|sec|seconds?|minutes?|hours?|days?|users?|requests?|rows?|bytes?|tokens?)\b/i
const NAMED_CONTROL_RE = /\b(?:OAuth|OIDC|SAML|JWT|MFA|TOTP|RBAC|ABAC|ACL|TLS|mTLS|HMAC|AES|RSA|ECDSA|HKDF|PBKDF2|bcrypt|argon2|scrypt|SOC2|HIPAA|GDPR|PCI|CSP|CORS|CSRF)\b/
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match named-control exemptions case-insensitively

NAMED_CONTROL_RE is case-sensitive, so QH1 suppression fails for common lowercase/mixed-case spellings of the same controls (for example, oauth, oidc, jwt). In practice this causes false spec_vague_language warnings for bullets like “login must be secure with oauth,” even though the rule is supposed to suppress warnings when a named control is present. This will add noisy DEFINE diagnostics and reduce trust in the linter output; normalize casing or use a case-insensitive match for the allow-list check.

Useful? React with 👍 / 👎.

@omerakben omerakben merged commit 1cdfd53 into main May 11, 2026
3 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a diagnostic-only SPEC quality linter (lintSpecQuality) and surfaces its warnings in DEFINE completion output, with the heuristics contract-pinned in documentation and accompanied by prd-taskmaster comparison writeups.

Changes:

  • Implement lintSpecQuality to emit warning issues for vague-language terms (QH1) and underspecified Goals (QH2), without impacting parseSpec / SpecLoadError.
  • Surface lint warnings in DEFINE’s completion userMessage after writing SPEC.md and emitting gate_required.
  • Document the heuristics in docs/references/spec-contract.md and add comparison/codex debate artifacts under docs/comparison/08-prd-taskmaster/.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/artifacts-spec.test.ts Adds unit coverage for QH1/QH2 behaviors, output shape, and immutability of returned issue arrays.
src/phases/define.ts Calls lintSpecQuality on successful DEFINE and appends diagnostic warnings to the CLI completion message.
src/artifacts/spec.ts Introduces the SpecLintIssue/SpecLintCode types and lintSpecQuality implementation.
docs/references/spec-contract.md Pins the vague-term vocabulary, suppression rules, and Goals sufficiency heuristic as diagnostic-only contract text.
docs/comparison/08-prd-taskmaster/SYNTHESIS.md Adds synthesis/closure record for the prd-taskmaster comparison and M-SPEC1 borrow implementation.
docs/comparison/08-prd-taskmaster/COMPARISON.md Adds the full comparison narrative and borrow decision record.
docs/comparison/08-prd-taskmaster/CODEX_BRIEFING.md Adds the structured debate input sent to Codex for review.
docs/comparison/08-prd-taskmaster/CODEX_RESPONSE.md Adds Codex’s verdict and recommended modifications for the borrow set.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/artifacts/spec.ts
Comment on lines +600 to +603
// Quality heuristics: diagnostic-only checks surfaced AFTER GATE_DEFINE_PASSED is
// written. These do NOT participate in parseSpec / SpecLoadError / approval flow
// (rule 20: zero new gate authority). Pinned in docs/references/spec-contract.md
// under "Quality heuristics (diagnostic-only)".
Comment thread src/artifacts/spec.ts
// or a named-control identifier from the contract-pinned allow-list.
// The intent is the source comparison's "explicit metric or named control" rule.
const METRIC_RE = /\d+\s*(?:ms|s|m|h|%|MB|GB|KB|kb|req|rps|qps|hz|min|sec|seconds?|minutes?|hours?|days?|users?|requests?|rows?|bytes?|tokens?)\b/i
const NAMED_CONTROL_RE = /\b(?:OAuth|OIDC|SAML|JWT|MFA|TOTP|RBAC|ABAC|ACL|TLS|mTLS|HMAC|AES|RSA|ECDSA|HKDF|PBKDF2|bcrypt|argon2|scrypt|SOC2|HIPAA|GDPR|PCI|CSP|CORS|CSRF)\b/
Comment on lines +296 to +303
The matching pattern is:

```regex
\b(?:should\s+be\s+|must\s+be\s+|needs?\s+to\s+be\s+)?(fast|quick|slow|good|bad|poor|user-friendly|easy|simple|secure|safe|scalable|flexible|performant|efficient)\b
```

The optional lead-in is `should be`, `must be`, or `need(s) to be`. Warnings are suppressed for any bullet containing an explicit metric (digits plus a unit-like token) or a named-control reference from this allow-list:


**Decision (pre-debate): YES — code-oz exceeds, with two narrow prompt-adjacent borrows.**

`prd-taskmaster` is a single-purpose Claude Code skill that turns a feature idea into a Product Requirements Document, then hands the PRD to TaskMaster (an external task generator) for breakdown and execution. It is ~3.7k LOC concentrated in one Python `script.py` plus a `SKILL.md` workflow. Its authority surface ends at *PRD draft + 13-check validation + USER-TEST checkpoint insertion*. code-oz, by contrast, is a multi-phase runtime with file-based gates, sha256-bound artifacts, cross-family review at REVIEW, run-level budgets, worktree isolation, and a debate-scheduler.
Comment on lines +1 to +10
---
name: codex-briefing-prd-taskmaster
companion-docs: COMPARISON.md (analysis), CODEX_RESPONSE.md (verdicts), SYNTHESIS.md (locks)
target: structured Codex debate input for the prd-taskmaster comparison
status: dispatched-pending
date: 2026-05-10
codex-model: gpt-5.5
codex-effort: xhigh
codex-sandbox: read-only
---

1. Update `docs/references/spec-contract.md` with the pinned 15-term vocabulary list and the Goals-sufficiency heuristic. Doc-only commit.
2. Add `SpecLintIssue` and `lintSpecQuality` to `src/artifacts/spec.ts`. Helper is pure: `(spec: ParsedSpec) → readonly SpecLintIssue[]`.
3. Wire the linter into the DEFINE completion message so users see warnings *after* `GATE_DEFINE_PASSED.json` is written. Approval semantics untouched.
- `a1fc14ff47a213104d1cc480b150905cde807c94` test(spec): add lintSpecQuality coverage (M-SPEC1)
- `50575bfe8035a738508de9c280d1c062b9eefc2e` docs(comparison): close M-SPEC1 implementation in prd-taskmaster synthesis
- `ea5593bd0a867d75fba1e32e6eda948b2fa80152` fix(spec): address Opus review F1+F2+F3 (regex clarity, AND-arm test, header comment)
- `PENDING_R1_FIX_SHA` fix(spec): close R1 findings — closure freshness, companion docs, QH2 healthy-arm test, narrow NAMED_CONTROL_RE
@omerakben omerakben deleted the worktree-m-spec1-prd-taskmaster-borrow branch May 30, 2026 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants