diff --git a/get-shit-done/references/artifact-types.md b/get-shit-done/references/artifact-types.md new file mode 100644 index 000000000..e1f57a9e3 --- /dev/null +++ b/get-shit-done/references/artifact-types.md @@ -0,0 +1,113 @@ +# GSD Artifact Types + +This reference documents all artifact types in the GSD planning taxonomy. Each type has a defined +shape, lifecycle, location, and consumption mechanism. A well-formatted artifact that no workflow +reads is inert — the consumption mechanism is what gives an artifact meaning. + +--- + +## Core Artifacts + +### ROADMAP.md +- **Shape**: Milestone + phase listing with goals and canonical refs +- **Lifecycle**: Created → Updated per milestone → Archived +- **Location**: `.planning/ROADMAP.md` +- **Consumed by**: `plan-phase`, `discuss-phase`, `execute-phase`, `progress`, `state` commands + +### STATE.md +- **Shape**: Current position tracker (phase, plan, progress, decisions) +- **Lifecycle**: Continuously updated throughout the project +- **Location**: `.planning/STATE.md` +- **Consumed by**: All orchestration workflows; `resume-project`, `progress`, `next` commands + +### REQUIREMENTS.md +- **Shape**: Numbered acceptance criteria with traceability table +- **Lifecycle**: Created at project start → Updated as requirements are satisfied +- **Location**: `.planning/REQUIREMENTS.md` +- **Consumed by**: `discuss-phase`, `plan-phase`, CONTEXT.md generation; executor marks complete + +### CONTEXT.md (per-phase) +- **Shape**: 6-section format: domain, decisions, canonical_refs, code_context, specifics, deferred +- **Lifecycle**: Created before planning → Used during planning and execution → Superseded by next phase +- **Location**: `.planning/phases/XX-name/XX-CONTEXT.md` +- **Consumed by**: `plan-phase` (reads decisions), `execute-phase` (reads code_context and canonical_refs) + +### PLAN.md (per-plan) +- **Shape**: Frontmatter + objective + tasks with types + success criteria + output spec +- **Lifecycle**: Created by planner → Executed → SUMMARY.md produced +- **Location**: `.planning/phases/XX-name/XX-YY-PLAN.md` +- **Consumed by**: `execute-phase` executor; task commits reference plan IDs + +### SUMMARY.md (per-plan) +- **Shape**: Frontmatter with dependency graph + narrative + deviations + self-check +- **Lifecycle**: Created at plan completion → Read by subsequent plans in same phase +- **Location**: `.planning/phases/XX-name/XX-YY-SUMMARY.md` +- **Consumed by**: Orchestrator (progress), planner (context for future plans), `milestone-summary` + +### HANDOFF.json / .continue-here.md +- **Shape**: Structured pause state (JSON machine-readable + Markdown human-readable) +- **Lifecycle**: Created on pause → Consumed on resume → Replaced by next pause +- **Location**: `.planning/HANDOFF.json` + `.planning/phases/XX-name/.continue-here.md` (or spike/deliberation path) +- **Consumed by**: `resume-project` workflow + +--- + +## Extended Artifacts + +### DISCUSSION-LOG.md (per-phase) +- **Shape**: Audit trail of assumptions and corrections from discuss-phase +- **Lifecycle**: Created at discussion time → Read-only audit record +- **Location**: `.planning/phases/XX-name/XX-DISCUSSION-LOG.md` +- **Consumed by**: Human review; not read by automated workflows + +### USER-PROFILE.md +- **Shape**: Calibration tier and preferences profile +- **Lifecycle**: Created by `profile-user` → Updated as preferences are observed +- **Location**: `~/.claude/get-shit-done/USER-PROFILE.md` +- **Consumed by**: `discuss-phase-assumptions` (calibration tier), `plan-phase` + +### SPIKE.md / DESIGN.md (per-spike) +- **Shape**: Research question + methodology + findings + recommendation +- **Lifecycle**: Created → Investigated → Decided → Archived +- **Location**: `.planning/spikes/SPIKE-NNN/` +- **Consumed by**: Planner when spike is referenced; `pause-work` for spike context handoff + +--- + +## Standing Reference Artifacts + +### METHODOLOGY.md + +- **Shape**: Standing reference — reusable interpretive frameworks (lenses) that apply across phases +- **Lifecycle**: Created → Active → Superseded (when a lens is replaced by a better one) +- **Location**: `.planning/METHODOLOGY.md` (project-scoped, not phase-scoped) +- **Contents**: Named lenses, each documenting: + - What it diagnoses (the class of problem it detects) + - What it recommends (the class of response it prescribes) + - When to apply (triggering conditions) + - Example: Bayesian updating, STRIDE threat modeling, Cost-of-delay prioritization +- **Consumed by**: + - `discuss-phase-assumptions` — reads METHODOLOGY.md (if it exists) and applies active lenses + to the current assumption analysis before surfacing findings to the user + - `plan-phase` — reads METHODOLOGY.md to inform methodology selection for each plan + - `pause-work` — includes METHODOLOGY.md in the Required Reading section of `.continue-here.md` + so resuming agents inherit the project's analytical orientation + +**Why consumption matters:** A METHODOLOGY.md that no workflow reads is inert. The lenses only +take effect when an agent loads them into its reasoning context before analysis. This is why +both the discuss-phase-assumptions and pause-work workflows explicitly reference this file. + +**Example lens entry:** + +```markdown +## Bayesian Updating + +**Diagnoses:** Decisions made with stale priors — assumptions formed early that evidence has since +contradicted, but which remain embedded in the plan. + +**Recommends:** Before confirming an assumption, ask: "What evidence would make me change this?" +If no evidence could change it, it's a belief, not an assumption. Flag for user review. + +**Apply when:** Any assumption carries Confident label but was formed before recent architectural +changes, library upgrades, or scope corrections. +``` diff --git a/get-shit-done/workflows/discuss-phase-assumptions.md b/get-shit-done/workflows/discuss-phase-assumptions.md index 3073807a9..1ac4d5609 100644 --- a/get-shit-done/workflows/discuss-phase-assumptions.md +++ b/get-shit-done/workflows/discuss-phase-assumptions.md @@ -186,6 +186,24 @@ Parse JSON for: `todo_count`, `matches[]`. **Auto mode (`--auto`):** Fold all todos with score >= 0.4 automatically. Log the selection. + +Read the project-level methodology file if it exists. This must happen before assumption analysis +so that active lenses shape how assumptions are generated and evaluated. + +```bash +cat .planning/METHODOLOGY.md 2>/dev/null || true +``` + +**If METHODOLOGY.md exists:** +- Parse each named lens: its diagnoses, recommendations, and triggering conditions +- Store as internal `` for use in deep_codebase_analysis and present_assumptions +- When spawning the gsd-assumptions-analyzer, pass the lens list so it can flag which lenses apply +- When presenting assumptions, append a "Methodology" section showing which lenses were applied + and what they flagged (if anything) + +**If METHODOLOGY.md does not exist:** Skip silently. This artifact is optional. + + Lightweight scan of existing code to inform assumption generation. diff --git a/get-shit-done/workflows/pause-work.md b/get-shit-done/workflows/pause-work.md index 7857e49d0..2442d4008 100644 --- a/get-shit-done/workflows/pause-work.md +++ b/get-shit-done/workflows/pause-work.md @@ -142,6 +142,7 @@ last_updated: [timestamp from current-timestamp] ## Required Reading (in order) 1. [document] — [why it matters] +1. `.planning/METHODOLOGY.md` (if it exists) — project analytical lenses; apply before any assumption analysis ## Critical Anti-Patterns (do NOT repeat these) diff --git a/tests/methodology-artifact.test.cjs b/tests/methodology-artifact.test.cjs new file mode 100644 index 000000000..31bc50978 --- /dev/null +++ b/tests/methodology-artifact.test.cjs @@ -0,0 +1,137 @@ +'use strict'; +const { test, describe } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.join(__dirname, '..'); +const REFERENCES_DIR = path.join(ROOT, 'get-shit-done', 'references'); +const WORKFLOWS_DIR = path.join(ROOT, 'get-shit-done', 'workflows'); + +describe('methodology artifact type (#1488)', () => { + // ------------------------------------------------------------------------- + // artifact-types.md existence and structure + // ------------------------------------------------------------------------- + let artifactTypesContent; + + test('artifact-types.md exists in get-shit-done/references/', () => { + const p = path.join(REFERENCES_DIR, 'artifact-types.md'); + assert.ok(fs.existsSync(p), 'get-shit-done/references/artifact-types.md must exist'); + artifactTypesContent = fs.readFileSync(p, 'utf-8'); + }); + + test('artifact-types.md documents the methodology artifact type', () => { + artifactTypesContent = artifactTypesContent || fs.readFileSync( + path.join(REFERENCES_DIR, 'artifact-types.md'), 'utf-8' + ); + assert.ok( + artifactTypesContent.includes('methodology') || artifactTypesContent.includes('Methodology'), + 'artifact-types.md must document the methodology artifact type' + ); + }); + + test('methodology artifact has shape documented (standing reference)', () => { + artifactTypesContent = artifactTypesContent || fs.readFileSync( + path.join(REFERENCES_DIR, 'artifact-types.md'), 'utf-8' + ); + assert.ok( + artifactTypesContent.includes('Standing reference') || + artifactTypesContent.includes('standing reference') || + artifactTypesContent.includes('reusable interpretive') || + artifactTypesContent.includes('interpretive framework'), + 'methodology artifact must have shape documented as standing reference / interpretive framework' + ); + }); + + test('methodology artifact has lifecycle documented (Created → Active → Superseded)', () => { + artifactTypesContent = artifactTypesContent || fs.readFileSync( + path.join(REFERENCES_DIR, 'artifact-types.md'), 'utf-8' + ); + assert.ok( + artifactTypesContent.includes('Superseded') || artifactTypesContent.includes('superseded'), + 'methodology artifact lifecycle must include Superseded state' + ); + assert.ok( + artifactTypesContent.includes('Active') || artifactTypesContent.includes('active'), + 'methodology artifact lifecycle must include Active state' + ); + }); + + test('methodology artifact has location documented (.planning/METHODOLOGY.md)', () => { + artifactTypesContent = artifactTypesContent || fs.readFileSync( + path.join(REFERENCES_DIR, 'artifact-types.md'), 'utf-8' + ); + assert.ok( + artifactTypesContent.includes('METHODOLOGY.md'), + 'artifact-types.md must document .planning/METHODOLOGY.md as the location' + ); + }); + + test('methodology artifact documents what it is consumed by', () => { + artifactTypesContent = artifactTypesContent || fs.readFileSync( + path.join(REFERENCES_DIR, 'artifact-types.md'), 'utf-8' + ); + assert.ok( + artifactTypesContent.toLowerCase().includes('consumed by') || + artifactTypesContent.toLowerCase().includes('consumption'), + 'methodology artifact must document its consumption mechanism' + ); + }); + + // ------------------------------------------------------------------------- + // Consumption in discuss-phase-assumptions.md + // ------------------------------------------------------------------------- + let discussContent; + + test('discuss-phase-assumptions.md exists', () => { + const p = path.join(WORKFLOWS_DIR, 'discuss-phase-assumptions.md'); + assert.ok(fs.existsSync(p), 'discuss-phase-assumptions.md must exist'); + discussContent = fs.readFileSync(p, 'utf-8'); + }); + + test('discuss-phase-assumptions.md references METHODOLOGY.md as consumable artifact', () => { + discussContent = discussContent || fs.readFileSync( + path.join(WORKFLOWS_DIR, 'discuss-phase-assumptions.md'), 'utf-8' + ); + assert.ok( + discussContent.includes('METHODOLOGY.md'), + 'discuss-phase-assumptions.md must reference METHODOLOGY.md as a consumable artifact' + ); + }); + + test('discuss-phase-assumptions.md reads METHODOLOGY.md when it exists', () => { + discussContent = discussContent || fs.readFileSync( + path.join(WORKFLOWS_DIR, 'discuss-phase-assumptions.md'), 'utf-8' + ); + assert.ok( + discussContent.includes('METHODOLOGY.md') && + (discussContent.includes('if it exists') || + discussContent.includes('2>/dev/null') || + discussContent.includes('cat .planning/METHODOLOGY') || + discussContent.includes('exists') || + discussContent.includes('lenses')), + 'discuss-phase-assumptions.md must conditionally read METHODOLOGY.md and apply lenses' + ); + }); + + // ------------------------------------------------------------------------- + // Consumption in pause-work.md Required Reading section + // ------------------------------------------------------------------------- + let pauseContent; + + test('pause-work.md exists', () => { + const p = path.join(WORKFLOWS_DIR, 'pause-work.md'); + assert.ok(fs.existsSync(p), 'pause-work.md must exist'); + pauseContent = fs.readFileSync(p, 'utf-8'); + }); + + test('pause-work.md Required Reading template includes METHODOLOGY.md', () => { + pauseContent = pauseContent || fs.readFileSync( + path.join(WORKFLOWS_DIR, 'pause-work.md'), 'utf-8' + ); + assert.ok( + pauseContent.includes('METHODOLOGY.md'), + 'pause-work.md Required Reading template must include METHODOLOGY.md so new sessions inherit the methodology' + ); + }); +});