feat(docs): design doc + implementation plan convention with CI check (closes #67 phase-1)#155
Merged
Merged
Conversation
…closes #67 phase-1) Establishes docs/design/ + docs/plans/ convention with templates, 4 retroactive design docs for existing features, a GitHub Action CI check that requires a design doc on new-feature PRs, and CONTRIBUTING.md guidance. New files: - docs/README.md — index + 'when do I need a design doc?' guide - docs/design/template.md — Problem/Goal/Changes/Trade-offs/Open Questions - docs/design/0001-taint-engine.md — retroactive design doc - docs/design/0002-mcp-server.md — retroactive design doc - docs/design/0003-plugin-system.md — retroactive design doc - docs/design/0004-graph-model.md — retroactive design doc - docs/plans/template.md — phase-based implementation checklist - scripts/check_design_doc.py — CI check logic (pure + CLI entry) - .github/workflows/design-doc-check.yml — GitHub Action - tests/test_design_doc_check.py — 48 tests Modified: - CONTRIBUTING.md — add 'Design Doc Requirement' section to PR process CI check logic: - Detects 'new feature' PRs by file pattern: - New file in scripts/commands/ (new CLI command) - New scripts/*_engine.py (new analysis engine) - New file in scripts/formatters/ (new output format) - New parser in scripts/parsers/ (excluding fallback_*.py) - Requires a design doc (.md) in docs/design/ added/modified in the PR - Bypassable via 'skip-design-doc' PR label for trivial features - Pure-logic check_pr() is unit-testable; CLI entry handles GitHub API I/O Verified: - 48 new tests pass (test_design_doc_check.py) - 145 passed total (test_design_doc_check + test_formatters + test_cli + test_command_count + test_command_registry — no regressions) - End-to-end local-mode: bug fix PASSes, new command without doc FAILs, new command with doc PASSes, bypass label PASSes - Workflow YAML syntax validated Phase 2 (VitePress homepage) and Phase 3 (live demo) are out of scope — they need external tooling and multi-week content work.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Closes #67 (phase-1)
Summary
Implements Phase 1 of issue #67 — Design doc + implementation plan convention. Establishes
docs/design/+docs/plans/with templates, backfills design docs for 4 existing features, adds a GitHub Action CI check that requires a design doc on new-feature PRs, and updatesCONTRIBUTING.mdwith the new requirement.Phase 2 (VitePress homepage) and Phase 3 (live demo) are out of scope — they need external tooling and multi-week content work.
What changed
New files (11)
Templates + guide:
docs/README.md— index + "when do I need a design doc?" guidedocs/design/template.md— Problem/Goal/Changes/Trade-offs/Open Questions/Migrationdocs/plans/template.md— phase-based implementation checklistRetroactive design docs (4 — exceeds the "3+" acceptance criterion):
docs/design/0001-taint-engine.md— AST taint analysis engine (issue [FEATURE] Taint analysis depth — unified cross-file engine + persistence + library approximation + debug trace #49)docs/design/0002-mcp-server.md— MCP server architecture (issues [PERF] Token-efficient output: structured compact format for all MCP tools #17, [FEATURE] Interactive dashboard — D3 force-directed graph + heatmap + cluster hull (5 workers converged) #59)docs/design/0003-plugin-system.md— 4-type plugin system (issue [PROPOSAL] Rule pattern engine — Semgrep-compatible YAML on tree-sitter AST (Layer 2 of #43 hybrid) #46)docs/design/0004-graph-model.md— SQLite graph data model (issues [ARCH] Replace flat registry with true graph data model (nodes + edges) #8, [FEATURE] Interactive dashboard — D3 force-directed graph + heatmap + cluster hull (5 workers converged) #59, [FEATURE] Cypher-like graph query engine for MCP toolquery_graph#9)CI check:
scripts/check_design_doc.py— pure-logiccheck_pr()+ CLI entry (356 lines).github/workflows/design-doc-check.yml— GitHub Action workflowtests/test_design_doc_check.py— 48 tests (399 lines)Modified files (1)
CONTRIBUTING.md— add "Design Doc Requirement" section to PR process (49 lines added)How the CI check works
Feature detection (file pattern + status)
scripts/commands/*.pyscripts/*_engine.pyscripts/formatters/*.pyscripts/parsers/*_parser.pyscripts/parsers/fallback_*.pytests/*.py*.mdBypass mechanism
PRs with the
skip-design-doclabel bypass the check entirely. This is for genuinely trivial features (e.g., a one-line command alias) where a design doc would be pure overhead. The bypass is intentionally a label (not a commit message flag) so it's visible in the PR UI and reviewable by BOS.Architecture
The check is split into two layers:
check_pr(pr_files, pr_labels) -> dict) — no I/O, no API calls, unit-testable. Takes the PR's files and labels and returns{passed, reason, feature_files, design_docs, bypassed}.main()) — handles two modes: CI mode (readsGITHUB_TOKEN/GITHUB_REPOSITORY/PR_NUMBERenv vars, fetches PR data via GitHub API) and local mode (--files/--status/--labelsargs for testing).This split means the logic is fully testable without mocking the GitHub API.
Acceptance criteria (from issue body)
docs/design/anddocs/plans/directories exist with templates — createddocs/design/template.mdanddocs/plans/template.mdtest_check_pr_feature_without_design_doc_failsand end-to-end local-mode test (exit code 1)Tests
tests/test_design_doc_check.pyTestIsFeatureFile(15 tests) — classifier unit testsTestCheckPrNoFeatureFiles(5 tests) — bug fix / test-only / doc-only PRs passTestCheckPrFeatureWithoutDesignDoc(6 tests) — feature PRs without docs fail with helpful messageTestCheckPrFeatureWithDesignDoc(5 tests) — feature PRs with docs passTestCheckPrBypass(4 tests) —skip-design-doclabel bypassesTestEdgeCases(6 tests) — missing keys, mixed PRs, wrong-directory docs, plan-doc-doesn't-satisfy-designTestCliEntryPoint(7 tests) — subprocess tests for CLI arg parsing + env-var handlingtest_formatters+test_cli+test_command_count+test_command_registry→ 97 passed, 0 failed (no regressions)End-to-end verification (local mode)
Design decisions
Pure-logic / I/O split — The check logic (
check_pr()) is a pure function that takes data and returns a result. The CLI entry handles all I/O (GitHub API, env vars, arg parsing). This makes the logic fully unit-testable without mocking. KISS — no mock framework needed.Label-based bypass, not commit-message bypass — A PR label is visible in the GitHub UI, reviewable by BOS, and doesn't pollute git history. A commit message flag (
[skip-design-doc]) would be permanent in git history even if the bypass was later deemed inappropriate.Require design doc, recommend plan — The issue says "design + plan" but the acceptance criteria only mention "design doc". Pragmatically, the design doc captures the "why" (most important for future contributors); the plan captures the "how" (often in the PR description anyway). The plan template is provided as a tool for contributors who want it, but not enforced.
File-pattern detection, not semantic detection — Detecting "is this a new feature?" by file pattern (new file in
scripts/commands/) is robust and simple. Semantic detection (parsing the diff to see if a new MCP tool was added tomcp_server.py) would be fragile and complex. The trade-off: modifications tomcp_server.pythat add a new tool won't trigger the check. Contributors adding a new MCP tool should add a design doc voluntarily; the CI check doesn't enforce it for in-place modifications.Retroactive design docs based on actual code — The 4 backfilled design docs (0001-0004) are written based on the actual engine source code and the CONTEXT.md snapshot. They document the design decisions that were already made, including the alternatives that were rejected. This is the "Open Questions" section's value — it records what's NOT yet decided.
ADR-style numbering —
NNNN-feature-name.md(zero-padded to 4 digits) is the industry standard (Michael Nygard's ADR template). Ensures sort stability and easy referencing ("see design doc 0003").No external dependencies — The check script uses only stdlib (
urllib,json,argparse). Norequests, noPyGithub. KISS — the GitHub API is simple enough forurllib.Findings (per pre-flight SKILL.md — outside scope, BOS decides)
docs/directory did not exist in the repo before this PR. The sparse-checkout set includeddocsbut it was a no-op. This PR creates the directory structure.references/directory exists with 6 files (agent-integration.md, changelog.md, parser-rules.md, query-examples.md, rule-schema.json, status-codes.md). These are reference docs, not design docs — they document "how to use" rather than "why it was designed this way". The newdocs/design/directory is complementary, not overlapping.Branch
feat/issue-67-design-doc-convention