* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
106
gsd-core/bin/check-latest-version.cjs
Executable file
106
gsd-core/bin/check-latest-version.cjs
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Deterministic latest-version check for /gsd-update (#2992).
|
||||
*
|
||||
* The /gsd-update workflow's check_latest_version step was previously
|
||||
* prescribed in LLM-driven prose ("run `npm view gsd-core
|
||||
* version`"). The executing model could shortcut the prescription and
|
||||
* invent npm queries against wrong-shaped names (`@gsd-core/cli`,
|
||||
* `get-shit-done-cli`, `gsd`), all of which 404 or — worse — return an
|
||||
* unrelated typosquat package.
|
||||
*
|
||||
* This script makes the package name a CONSTANT in code, not a free
|
||||
* choice at execution time. The workflow calls it via `npm run
|
||||
* check-latest-version -- --json` and parses the structured response.
|
||||
*
|
||||
* Tests assert on the typed CHECK_REASON enum and the structured result
|
||||
* record, never on console prose. See CONTRIBUTING.md "Prohibited: Raw
|
||||
* Text Matching on Test Outputs".
|
||||
*/
|
||||
|
||||
const { execNpm } = require('./lib/shell-command-projection.cjs');
|
||||
|
||||
// Sourced from the single Package Identity seam (#498), not re-typed. The seam
|
||||
// bakes the value from package.json at build time, so it is a code constant —
|
||||
// still NOT a runtime choice for the caller (#2992) — and a rename propagates
|
||||
// from one place (#378). The drift-guard lint forbids re-introducing a literal.
|
||||
const { packageName: PACKAGE_NAME } = require('./lib/package-identity.cjs');
|
||||
|
||||
const CHECK_REASON = Object.freeze({
|
||||
OK: 'ok',
|
||||
FAIL_NPM_FAILED: 'fail_npm_failed',
|
||||
FAIL_INVALID_OUTPUT: 'fail_invalid_output',
|
||||
});
|
||||
|
||||
const SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
|
||||
|
||||
/**
|
||||
* Pure-ish: takes an injected spawn function so tests don't actually run npm.
|
||||
* In production, defaults to execNpm() from the shell-projection seam.
|
||||
*/
|
||||
function checkLatestVersion(opts = {}) {
|
||||
// Default path routes through the shell-projection seam (execNpm owns the
|
||||
// Windows shell-flag policy and timeout default). The injection point
|
||||
// remains spawnSync-shaped for test compatibility — the adapter below
|
||||
// translates { exitCode } → { status } so the consumer logic is unchanged.
|
||||
// Bounded at 15s so a hung registry doesn't block /gsd-update (#2993 CR).
|
||||
const defaultSpawn = () => {
|
||||
const r = execNpm(['view', PACKAGE_NAME, 'version'], { timeout: 15_000 });
|
||||
return {
|
||||
status: r.exitCode,
|
||||
stdout: r.stdout,
|
||||
stderr: r.stderr,
|
||||
signal: r.signal,
|
||||
error: r.error,
|
||||
};
|
||||
};
|
||||
const spawn = opts.spawn || defaultSpawn;
|
||||
|
||||
const r = spawn();
|
||||
if (!r || r.status !== 0) {
|
||||
// Distinguish timeout (status null, signal set, stderr empty) from a
|
||||
// genuine npm failure. Without this, both surfaced as "npm exited
|
||||
// non-zero" and the operator couldn't tell which (#2993 CR).
|
||||
let detail;
|
||||
if (r && r.signal) {
|
||||
detail = `npm timed out (signal: ${r.signal})`;
|
||||
} else if (r && r.stderr) {
|
||||
detail = r.stderr.trim();
|
||||
} else {
|
||||
detail = 'npm exited non-zero';
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
reason: CHECK_REASON.FAIL_NPM_FAILED,
|
||||
detail,
|
||||
};
|
||||
}
|
||||
const version = (r.stdout || '').trim();
|
||||
if (!SEMVER_RE.test(version)) {
|
||||
return {
|
||||
ok: false,
|
||||
reason: CHECK_REASON.FAIL_INVALID_OUTPUT,
|
||||
detail: version || '(empty)',
|
||||
};
|
||||
}
|
||||
return { ok: true, version, reason: CHECK_REASON.OK };
|
||||
}
|
||||
|
||||
function main() {
|
||||
const json = process.argv.includes('--json');
|
||||
const r = checkLatestVersion();
|
||||
if (json) {
|
||||
process.stdout.write(JSON.stringify(r) + '\n');
|
||||
} else if (r.ok) {
|
||||
process.stdout.write(r.version + '\n');
|
||||
} else {
|
||||
process.stderr.write(`check-latest-version: ${r.reason}: ${r.detail}\n`);
|
||||
}
|
||||
process.exit(r.ok ? 0 : 1);
|
||||
}
|
||||
|
||||
if (require.main === module) main();
|
||||
|
||||
module.exports = { checkLatestVersion, CHECK_REASON, PACKAGE_NAME };
|
||||
1722
gsd-core/bin/gsd-tools.cjs
Executable file
1722
gsd-core/bin/gsd-tools.cjs
Executable file
File diff suppressed because it is too large
Load Diff
253
gsd-core/bin/lib/legacy-cleanup.cjs
Normal file
253
gsd-core/bin/lib/legacy-cleanup.cjs
Normal file
@@ -0,0 +1,253 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* legacy-cleanup.cjs — detect and remove leftover artifacts from the old package.
|
||||
*
|
||||
* Provides a pure-ish scan phase (planLegacyCleanup) and a thin IO applier
|
||||
* (applyLegacyCleanup) that together root out stale files from the old
|
||||
* package across every GSD-managed runtime config directory.
|
||||
*
|
||||
* Issue: #607
|
||||
*
|
||||
* House style: CommonJS, 'use strict', pure functions + thin IO appliers.
|
||||
* Seams (opts.fs, opts.logger) allow full unit-test coverage without touching
|
||||
* the real filesystem except in the apply phase.
|
||||
*/
|
||||
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// ─── Constants ───────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Substring that identifies a file as belonging to the old package.
|
||||
* Assembled from parts so this source file itself never contains the literal
|
||||
* as a plain substring (avoids self-flagging if the content scan were ever
|
||||
* widened back to include this subtree).
|
||||
*/
|
||||
const OLD_PACKAGE_SIGNAL = 'gsd-core' + '-cc';
|
||||
|
||||
/**
|
||||
* Subtrees within a configDir that GSD actively scans for old-package content.
|
||||
* Deliberately excludes 'gsd-core' — the current package's own infra and
|
||||
* docs live there (CHANGELOG.md, this file, etc.) and are overwritten by
|
||||
* install anyway. Poisoning hooks from the old package live in 'hooks/', which
|
||||
* IS scanned.
|
||||
*/
|
||||
const GSD_MANAGED_SUBTREES = ['hooks', 'commands'];
|
||||
|
||||
/**
|
||||
* Extensions eligible for the content-reference scan.
|
||||
*
|
||||
* WHY: The current @opengsd/gsd-core package ships ZERO references to the old
|
||||
* package name in any code file (.js/.cjs/.mjs/.sh). Therefore a code file
|
||||
* that still contains that string is genuinely a leftover from the old package
|
||||
* and is safe to flag.
|
||||
*
|
||||
* Markdown, JSON, TOML, YAML, and other doc/config files, however,
|
||||
* legitimately cite the old name in historical or reference context
|
||||
* (e.g. CHANGELOG.md, workflow .md files). Scanning them caused the
|
||||
* installer to delete the freshly-installed gsd-core/CHANGELOG.md,
|
||||
* breaking installs. Fix: restrict the content scan to code extensions only.
|
||||
*/
|
||||
const CODE_EXTENSIONS = new Set(['.js', '.cjs', '.mjs', '.sh']);
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Return true if any segment of the absolute file path is `dev-preferences`
|
||||
* or the file is named `dev-preferences.md`. These are always user artifacts.
|
||||
*
|
||||
* @param {string} absPath
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isDevPreferencesPath(absPath) {
|
||||
const parts = absPath.split(path.sep);
|
||||
return parts.some(
|
||||
(seg) => seg === 'dev-preferences' || seg === 'dev-preferences.md'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collect all file paths under `dir` (bounded; skips
|
||||
* unreadable entries silently).
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} fsMod - injectable fs module
|
||||
* @returns {string[]} absolute file paths
|
||||
*/
|
||||
function collectFilesUnder(dir, fsMod) {
|
||||
const results = [];
|
||||
let entries;
|
||||
try {
|
||||
entries = fsMod.readdirSync(dir, { withFileTypes: true });
|
||||
} catch {
|
||||
return results;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
results.push(...collectFilesUnder(full, fsMod));
|
||||
} else if (entry.isFile()) {
|
||||
results.push(full);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the file at `absPath` contains the old-package substring.
|
||||
* Skips unreadable files (returns false on any error).
|
||||
*
|
||||
* @param {string} absPath
|
||||
* @param {object} fsMod
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function fileContainsOldPackageSignal(absPath, fsMod) {
|
||||
try {
|
||||
const content = fsMod.readFileSync(absPath, 'utf8');
|
||||
return content.includes(OLD_PACKAGE_SIGNAL);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Public API ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Scan `configDirs` for leftover old-package artifacts and the legacy
|
||||
* shared cache, returning an ordered array of removal candidates.
|
||||
*
|
||||
* Possible reasons in returned entries:
|
||||
* - 'content-references-old-package': a code file whose content contains
|
||||
* the old package name signal (hooks/ and commands/ subtrees only).
|
||||
* - 'legacy-shared-cache': the old package's shared update-check cache file.
|
||||
*
|
||||
* @param {string[]} configDirs - absolute paths to runtime config dirs to scan
|
||||
* @param {object} [opts]
|
||||
* @param {string} [opts.homeDir] - home directory (default: os.homedir())
|
||||
* @param {object} [opts.fs] - injectable fs module (default: require('node:fs'))
|
||||
* @returns {{ path: string, reason: string }[]}
|
||||
*/
|
||||
function planLegacyCleanup(configDirs, opts = {}) {
|
||||
const homeDir = opts.homeDir || os.homedir();
|
||||
const fsMod = opts.fs || fs;
|
||||
|
||||
/** @type {Map<string, string>} path → reason (de-dup by path) */
|
||||
const candidates = new Map();
|
||||
|
||||
const addCandidate = (absPath, reason) => {
|
||||
if (!candidates.has(absPath)) {
|
||||
candidates.set(absPath, reason);
|
||||
}
|
||||
};
|
||||
|
||||
for (const configDir of configDirs) {
|
||||
for (const subtree of GSD_MANAGED_SUBTREES) {
|
||||
const subtreeDir = path.join(configDir, subtree);
|
||||
|
||||
// Collect all files under this subtree (skip if absent)
|
||||
const files = collectFilesUnder(subtreeDir, fsMod);
|
||||
|
||||
for (const absPath of files) {
|
||||
// Never flag user-authored dev-preferences artifacts
|
||||
if (isDevPreferencesPath(absPath)) continue;
|
||||
|
||||
// Content signal: code files referencing the old package name.
|
||||
// Only scan files with code extensions — docs/config files (.md, .json,
|
||||
// .yml, etc.) legitimately cite the old name in historical context and
|
||||
// must never be deleted (see CODE_EXTENSIONS declaration above).
|
||||
const ext = path.extname(absPath).toLowerCase();
|
||||
if (CODE_EXTENSIONS.has(ext) && fileContainsOldPackageSignal(absPath, fsMod)) {
|
||||
addCandidate(absPath, 'content-references-old-package');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy shared cache (fixed name from the old package)
|
||||
const legacyCachePath = path.join(homeDir, '.cache', 'gsd', 'gsd-update-check.json');
|
||||
try {
|
||||
const stat = fsMod.statSync(legacyCachePath);
|
||||
if (stat.isFile()) {
|
||||
addCandidate(legacyCachePath, 'legacy-shared-cache');
|
||||
}
|
||||
} catch {
|
||||
// absent — skip
|
||||
}
|
||||
|
||||
// Sort deterministically by path
|
||||
const sorted = [...candidates.entries()]
|
||||
.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)
|
||||
.map(([p, reason]) => ({ path: p, reason }));
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the plan returned by `planLegacyCleanup`.
|
||||
*
|
||||
* @param {{ path: string, reason: string }[]} plan
|
||||
* @param {object} [opts]
|
||||
* @param {boolean} [opts.dryRun=false] - when true, log but do not remove
|
||||
* @param {object} [opts.fs] - injectable fs module
|
||||
* @param {object} [opts.logger] - injectable logger (default: console)
|
||||
* @returns {{ removed: string[], skipped: string[], errors: Array<{path:string,error:string}>, dryRun: boolean }}
|
||||
*/
|
||||
function applyLegacyCleanup(plan, opts = {}) {
|
||||
const dryRun = opts.dryRun === true;
|
||||
const fsMod = opts.fs || fs;
|
||||
const logger = opts.logger || console;
|
||||
|
||||
if (dryRun) {
|
||||
for (const item of plan) {
|
||||
logger.log('[dry-run] would remove: ' + item.path + ' (' + item.reason + ')');
|
||||
}
|
||||
return {
|
||||
removed: [],
|
||||
skipped: plan.map((item) => item.path),
|
||||
errors: [],
|
||||
dryRun: true,
|
||||
};
|
||||
}
|
||||
|
||||
const removed = [];
|
||||
const errors = [];
|
||||
|
||||
for (const item of plan) {
|
||||
let lastErr;
|
||||
const maxAttempts = process.platform === 'win32' ? 3 : 1;
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
try {
|
||||
if (attempt > 0) {
|
||||
// Synchronous 100ms delay before retry (win32 EBUSY/EPERM from Defender)
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
|
||||
}
|
||||
fsMod.rmSync(item.path, { force: true });
|
||||
lastErr = undefined;
|
||||
break;
|
||||
} catch (err) {
|
||||
lastErr = err;
|
||||
if (process.platform !== 'win32' ||
|
||||
(err.code !== 'EBUSY' && err.code !== 'EPERM')) {
|
||||
break; // non-retryable error; stop immediately
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastErr) {
|
||||
errors.push({ path: item.path, error: lastErr.message });
|
||||
} else {
|
||||
removed.push(item.path);
|
||||
}
|
||||
}
|
||||
|
||||
return { removed, skipped: [], errors, dryRun: false };
|
||||
}
|
||||
|
||||
// ─── Exports ─────────────────────────────────────────────────────────────────
|
||||
|
||||
module.exports = {
|
||||
planLegacyCleanup,
|
||||
applyLegacyCleanup,
|
||||
};
|
||||
35
gsd-core/bin/lib/package-identity.cjs
Normal file
35
gsd-core/bin/lib/package-identity.cjs
Normal file
@@ -0,0 +1,35 @@
|
||||
// @generated by scripts/generate-package-identity.cjs from package.json — DO NOT EDIT.
|
||||
// Single source for GSD package coordinates (issue #498). Regenerate with:
|
||||
// node scripts/generate-package-identity.cjs
|
||||
'use strict';
|
||||
|
||||
const packageName = "@opengsd/gsd-core";
|
||||
const binName = "gsd-core";
|
||||
const repoSlug = "open-gsd/gsd-core";
|
||||
const repoUrl = "https://github.com/open-gsd/gsd-core";
|
||||
const changelogRawUrl = "https://raw.githubusercontent.com/open-gsd/gsd-core/main/CHANGELOG.md";
|
||||
const cacheSlug = "opengsd-gsd-core";
|
||||
const updateCacheFileName = "gsd-update-check-opengsd-gsd-core.json";
|
||||
|
||||
function formatManualInstall({ packageName, binName, scope, runtime } = {}) {
|
||||
const runtimeFlag = runtime ? ` --${runtime}` : '';
|
||||
return `npx -y --package=${packageName}@latest -- ${binName}${runtimeFlag} --${scope}`;
|
||||
}
|
||||
|
||||
function manualInstallCommand(opts = {}) {
|
||||
return formatManualInstall({ packageName, binName, scope: opts.scope, runtime: opts.runtime });
|
||||
}
|
||||
|
||||
module.exports = Object.freeze({
|
||||
packageName,
|
||||
// PACKAGE_NAME: back-compat alias for #516-era consumers. Baked here, so it
|
||||
// survives the installed tree's synthetic package.json (fixes the #378 undefined).
|
||||
PACKAGE_NAME: packageName,
|
||||
binName,
|
||||
repoSlug,
|
||||
repoUrl,
|
||||
changelogRawUrl,
|
||||
cacheSlug,
|
||||
updateCacheFileName,
|
||||
manualInstallCommand,
|
||||
});
|
||||
98
gsd-core/bin/shared/config-defaults.manifest.json
Normal file
98
gsd-core/bin/shared/config-defaults.manifest.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"_comment": "Canonical CONFIG_DEFAULTS for the Configuration Module. Nested shape is canonical. CJS flat projection (branching_strategy, sub_repos, etc.) is handled by consumers at the boundary. Security keys (security_enforcement, security_asvs_level, security_block_on) and post_planning_gaps live in workflow.* as their canonical location. resolve_model_ids, context_window, phase_naming are CJS-originated top-level keys included here. brave_search, firecrawl, exa_search default to false in the manifest; at runtime buildNewProjectConfig detects API keys. The plan_checker (CJS flat) → workflow.plan_check (canonical nested) divergence is resolved: canonical name is workflow.plan_check. _auto_chain_active is a runtime-state field included for completeness.",
|
||||
"model_profile": "balanced",
|
||||
"commit_docs": true,
|
||||
"parallelization": true,
|
||||
"search_gitignored": false,
|
||||
"brave_search": false,
|
||||
"firecrawl": false,
|
||||
"exa_search": false,
|
||||
"resolve_model_ids": false,
|
||||
"context_window": 200000,
|
||||
"phase_naming": "sequential",
|
||||
"project_code": null,
|
||||
"phase_id_convention": null,
|
||||
"mode": "interactive",
|
||||
"claude_md_path": "./CLAUDE.md",
|
||||
"git": {
|
||||
"branching_strategy": "none",
|
||||
"create_tag": true,
|
||||
"base_branch": null,
|
||||
"phase_branch_template": "gsd/phase-{phase}-{slug}",
|
||||
"milestone_branch_template": "gsd/{milestone}-{slug}",
|
||||
"quick_branch_template": null
|
||||
},
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"nyquist_validation": true,
|
||||
"ai_integration_phase": true,
|
||||
"tdd_mode": false,
|
||||
"human_verify_mode": "end-of-phase",
|
||||
"auto_advance": false,
|
||||
"_auto_chain_active": false,
|
||||
"node_repair": true,
|
||||
"node_repair_budget": 2,
|
||||
"ui_phase": true,
|
||||
"ui_safety_gate": true,
|
||||
"text_mode": false,
|
||||
"research_before_questions": false,
|
||||
"discuss_mode": "discuss",
|
||||
"skip_discuss": false,
|
||||
"max_discuss_passes": 3,
|
||||
"subagent_timeout": 300000,
|
||||
"context_coverage_gate": true,
|
||||
"code_review": true,
|
||||
"code_review_depth": "standard",
|
||||
"code_review_command": null,
|
||||
"pattern_mapper": true,
|
||||
"plan_bounce": false,
|
||||
"plan_bounce_script": null,
|
||||
"plan_bounce_passes": 2,
|
||||
"auto_prune_state": false,
|
||||
"post_planning_gaps": true,
|
||||
"security_enforcement": true,
|
||||
"security_asvs_level": 1,
|
||||
"security_block_on": "high"
|
||||
},
|
||||
"planning": {
|
||||
"commit_docs": true,
|
||||
"search_gitignored": false,
|
||||
"sub_repos": [],
|
||||
"granularity": "standard"
|
||||
},
|
||||
"hooks": {
|
||||
"context_warnings": true,
|
||||
"workflow_guard": false
|
||||
},
|
||||
"ship": {
|
||||
"pr_body_sections": []
|
||||
},
|
||||
"graphify": {
|
||||
"auto_update": false
|
||||
},
|
||||
"agent_skills": {},
|
||||
"effort": {
|
||||
"default": "high",
|
||||
"routing_tier_defaults": {
|
||||
"light": "low",
|
||||
"standard": "high",
|
||||
"heavy": "xhigh"
|
||||
},
|
||||
"agent_overrides": {}
|
||||
},
|
||||
"fast_mode": {
|
||||
"enabled": false,
|
||||
"routing_tier_defaults": {
|
||||
"light": true,
|
||||
"standard": false,
|
||||
"heavy": false
|
||||
},
|
||||
"agent_overrides": {}
|
||||
},
|
||||
"plan_review": {
|
||||
"source_grounding": true,
|
||||
"source_grounding_authority": "grep"
|
||||
}
|
||||
}
|
||||
191
gsd-core/bin/shared/config-schema.manifest.json
Normal file
191
gsd-core/bin/shared/config-schema.manifest.json
Normal file
@@ -0,0 +1,191 @@
|
||||
{
|
||||
"_comment": "Canonical schema manifest for valid config key paths. This manifest is the single CJS source of truth for valid config keys; dynamicKeyPatterns source strings are recompiled to RegExp at runtime by config-schema.cjs. runtimeStateKeys mirrors RUNTIME_STATE_KEYS.",
|
||||
"validKeys": [
|
||||
"mode",
|
||||
"granularity",
|
||||
"parallelization",
|
||||
"commit_docs",
|
||||
"model_profile",
|
||||
"search_gitignored",
|
||||
"brave_search",
|
||||
"firecrawl",
|
||||
"exa_search",
|
||||
"workflow.research",
|
||||
"workflow.plan_check",
|
||||
"workflow.verifier",
|
||||
"workflow.nyquist_validation",
|
||||
"workflow.ai_integration_phase",
|
||||
"workflow.ui_phase",
|
||||
"workflow.ui_safety_gate",
|
||||
"workflow.auto_advance",
|
||||
"workflow.node_repair",
|
||||
"workflow.node_repair_budget",
|
||||
"workflow.tdd_mode",
|
||||
"workflow.human_verify_mode",
|
||||
"workflow.text_mode",
|
||||
"workflow.research_before_questions",
|
||||
"workflow.discuss_mode",
|
||||
"workflow.skip_discuss",
|
||||
"workflow.auto_prune_state",
|
||||
"workflow.use_worktrees",
|
||||
"workflow.worktree_skip_hooks",
|
||||
"workflow.code_review",
|
||||
"workflow.code_review_depth",
|
||||
"workflow.code_review_command",
|
||||
"workflow.pattern_mapper",
|
||||
"workflow.plan_bounce",
|
||||
"workflow.plan_bounce_script",
|
||||
"workflow.plan_bounce_passes",
|
||||
"workflow.plan_chunked",
|
||||
"workflow.plan_review_convergence",
|
||||
"workflow.post_planning_gaps",
|
||||
"workflow.security_enforcement",
|
||||
"workflow.security_asvs_level",
|
||||
"workflow.security_block_on",
|
||||
"workflow.drift_threshold",
|
||||
"workflow.drift_action",
|
||||
"code_quality.fallow.enabled",
|
||||
"code_quality.fallow.scope",
|
||||
"code_quality.fallow.profile",
|
||||
"code_quality.fallow.mcp",
|
||||
"ship.pr_body_sections",
|
||||
"git.branching_strategy",
|
||||
"git.base_branch",
|
||||
"git.create_tag",
|
||||
"git.phase_branch_template",
|
||||
"git.milestone_branch_template",
|
||||
"git.quick_branch_template",
|
||||
"planning.commit_docs",
|
||||
"planning.search_gitignored",
|
||||
"planning.sub_repos",
|
||||
"review.ollama_host",
|
||||
"review.lm_studio_host",
|
||||
"review.llama_cpp_host",
|
||||
"review.default_reviewers",
|
||||
"review.max_prompt_tokens",
|
||||
"review.max_prompt_tokens_per_reviewer",
|
||||
"workflow.cross_ai_execution",
|
||||
"workflow.cross_ai_command",
|
||||
"workflow.cross_ai_timeout",
|
||||
"workflow.subagent_timeout",
|
||||
"executor.stall_detect_interval_minutes",
|
||||
"executor.stall_threshold_minutes",
|
||||
"workflow.inline_plan_threshold",
|
||||
"hooks.context_warnings",
|
||||
"hooks.workflow_guard",
|
||||
"workflow.context_coverage_gate",
|
||||
"statusline.show_last_command",
|
||||
"statusline.context_position",
|
||||
"workflow.ui_review",
|
||||
"workflow.max_discuss_passes",
|
||||
"features.thinking_partner",
|
||||
"context",
|
||||
"features.global_learnings",
|
||||
"learnings.max_inject",
|
||||
"project_code",
|
||||
"phase_id_convention",
|
||||
"phase_naming",
|
||||
"manager.flags.discuss",
|
||||
"manager.flags.plan",
|
||||
"manager.flags.execute",
|
||||
"response_language",
|
||||
"context_window",
|
||||
"intel.enabled",
|
||||
"graphify.enabled",
|
||||
"graphify.build_timeout",
|
||||
"graphify.auto_update",
|
||||
"claude_md_path",
|
||||
"claude_md_assembly.mode",
|
||||
"runtime",
|
||||
"resolve_model_ids",
|
||||
"effort.default",
|
||||
"fast_mode.enabled",
|
||||
"plan_review.source_grounding",
|
||||
"plan_review.source_grounding_authority",
|
||||
"model_policy.provider",
|
||||
"model_policy.budget",
|
||||
"model_policy.high",
|
||||
"model_policy.medium",
|
||||
"model_policy.low"
|
||||
],
|
||||
"runtimeStateKeys": [
|
||||
"workflow._auto_chain_active"
|
||||
],
|
||||
"dynamicKeyPatterns": [
|
||||
{
|
||||
"topLevel": "agent_skills",
|
||||
"source": "^agent_skills\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "agent_skills.<agent-type>"
|
||||
},
|
||||
{
|
||||
"topLevel": "review",
|
||||
"source": "^review\\.models\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "review.models.<cli-name>"
|
||||
},
|
||||
{
|
||||
"topLevel": "features",
|
||||
"source": "^features\\.[a-zA-Z0-9_]+$",
|
||||
"description": "features.<feature_name>"
|
||||
},
|
||||
{
|
||||
"topLevel": "claude_md_assembly",
|
||||
"source": "^claude_md_assembly\\.blocks\\.[a-zA-Z0-9_]+$",
|
||||
"description": "claude_md_assembly.blocks.<section>"
|
||||
},
|
||||
{
|
||||
"topLevel": "model_profile_overrides",
|
||||
"source": "^model_profile_overrides\\.[a-zA-Z0-9_-]+\\.(opus|sonnet|haiku)$",
|
||||
"description": "model_profile_overrides.<runtime>.<opus|sonnet|haiku>"
|
||||
},
|
||||
{
|
||||
"topLevel": "models",
|
||||
"source": "^models\\.(planning|discuss|research|execution|verification|completion)$",
|
||||
"description": "models.<planning|discuss|research|execution|verification|completion>"
|
||||
},
|
||||
{
|
||||
"topLevel": "granularities",
|
||||
"source": "^granularities\\.(planning|discuss|research|execution|verification|completion)$",
|
||||
"description": "granularities.<planning|discuss|research|execution|verification|completion>"
|
||||
},
|
||||
{
|
||||
"topLevel": "dynamic_routing",
|
||||
"source": "^dynamic_routing\\.(enabled|escalate_on_failure|max_escalations|tier_models\\.(light|standard|heavy))$",
|
||||
"description": "dynamic_routing.<enabled|escalate_on_failure|max_escalations|tier_models.<light|standard|heavy>>"
|
||||
},
|
||||
{
|
||||
"topLevel": "model_overrides",
|
||||
"source": "^model_overrides\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "model_overrides.<agent-id>"
|
||||
},
|
||||
{
|
||||
"topLevel": "effort",
|
||||
"source": "^effort\\.routing_tier_defaults\\.(light|standard|heavy)$",
|
||||
"description": "effort.routing_tier_defaults.<light|standard|heavy>"
|
||||
},
|
||||
{
|
||||
"topLevel": "effort",
|
||||
"source": "^effort\\.agent_overrides\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "effort.agent_overrides.<agent-id>"
|
||||
},
|
||||
{
|
||||
"topLevel": "fast_mode",
|
||||
"source": "^fast_mode\\.routing_tier_defaults\\.(light|standard|heavy)$",
|
||||
"description": "fast_mode.routing_tier_defaults.<light|standard|heavy>"
|
||||
},
|
||||
{
|
||||
"topLevel": "fast_mode",
|
||||
"source": "^fast_mode\\.agent_overrides\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "fast_mode.agent_overrides.<agent-id>"
|
||||
},
|
||||
{
|
||||
"topLevel": "review",
|
||||
"source": "^review\\.max_prompt_tokens_per_reviewer\\.[a-zA-Z0-9_-]+$",
|
||||
"description": "review.max_prompt_tokens_per_reviewer.<reviewer-slug>"
|
||||
},
|
||||
{
|
||||
"topLevel": "model_policy",
|
||||
"source": "^model_policy\\.runtime_tiers\\.[a-zA-Z0-9_-]+\\.(opus|sonnet|haiku)$",
|
||||
"description": "model_policy.runtime_tiers.<runtime>.<opus|sonnet|haiku>"
|
||||
}
|
||||
]
|
||||
}
|
||||
149
gsd-core/bin/shared/model-catalog.json
Normal file
149
gsd-core/bin/shared/model-catalog.json
Normal file
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"profiles": ["quality", "balanced", "budget", "adaptive", "inherit"],
|
||||
"phaseTypes": ["planning", "discuss", "research", "execution", "verification", "completion"],
|
||||
"adaptiveTierMap": {
|
||||
"heavy": "opus",
|
||||
"standard": "sonnet",
|
||||
"light": "haiku"
|
||||
},
|
||||
"runtimeTierDefaults": {
|
||||
"claude": {
|
||||
"opus": { "model": "claude-opus-4-8" },
|
||||
"sonnet": { "model": "claude-sonnet-4-6" },
|
||||
"haiku": { "model": "claude-haiku-4-5" }
|
||||
},
|
||||
"codex": {
|
||||
"opus": { "model": "gpt-5.5", "reasoning_effort": "xhigh" },
|
||||
"sonnet": { "model": "gpt-5.3-codex", "reasoning_effort": "medium" },
|
||||
"haiku": { "model": "gpt-5.4-mini", "reasoning_effort": "medium" }
|
||||
},
|
||||
"gemini": {
|
||||
"opus": { "model": "gemini-3-pro" },
|
||||
"sonnet": { "model": "gemini-3-flash" },
|
||||
"haiku": { "model": "gemini-2.5-flash-lite" }
|
||||
},
|
||||
"qwen": {
|
||||
"opus": { "model": "qwen3-max-2026-01-23" },
|
||||
"sonnet": { "model": "qwen3-coder-plus" },
|
||||
"haiku": { "model": "qwen3-coder-next" }
|
||||
},
|
||||
"opencode": {
|
||||
"opus": { "model": "anthropic/claude-opus-4-8" },
|
||||
"sonnet": { "model": "anthropic/claude-sonnet-4-6" },
|
||||
"haiku": { "model": "anthropic/claude-haiku-4-5" }
|
||||
},
|
||||
"copilot": {
|
||||
"opus": { "model": "claude-opus-4-8" },
|
||||
"sonnet": { "model": "claude-sonnet-4-6" },
|
||||
"haiku": { "model": "claude-haiku-4-5" }
|
||||
},
|
||||
"hermes": {
|
||||
"opus": { "model": "anthropic/claude-opus-4-8" },
|
||||
"sonnet": { "model": "anthropic/claude-sonnet-4-6" },
|
||||
"haiku": { "model": "anthropic/claude-haiku-4-5" }
|
||||
},
|
||||
"kilo": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"cline": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"cursor": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"windsurf": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"augment": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"trae": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"codebuddy": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
},
|
||||
"antigravity": {
|
||||
"opus": null,
|
||||
"sonnet": null,
|
||||
"haiku": null
|
||||
}
|
||||
},
|
||||
"providerPresets": {
|
||||
"anthropic": {
|
||||
"opus": { "low": { "model": "claude-opus-4-5" }, "medium": { "model": "claude-opus-4-8" }, "high": { "model": "claude-opus-4-8" } },
|
||||
"sonnet": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-sonnet-4-6" }, "high": { "model": "claude-opus-4-8" } },
|
||||
"haiku": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-haiku-4-5" }, "high": { "model": "claude-sonnet-4-6" } }
|
||||
},
|
||||
"openai": {
|
||||
"opus": { "low": { "model": "gpt-5.3-codex", "reasoning_effort": "medium" }, "medium": { "model": "gpt-5.5", "reasoning_effort": "high" }, "high": { "model": "gpt-5.5", "reasoning_effort": "xhigh" } },
|
||||
"sonnet": { "low": { "model": "gpt-5.4-mini", "reasoning_effort": "low" }, "medium": { "model": "gpt-5.3-codex", "reasoning_effort": "medium" }, "high": { "model": "gpt-5.5", "reasoning_effort": "medium" } },
|
||||
"haiku": { "low": { "model": "gpt-5.4-mini", "reasoning_effort": "minimal" }, "medium": { "model": "gpt-5.4-mini", "reasoning_effort": "medium" }, "high": { "model": "gpt-5.3-codex", "reasoning_effort": "medium" } }
|
||||
},
|
||||
"google": {
|
||||
"opus": { "low": { "model": "gemini-2.5-flash-lite" }, "medium": { "model": "gemini-3-flash" }, "high": { "model": "gemini-3-pro" } },
|
||||
"sonnet": { "low": { "model": "gemini-2.5-flash-lite" }, "medium": { "model": "gemini-3-flash" }, "high": { "model": "gemini-3-flash" } },
|
||||
"haiku": { "low": { "model": "gemini-2.5-flash-lite" }, "medium": { "model": "gemini-2.5-flash-lite" }, "high": { "model": "gemini-3-flash" } }
|
||||
},
|
||||
"qwen": {
|
||||
"opus": { "low": { "model": "qwen3-coder-plus" }, "medium": { "model": "qwen3-max-2026-01-23" }, "high": { "model": "qwen3-max-2026-01-23" } },
|
||||
"sonnet": { "low": { "model": "qwen3-coder-next" }, "medium": { "model": "qwen3-coder-plus" }, "high": { "model": "qwen3-max-2026-01-23" } },
|
||||
"haiku": { "low": { "model": "qwen3-coder-next" }, "medium": { "model": "qwen3-coder-next" }, "high": { "model": "qwen3-coder-plus" } }
|
||||
},
|
||||
"generic": {
|
||||
"opus": { "low": null, "medium": null, "high": null },
|
||||
"sonnet": { "low": null, "medium": null, "high": null },
|
||||
"haiku": { "low": null, "medium": null, "high": null }
|
||||
}
|
||||
},
|
||||
"agents": {
|
||||
"gsd-planner": { "golden": "opus", "balanced": "opus", "budget": "sonnet", "phaseType": "planning", "routingTier": "heavy" },
|
||||
"gsd-roadmapper": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "planning", "routingTier": "heavy" },
|
||||
"gsd-executor": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "execution", "routingTier": "standard" },
|
||||
"gsd-phase-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-project-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-research-synthesizer": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
|
||||
"gsd-debugger": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "execution", "routingTier": "heavy" },
|
||||
"gsd-codebase-mapper": { "golden": "sonnet", "balanced": "haiku", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
|
||||
"gsd-verifier": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "standard" },
|
||||
"gsd-plan-checker": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
"gsd-integration-checker": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
"gsd-nyquist-auditor": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
"gsd-pattern-mapper": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "planning", "routingTier": "light" },
|
||||
"gsd-ui-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-ui-checker": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
"gsd-ui-auditor": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
"gsd-doc-writer": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "execution", "routingTier": "standard" },
|
||||
"gsd-doc-verifier": { "golden": "sonnet", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "light" },
|
||||
|
||||
"gsd-advisor-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-ai-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-assumptions-analyzer": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "discuss", "routingTier": "heavy" },
|
||||
"gsd-code-fixer": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "execution", "routingTier": "standard" },
|
||||
"gsd-code-reviewer": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "verification", "routingTier": "standard" },
|
||||
"gsd-debug-session-manager": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "execution", "routingTier": "heavy" },
|
||||
"gsd-doc-classifier": { "golden": "sonnet", "balanced": "haiku", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
|
||||
"gsd-doc-synthesizer": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-domain-researcher": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "standard" },
|
||||
"gsd-eval-auditor": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "verification", "routingTier": "standard" },
|
||||
"gsd-eval-planner": { "golden": "opus", "balanced": "opus", "budget": "sonnet", "phaseType": "planning", "routingTier": "heavy" },
|
||||
"gsd-framework-selector": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "planning", "routingTier": "heavy" },
|
||||
"gsd-intel-updater": { "golden": "opus", "balanced": "sonnet", "budget": "haiku", "phaseType": "research", "routingTier": "light" },
|
||||
"gsd-security-auditor": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "verification", "routingTier": "heavy" },
|
||||
"gsd-user-profiler": { "golden": "opus", "balanced": "sonnet", "budget": "sonnet", "phaseType": "research", "routingTier": "heavy" }
|
||||
}
|
||||
}
|
||||
75
gsd-core/bin/shared/runtime-aliases.manifest.json
Normal file
75
gsd-core/bin/shared/runtime-aliases.manifest.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"claude": [
|
||||
"claude",
|
||||
"claude-code",
|
||||
"claude-cli"
|
||||
],
|
||||
"opencode": [
|
||||
"opencode",
|
||||
"open-code",
|
||||
"opencode-cli"
|
||||
],
|
||||
"kilo": [
|
||||
"kilo",
|
||||
"kilo-cli"
|
||||
],
|
||||
"gemini": [
|
||||
"gemini",
|
||||
"gemini-cli",
|
||||
"gemini-code"
|
||||
],
|
||||
"codex": [
|
||||
"codex",
|
||||
"codex-app",
|
||||
"codex-cli",
|
||||
"codex_desktop",
|
||||
"codex-desktop"
|
||||
],
|
||||
"copilot": [
|
||||
"copilot",
|
||||
"copilot-cli",
|
||||
"github-copilot"
|
||||
],
|
||||
"antigravity": [
|
||||
"antigravity",
|
||||
"antigravity-cli",
|
||||
"antigravity-agent"
|
||||
],
|
||||
"cursor": [
|
||||
"cursor",
|
||||
"cursor-cli",
|
||||
"cursor-nightly"
|
||||
],
|
||||
"windsurf": [
|
||||
"windsurf",
|
||||
"windsurf-cli",
|
||||
"windsurf-next"
|
||||
],
|
||||
"augment": [
|
||||
"augment",
|
||||
"augment-code",
|
||||
"augment-cli"
|
||||
],
|
||||
"trae": [
|
||||
"trae",
|
||||
"trae-cli"
|
||||
],
|
||||
"qwen": [
|
||||
"qwen",
|
||||
"qwen-code",
|
||||
"qwen-cli"
|
||||
],
|
||||
"hermes": [
|
||||
"hermes",
|
||||
"hermes-agent",
|
||||
"hermes-cli"
|
||||
],
|
||||
"codebuddy": [
|
||||
"codebuddy",
|
||||
"codebuddy-cli"
|
||||
],
|
||||
"cline": [
|
||||
"cline",
|
||||
"cline-cli"
|
||||
]
|
||||
}
|
||||
352
gsd-core/bin/verify-reapply-patches.cjs
Executable file
352
gsd-core/bin/verify-reapply-patches.cjs
Executable file
@@ -0,0 +1,352 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Deterministic verifier for the /gsd-reapply-patches Step 5 "Hunk Verification
|
||||
* Gate". For each backed-up patch file, asserts that the user's added lines
|
||||
* (computed from a real diff against the pristine baseline, not from the
|
||||
* LLM's prose summary) survive into the merged output.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/verify-reapply-patches.cjs \
|
||||
* --patches-dir <path> \ # gsd-local-patches/
|
||||
* --config-dir <path> \ # ~/.claude (or runtime equivalent)
|
||||
* [--pristine-dir <path>] # gsd-pristine/; if absent, falls back to
|
||||
* # treating every significant backup line as
|
||||
* # required (over-broad but safe for #2969:
|
||||
* # false-positive halts beat silent successes
|
||||
* # on lost content)
|
||||
* [--json] # emit JSON report instead of human text
|
||||
*
|
||||
* Exit codes:
|
||||
* 0 — every user-added line is present in the merged file (gate passes)
|
||||
* 1 — at least one missing line in at least one file (gate fails)
|
||||
* 2 — usage / structural error (e.g. patches dir missing)
|
||||
*
|
||||
* Bug #2969: the Step 5 gate previously trusted Claude's free-text "verified:
|
||||
* yes/no" reporting per hunk. The LLM was filling in `yes` even when content
|
||||
* had been silently dropped. Moving the check to a deterministic script is the
|
||||
* durability fix.
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const crypto = require('node:crypto');
|
||||
|
||||
const SIGNIFICANT_MIN_CHARS = 12;
|
||||
const GSD_HOOK_VERSION_LINE_RE = /^(?:\/\/|#)\s*gsd-hook-version:\s*\S+\s*$/i;
|
||||
|
||||
function parseArgs(argv) {
|
||||
const opts = { patchesDir: null, configDir: null, pristineDir: null, json: false };
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
const arg = argv[i];
|
||||
if (arg === '--patches-dir') opts.patchesDir = argv[++i];
|
||||
else if (arg === '--config-dir') opts.configDir = argv[++i];
|
||||
else if (arg === '--pristine-dir') opts.pristineDir = argv[++i];
|
||||
else if (arg === '--json') opts.json = true;
|
||||
else if (arg === '--help' || arg === '-h') {
|
||||
process.stdout.write(
|
||||
'usage: verify-reapply-patches.cjs --patches-dir <path> --config-dir <path> [--pristine-dir <path>] [--json]\n',
|
||||
);
|
||||
process.exit(0);
|
||||
} else {
|
||||
process.stderr.write(`unknown argument: ${arg}\n`);
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
function isSignificantLine(line) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.length < SIGNIFICANT_MIN_CHARS) return false;
|
||||
// Pure punctuation / closing brackets carry too little structural info to
|
||||
// reliably distinguish a survived hunk from incidental similarity.
|
||||
if (/^[\s})\];,]+$/.test(trimmed)) return false;
|
||||
// Generic decorative comments like `// ----` similarly fail the test.
|
||||
if (/^[\s\-=#*/]+$/.test(trimmed)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function normalizeUpstreamOwnedLine(line) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) return line;
|
||||
if (GSD_HOOK_VERSION_LINE_RE.test(trimmed)) {
|
||||
const prefix = trimmed.startsWith('#') ? '#' : '//';
|
||||
return `${prefix} gsd-hook-version: __GSD_VERSION_TOKEN__`;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the SHA-256 hex digest of a string (UTF-8 encoded).
|
||||
*/
|
||||
function sha256(content) {
|
||||
return crypto.createHash('sha256').update(content, 'utf8').digest('hex');
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the `pristine_hashes` map from backup-meta.json in the patches dir.
|
||||
* Returns an empty object if backup-meta.json is absent, unreadable, or has no
|
||||
* `pristine_hashes` field — callers must treat an empty map as "no recorded
|
||||
* hash for any file" (no hash-validation possible, not an error).
|
||||
*/
|
||||
function readPristineHashes(patchesDir) {
|
||||
const metaPath = path.join(patchesDir, 'backup-meta.json');
|
||||
try {
|
||||
const raw = fs.readFileSync(metaPath, 'utf8');
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed && typeof parsed.pristine_hashes === 'object' && parsed.pristine_hashes !== null) {
|
||||
return parsed.pristine_hashes;
|
||||
}
|
||||
} catch {
|
||||
// absent or unreadable — not an error, just no recorded hashes
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk a directory, returning every file's path relative to the root.
|
||||
*/
|
||||
function walk(rootDir, relPrefix = '') {
|
||||
const out = [];
|
||||
if (!fs.existsSync(rootDir)) return out;
|
||||
for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {
|
||||
const rel = relPrefix ? path.join(relPrefix, entry.name) : entry.name;
|
||||
const abs = path.join(rootDir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
out.push(...walk(abs, rel));
|
||||
} else if (entry.isFile()) {
|
||||
out.push(rel);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the set of "user-added" lines: lines present in the backup but
|
||||
* absent from the pristine baseline. If no pristine is provided, falls back
|
||||
* to using every significant line in the backup (over-broad but safe — favours
|
||||
* false-positive failures over silent successes, which is the right side to
|
||||
* err on for #2969).
|
||||
*/
|
||||
function computeUserAddedLines(backupContent, pristineContent) {
|
||||
const backupLines = backupContent.split(/\r?\n/);
|
||||
if (!pristineContent) {
|
||||
return backupLines.filter(isSignificantLine);
|
||||
}
|
||||
const pristineSet = new Set(
|
||||
pristineContent.split(/\r?\n/).map(normalizeUpstreamOwnedLine),
|
||||
);
|
||||
return backupLines.filter((line) => {
|
||||
if (!isSignificantLine(line)) return false;
|
||||
return !pristineSet.has(normalizeUpstreamOwnedLine(line));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Stable reason codes for the per-file result. Tests assert via
|
||||
* `assert.equal(result.reason, REASON.X)` rather than regex-matching prose,
|
||||
* so the diagnostic surface is a typed enum, not free text.
|
||||
*
|
||||
* Adding a new reason requires updating the REASON map AND the tests'
|
||||
* shape assertion that locks the documented set of codes.
|
||||
*/
|
||||
const REASON = Object.freeze({
|
||||
OK_NO_USER_LINES_VS_PRISTINE: 'ok_no_user_lines_vs_pristine',
|
||||
OK_NO_SIGNIFICANT_BACKUP_LINES: 'ok_no_significant_backup_lines',
|
||||
// Bug #3657: the on-disk gsd-pristine/ file's SHA-256 does not match the
|
||||
// hash recorded in backup-meta.json.pristine_hashes. This means the
|
||||
// pristine snapshot was refreshed to a newer GSD version after the backup
|
||||
// was captured. Using the wrong-version pristine as the diff baseline would
|
||||
// invert the delta (upstream removals appear as "missing user lines").
|
||||
// The verifier skips this file rather than false-failing it. A separate
|
||||
// re-anchor step (or the git-aware fallback in the workflow) is needed to
|
||||
// resolve this file; the guard here ensures the gate does not report spurious
|
||||
// failures in the meantime.
|
||||
OK_PRISTINE_DRIFT_DETECTED: 'ok_pristine_drift_detected',
|
||||
FAIL_INSTALLED_MISSING: 'fail_installed_missing',
|
||||
FAIL_INSTALLED_NOT_REGULAR_FILE: 'fail_installed_not_regular_file',
|
||||
FAIL_READ_ERROR: 'fail_read_error',
|
||||
FAIL_USER_LINES_MISSING: 'fail_user_lines_missing',
|
||||
});
|
||||
|
||||
function verifyFile({ relPath, patchesDir, configDir, pristineDir, pristineHashes }) {
|
||||
const backupPath = path.join(patchesDir, relPath);
|
||||
const installedPath = path.join(configDir, relPath);
|
||||
const result = { file: relPath, status: 'ok', missing: [], reason: null };
|
||||
|
||||
if (!fs.existsSync(backupPath) || !fs.statSync(backupPath).isFile()) {
|
||||
return result; // walked entry no longer exists — non-fatal
|
||||
}
|
||||
|
||||
// Installed path checks: must exist, must be a regular file, must be
|
||||
// readable. Anything else is a fail-with-diagnostic, not a crash that
|
||||
// aborts the whole gate run and drops structured output.
|
||||
let installedStat;
|
||||
try {
|
||||
installedStat = fs.statSync(installedPath);
|
||||
} catch {
|
||||
result.status = 'fail';
|
||||
result.reason = REASON.FAIL_INSTALLED_MISSING;
|
||||
return result;
|
||||
}
|
||||
if (!installedStat.isFile()) {
|
||||
result.status = 'fail';
|
||||
result.reason = REASON.FAIL_INSTALLED_NOT_REGULAR_FILE;
|
||||
return result;
|
||||
}
|
||||
|
||||
let backupContent;
|
||||
let installedContent;
|
||||
try {
|
||||
backupContent = fs.readFileSync(backupPath, 'utf8');
|
||||
installedContent = fs.readFileSync(installedPath, 'utf8');
|
||||
} catch {
|
||||
result.status = 'fail';
|
||||
result.reason = REASON.FAIL_READ_ERROR;
|
||||
return result;
|
||||
}
|
||||
|
||||
let pristineContent = null;
|
||||
if (pristineDir) {
|
||||
const pristinePath = path.join(pristineDir, relPath);
|
||||
try {
|
||||
const stat = fs.statSync(pristinePath);
|
||||
if (stat.isFile()) {
|
||||
const candidate = fs.readFileSync(pristinePath, 'utf8');
|
||||
// Bug #3657: if backup-meta.json recorded a pristine_hash for this
|
||||
// file, validate that the on-disk pristine matches it. A mismatch
|
||||
// means the installer refreshed gsd-pristine/ to a newer GSD version
|
||||
// after the backup was captured. Using the wrong-version pristine as
|
||||
// the diff baseline inverts the delta: upstream removals appear as
|
||||
// "user-added lines that must survive", causing FAIL_USER_LINES_MISSING
|
||||
// false positives. When the hash is stale, skip the pristine and fall
|
||||
// through to over-broad mode (every significant backup line is checked).
|
||||
// Over-broad mode never false-fails for a different reason because all
|
||||
// backup lines that are genuinely user-added will still be present in a
|
||||
// correctly merged install.
|
||||
// Normalize to forward slashes so the key lookup matches on Windows
|
||||
// where path.join produces backslash-separated relPath values but
|
||||
// backup-meta.json stores keys written with forward slashes.
|
||||
const hashKey = relPath.replace(/\\/g, '/');
|
||||
const recordedHash = pristineHashes && pristineHashes[hashKey];
|
||||
if (recordedHash) {
|
||||
if (sha256(candidate) === recordedHash) {
|
||||
// Hash matches: the on-disk pristine is the correct baseline.
|
||||
pristineContent = candidate;
|
||||
} else {
|
||||
// Hash mismatch: the on-disk gsd-pristine/ was refreshed to a newer
|
||||
// GSD version after the backup was captured. Using it as the diff
|
||||
// baseline would invert the delta and produce false FAIL_USER_LINES_MISSING
|
||||
// reports (Bug #3657). Report the file as ok with a diagnostic code
|
||||
// so the gate does not false-fail; a re-anchor or git-aware baseline
|
||||
// step is required to verify this file correctly.
|
||||
result.reason = REASON.OK_PRISTINE_DRIFT_DETECTED;
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
// No recorded hash for this file (older installer or absent
|
||||
// backup-meta) — use the on-disk pristine as-is (pre-fix behaviour).
|
||||
pristineContent = candidate;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Pristine missing or unreadable — fall through to over-broad mode.
|
||||
}
|
||||
}
|
||||
|
||||
const userAdded = computeUserAddedLines(backupContent, pristineContent);
|
||||
if (userAdded.length === 0) {
|
||||
// Backup and pristine match exactly (or no significant content) — nothing
|
||||
// to verify but also nothing to lose. Report as ok with diagnostic code.
|
||||
result.reason = pristineContent
|
||||
? REASON.OK_NO_USER_LINES_VS_PRISTINE
|
||||
: REASON.OK_NO_SIGNIFICANT_BACKUP_LINES;
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const line of userAdded) {
|
||||
if (!installedContent.includes(line)) {
|
||||
result.missing.push(line.trim());
|
||||
}
|
||||
}
|
||||
if (result.missing.length > 0) {
|
||||
result.status = 'fail';
|
||||
result.reason = REASON.FAIL_USER_LINES_MISSING;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const opts = parseArgs(process.argv.slice(2));
|
||||
if (!opts.patchesDir || !opts.configDir) {
|
||||
process.stderr.write('--patches-dir and --config-dir are required\n');
|
||||
process.exit(2);
|
||||
}
|
||||
if (!fs.existsSync(opts.patchesDir)) {
|
||||
process.stderr.write(`patches dir not found: ${opts.patchesDir}\n`);
|
||||
process.exit(2);
|
||||
}
|
||||
if (!fs.existsSync(opts.configDir)) {
|
||||
process.stderr.write(`config dir not found: ${opts.configDir}\n`);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const files = walk(opts.patchesDir).filter((f) => !f.endsWith('backup-meta.json'));
|
||||
// Bug #3657: read pristine_hashes from backup-meta.json once and share
|
||||
// across all per-file verifications so each can detect drift independently.
|
||||
const pristineHashes = readPristineHashes(opts.patchesDir);
|
||||
const results = files.map((relPath) =>
|
||||
verifyFile({
|
||||
relPath,
|
||||
patchesDir: opts.patchesDir,
|
||||
configDir: opts.configDir,
|
||||
pristineDir: opts.pristineDir,
|
||||
pristineHashes,
|
||||
}),
|
||||
);
|
||||
|
||||
const failures = results.filter((r) => r.status === 'fail');
|
||||
|
||||
// Bug #3657 (Finding 1): aggregate drifted files into top-level report fields
|
||||
// so workflow Step 5a can gate on drift distinctly from failures. Drift is
|
||||
// NOT a failure (exit code stays 0) but the workflow now has structured data
|
||||
// to decide whether to proceed. Per-file shape is unchanged: each drifted
|
||||
// result still has status:'ok' + reason:OK_PRISTINE_DRIFT_DETECTED for
|
||||
// backward compat. The new top-level fields are purely additive.
|
||||
const driftedResults = results.filter((r) => r.reason === REASON.OK_PRISTINE_DRIFT_DETECTED);
|
||||
const drifted = driftedResults.length;
|
||||
const drifted_files = driftedResults.map((r) => r.file);
|
||||
|
||||
if (opts.json) {
|
||||
process.stdout.write(
|
||||
JSON.stringify({ checked: results.length, failures: failures.length, drifted, drifted_files, results }, null, 2) + '\n',
|
||||
);
|
||||
} else {
|
||||
process.stdout.write(`# Hunk Verification Gate (#2969)\n\n`);
|
||||
process.stdout.write(`Checked: ${results.length} file(s)\n`);
|
||||
process.stdout.write(`Failures: ${failures.length}\n\n`);
|
||||
if (failures.length > 0) {
|
||||
process.stdout.write(`## Files with missing user-added content\n\n`);
|
||||
for (const r of failures) {
|
||||
process.stdout.write(`- ${r.file}\n`);
|
||||
if (r.reason) process.stdout.write(` reason: ${r.reason}\n`);
|
||||
for (const line of r.missing.slice(0, 5)) {
|
||||
process.stdout.write(` missing: ${line}\n`);
|
||||
}
|
||||
if (r.missing.length > 5) {
|
||||
process.stdout.write(` …and ${r.missing.length - 5} more line(s)\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(failures.length > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = { computeUserAddedLines, isSignificantLine, verifyFile, walk, REASON, readPristineHashes, sha256 };
|
||||
21
gsd-core/contexts/dev.md
Normal file
21
gsd-core/contexts/dev.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Dev Context Profile
|
||||
|
||||
Agent output guidance for dev mode. Loaded when `context: dev` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Concise, action-oriented responses
|
||||
- Lead with the code change or command, follow with brief rationale
|
||||
- Skip preamble — assume the developer has full context
|
||||
- Use inline code references (`file:line`) over prose descriptions
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Working code that compiles and passes tests
|
||||
- Minimal diff — change only what is necessary
|
||||
- Flag side effects or breaking changes immediately
|
||||
- Surface the next actionable step at the end of every response
|
||||
|
||||
## Verbosity
|
||||
|
||||
Low. One-liner explanations unless the change is non-obvious. Omit background theory, alternative approaches, and caveats that do not affect the current task.
|
||||
22
gsd-core/contexts/research.md
Normal file
22
gsd-core/contexts/research.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Research Context Profile
|
||||
|
||||
Agent output guidance for research mode. Loaded when `context: research` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Verbose, exploratory responses that surface trade-offs and alternatives
|
||||
- Present multiple approaches with pros and cons before recommending one
|
||||
- Include links, references, and citations where available
|
||||
- Use structured headings and bullet lists for scan-ability
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Breadth of options — enumerate before narrowing
|
||||
- Prior art and ecosystem conventions
|
||||
- Risks, edge cases, and failure modes
|
||||
- Dependencies and compatibility implications
|
||||
- Long-term maintainability of each approach
|
||||
|
||||
## Verbosity
|
||||
|
||||
High. Explain reasoning, show evidence, and document assumptions. Include background context even if the developer likely knows it — research artifacts are read by future contributors who may not.
|
||||
23
gsd-core/contexts/review.md
Normal file
23
gsd-core/contexts/review.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Review Context Profile
|
||||
|
||||
Agent output guidance for review mode. Loaded when `context: review` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Critical, detail-focused responses that prioritize correctness
|
||||
- Organize findings by severity: blocking, important, nit
|
||||
- Reference specific lines and files for every finding
|
||||
- State what is correct as well as what needs change — confirm the good parts
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Correctness — logic errors, off-by-ones, missing edge cases
|
||||
- Security — input validation, injection vectors, secret exposure
|
||||
- Performance — unnecessary allocations, O(n^2) patterns, missing caching
|
||||
- Style and consistency — naming, formatting, import order
|
||||
- Test coverage — untested branches, missing assertions, flaky patterns
|
||||
- Structural Findings (fallow) — machine-derived cross-module facts injected as `<structural_findings>{ findings: [...], summary: { total, unusedExports, duplicates, circularDependencies } }</structural_findings>`. Render in REVIEW.md under `## Structural Findings (fallow)` as a separate section from narrative findings. Treat as ground truth for cross-module facts; do not re-derive.
|
||||
|
||||
## Verbosity
|
||||
|
||||
Medium. Be thorough on findings but terse in explanation. Each issue should be one to three sentences: what is wrong, why it matters, and how to fix it.
|
||||
79
gsd-core/references/agent-contracts.md
Normal file
79
gsd-core/references/agent-contracts.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Agent Contracts
|
||||
|
||||
Completion markers and handoff schemas for all GSD agents. Workflows use these markers to detect agent completion and route accordingly.
|
||||
|
||||
This doc describes what IS, not what should be. Casing inconsistencies are documented as they appear in agent source files.
|
||||
|
||||
---
|
||||
|
||||
## Agent Registry
|
||||
|
||||
| Agent | Role | Completion Markers |
|
||||
|-------|------|--------------------|
|
||||
| gsd-planner | Plan creation | `## PLANNING COMPLETE` |
|
||||
| gsd-executor | Plan execution | `## PLAN COMPLETE`, `## CHECKPOINT REACHED` |
|
||||
| gsd-phase-researcher | Phase-scoped research | `## RESEARCH COMPLETE`, `## RESEARCH BLOCKED` |
|
||||
| gsd-project-researcher | Project-wide research | `## RESEARCH COMPLETE`, `## RESEARCH BLOCKED` |
|
||||
| gsd-plan-checker | Plan validation | `## VERIFICATION PASSED`, `## ISSUES FOUND` |
|
||||
| gsd-research-synthesizer | Multi-research synthesis | `## SYNTHESIS COMPLETE`, `## SYNTHESIS BLOCKED` |
|
||||
| gsd-debugger | Debug investigation | `## DEBUG COMPLETE`, `## ROOT CAUSE FOUND`, `## CHECKPOINT REACHED` |
|
||||
| gsd-roadmapper | Roadmap creation/revision | `## ROADMAP CREATED`, `## ROADMAP REVISED`, `## ROADMAP BLOCKED` |
|
||||
| gsd-ui-auditor | UI review | `## UI REVIEW COMPLETE` |
|
||||
| gsd-ui-checker | UI validation | `## ISSUES FOUND` |
|
||||
| gsd-ui-researcher | UI spec creation | `## UI-SPEC COMPLETE`, `## UI-SPEC BLOCKED` |
|
||||
| gsd-verifier | Post-execution verification | `## Verification Complete` (title case) |
|
||||
| gsd-integration-checker | Cross-phase integration check | `## Integration Check Complete` (title case) |
|
||||
| gsd-nyquist-auditor | Sampling audit | `## PARTIAL`, `## ESCALATE` (non-standard) |
|
||||
| gsd-security-auditor | Security audit | `## OPEN_THREATS`, `## ESCALATE` (non-standard) |
|
||||
| gsd-codebase-mapper | Codebase analysis | No marker (writes docs directly) |
|
||||
| gsd-assumptions-analyzer | Assumption extraction | No marker (returns `## Assumptions` sections) |
|
||||
| gsd-doc-verifier | Doc validation | No marker (writes JSON to `.planning/tmp/`) |
|
||||
| gsd-doc-writer | Doc generation | No marker (writes docs directly) |
|
||||
| gsd-advisor-researcher | Advisory research | No marker (utility agent) |
|
||||
| gsd-user-profiler | User profiling | No marker (returns JSON in analysis tags) |
|
||||
| gsd-intel-updater | Codebase intelligence analysis | `## INTEL UPDATE COMPLETE`, `## INTEL UPDATE FAILED` |
|
||||
|
||||
## Marker Rules
|
||||
|
||||
1. **ALL-CAPS markers** (e.g., `## PLANNING COMPLETE`) are the standard convention
|
||||
2. **Title-case markers** (e.g., `## Verification Complete`) exist in gsd-verifier and gsd-integration-checker -- these are intentional as-is, not bugs
|
||||
3. **Non-standard markers** (e.g., `## PARTIAL`, `## ESCALATE`) in audit agents indicate partial results requiring orchestrator judgment
|
||||
4. **Agents without markers** either write artifacts directly to disk or return structured data (JSON/sections) that the caller parses
|
||||
5. Markers must appear as H2 headings (`## `) at the start of a line in the agent's final output
|
||||
|
||||
## Key Handoff Contracts
|
||||
|
||||
### Planner -> Executor (via PLAN.md)
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| Frontmatter | Yes | phase, plan, type, wave, depends_on, files_modified, autonomous, requirements |
|
||||
| `<objective>` | Yes | What the plan achieves |
|
||||
| `<tasks>` | Yes | Ordered task list with type, files, action, verify, acceptance_criteria |
|
||||
| `<verification>` | Yes | Overall verification steps |
|
||||
| `<success_criteria>` | Yes | Measurable completion criteria |
|
||||
|
||||
### Executor -> Verifier (via SUMMARY.md)
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| Frontmatter | Yes | phase, plan, subsystem, tags, key-files, metrics |
|
||||
| Commits table | Yes | Per-task commit hashes and descriptions |
|
||||
| Deviations section | Yes | Auto-fixed issues or "None" |
|
||||
| Self-Check | Yes | PASSED or FAILED with details |
|
||||
|
||||
## Workflow Regex Patterns
|
||||
|
||||
Workflows match these markers to detect agent completion:
|
||||
|
||||
**plan-phase.md matches:**
|
||||
- `## RESEARCH COMPLETE` / `## RESEARCH BLOCKED` (researcher output)
|
||||
- `## PLANNING COMPLETE` (planner output)
|
||||
- `## CHECKPOINT REACHED` (planner/executor pause)
|
||||
- `## VERIFICATION PASSED` / `## ISSUES FOUND` (plan-checker output)
|
||||
|
||||
**execute-phase.md matches:**
|
||||
- `## PHASE COMPLETE` (all plans in phase done)
|
||||
- `## Self-Check: FAILED` (summary self-check)
|
||||
|
||||
> **NOTE:** `## PLAN COMPLETE` is the gsd-executor's completion marker but execute-phase.md does not regex-match it. Instead, it detects executor completion via spot-checks (SUMMARY.md existence, git commit state). This is intentional behavior, not a mismatch.
|
||||
156
gsd-core/references/ai-evals.md
Normal file
156
gsd-core/references/ai-evals.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# AI Evaluation Reference
|
||||
|
||||
> Reference used by `gsd-eval-planner` and `gsd-eval-auditor`.
|
||||
> Based on "AI Evals for Everyone" course (Reganti & Badam) + industry practice.
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Why Evals Exist
|
||||
AI systems are non-deterministic. Input X does not reliably produce output Y across runs, users, or edge cases. Evals are the continuous process of assessing whether your system's behavior meets expectations under real-world conditions — unit tests and integration tests alone are insufficient.
|
||||
|
||||
### Model vs. Product Evaluation
|
||||
- **Model evals** (MMLU, HumanEval, GSM8K) — measure general capability in standardized conditions. Use as initial filter only.
|
||||
- **Product evals** — measure behavior inside your specific system, with your data, your users, your domain rules. This is where 80% of eval effort belongs.
|
||||
|
||||
### The Three Components of Every Eval
|
||||
- **Input** — everything affecting the system: query, history, retrieved docs, system prompt, config
|
||||
- **Expected** — what good behavior looks like, defined through rubrics
|
||||
- **Actual** — what the system produced, including intermediate steps, tool calls, and reasoning traces
|
||||
|
||||
### Three Measurement Approaches
|
||||
1. **Code-based metrics** — deterministic checks: JSON validation, required disclaimers, performance thresholds, classification flags. Fast, cheap, reliable. Use first.
|
||||
2. **LLM judges** — one model evaluates another against a rubric. Powerful for subjective qualities (tone, reasoning, escalation). Requires calibration against human judgment before trusting.
|
||||
3. **Human evaluation** — gold standard for nuanced judgment. Doesn't scale. Use for calibration, edge cases, periodic sampling, and high-stakes decisions.
|
||||
|
||||
Most effective systems combine all three.
|
||||
|
||||
---
|
||||
|
||||
## Evaluation Dimensions
|
||||
|
||||
### Pre-Deployment (Development Phase)
|
||||
|
||||
| Dimension | What It Measures | When It Matters |
|
||||
|-----------|-----------------|-----------------|
|
||||
| **Factual accuracy** | Correctness of claims against ground truth | RAG, knowledge bases, any factual assertions |
|
||||
| **Context faithfulness** | Response grounded in provided context vs. fabricated | RAG pipelines, document Q&A, retrieval-augmented systems |
|
||||
| **Hallucination detection** | Plausible but unsupported claims | All generative systems, high-stakes domains |
|
||||
| **Escalation accuracy** | Correct identification of when human intervention needed | Customer service, healthcare, financial advisory |
|
||||
| **Policy compliance** | Adherence to business rules, legal requirements, disclaimers | Regulated industries, enterprise deployments |
|
||||
| **Tone/style appropriateness** | Match with brand voice, audience expectations, emotional context | Customer-facing systems, content generation |
|
||||
| **Output structure validity** | Schema compliance, required fields, format correctness | Structured extraction, API integrations, data pipelines |
|
||||
| **Task completion** | Whether the system accomplished the stated goal | Agentic workflows, multi-step tasks |
|
||||
| **Tool use correctness** | Correct selection and invocation of tools | Agent systems with tool calls |
|
||||
| **Safety** | Absence of harmful, biased, or inappropriate outputs | All user-facing systems |
|
||||
|
||||
### Production Monitoring
|
||||
|
||||
| Dimension | Monitoring Approach |
|
||||
|-----------|---------------------|
|
||||
| **Safety violations** | Online guardrail — real-time, immediate intervention |
|
||||
| **Compliance failures** | Online guardrail — block or escalate before user sees output |
|
||||
| **Quality degradation trends** | Offline flywheel — batch analysis of sampled interactions |
|
||||
| **Emerging failure modes** | Signal-metric divergence — when user behavior signals diverge from metric scores, investigate manually |
|
||||
| **Cost/latency drift** | Code-based metrics — automated threshold alerts |
|
||||
|
||||
---
|
||||
|
||||
## The Guardrail vs. Flywheel Decision
|
||||
|
||||
Ask: "If this behavior goes wrong, would it be catastrophic for my business?"
|
||||
|
||||
- **Yes → Guardrail** — run online, real-time, with immediate intervention (block, escalate, hand off). Be selective: guardrails add latency.
|
||||
- **No → Flywheel** — run offline as batch analysis feeding system refinements over time.
|
||||
|
||||
---
|
||||
|
||||
## Rubric Design
|
||||
|
||||
Generic metrics are meaningless without context. "Helpfulness" in real estate means summarizing listings clearly. In healthcare it means knowing when *not* to answer.
|
||||
|
||||
A rubric must define:
|
||||
1. The dimension being measured
|
||||
2. What scores 1, 3, and 5 on a 5-point scale (or pass/fail criteria)
|
||||
3. Domain-specific examples of acceptable vs. unacceptable behavior
|
||||
|
||||
Without rubrics, LLM judges produce noise rather than signal.
|
||||
|
||||
---
|
||||
|
||||
## Reference Dataset Guidelines
|
||||
|
||||
- Start with **10-20 high-quality examples** — not 200 mediocre ones
|
||||
- Cover: critical success scenarios, common user workflows, known edge cases, historical failure modes
|
||||
- Have domain experts label the examples (not just engineers)
|
||||
- Expand based on what you learn in production — don't build for hypothetical coverage
|
||||
|
||||
---
|
||||
|
||||
## Eval Tooling Guide
|
||||
|
||||
| Tool | Type | Best For | Key Strength |
|
||||
|------|------|----------|-------------|
|
||||
| **RAGAS** | Python library | RAG evaluation | Purpose-built metrics: faithfulness, answer relevance, context precision/recall |
|
||||
| **Langfuse** | Platform (open-source, self-hostable) | All system types | Strong tracing, prompt management, good for teams wanting infrastructure control |
|
||||
| **LangSmith** | Platform (commercial) | LangChain/LangGraph ecosystems | Tightest integration with LangChain; best if already in that ecosystem |
|
||||
| **Arize Phoenix** | Platform (open-source + hosted) | RAG + multi-agent tracing | Strong RAG eval + trace visualization; open-source with hosted option |
|
||||
| **Braintrust** | Platform (commercial) | Model-agnostic evaluation | Dataset and experiment management; good for comparing across frameworks |
|
||||
| **Promptfoo** | CLI tool (open-source) | Prompt testing, CI/CD | CLI-first, excellent for CI/CD prompt regression testing |
|
||||
|
||||
### Tool Selection by System Type
|
||||
|
||||
| System Type | Recommended Tooling |
|
||||
|-------------|---------------------|
|
||||
| RAG / Knowledge Q&A | RAGAS + Arize Phoenix or Braintrust |
|
||||
| Multi-agent systems | Langfuse + Arize Phoenix |
|
||||
| Conversational / single-model | Promptfoo + Braintrust |
|
||||
| Structured extraction | Promptfoo + code-based validators |
|
||||
| LangChain/LangGraph projects | LangSmith (native integration) |
|
||||
| Production monitoring (all types) | Langfuse, Arize Phoenix, or LangSmith |
|
||||
|
||||
---
|
||||
|
||||
## Evals in the Development Lifecycle
|
||||
|
||||
### Plan Phase (Evaluation-Aware Design)
|
||||
Before writing code, define:
|
||||
1. What type of AI system is being built → determines framework and dominant eval concerns
|
||||
2. Critical failure modes (3-5 behaviors that cannot go wrong)
|
||||
3. Rubrics — explicit definitions of acceptable/unacceptable behavior per dimension
|
||||
4. Evaluation strategy — which dimensions use code metrics, LLM judges, or human review
|
||||
5. Reference dataset requirements — size, composition, labeling approach
|
||||
6. Eval tooling selection
|
||||
|
||||
Output: EVALS-SPEC section of AI-SPEC.md
|
||||
|
||||
### Execute Phase (Instrument While Building)
|
||||
- Add tracing from day one (Langfuse, Arize Phoenix, or LangSmith)
|
||||
- Build reference dataset concurrently with implementation
|
||||
- Implement code-based checks first; add LLM judges only for subjective dimensions
|
||||
- Run evals in CI/CD via Promptfoo or Braintrust
|
||||
|
||||
### Verify Phase (Pre-Deployment Validation)
|
||||
- Run full reference dataset against all metrics
|
||||
- Conduct human review of edge cases and LLM judge disagreements
|
||||
- Calibrate LLM judges against human scores (target ≥ 0.7 correlation before trusting)
|
||||
- Define and configure production guardrails
|
||||
- Establish monitoring baseline
|
||||
|
||||
### Monitor Phase (Production Evaluation Loop)
|
||||
- Smart sampling — weight toward interactions with concerning signals (retries, unusual length, explicit escalations)
|
||||
- Online guardrails on every interaction
|
||||
- Offline flywheel on sampled batch
|
||||
- Watch for signal-metric divergence — the early warning system for evaluation gaps
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Assuming benchmarks predict product success** — they don't; model evals are a filter, not a verdict
|
||||
2. **Engineering evals in isolation** — domain experts must co-define rubrics; engineers alone miss critical nuances
|
||||
3. **Building comprehensive coverage on day one** — start small (10-20 examples), expand from real failure modes
|
||||
4. **Trusting uncalibrated LLM judges** — validate against human judgment before relying on them
|
||||
5. **Measuring everything** — only track metrics that drive decisions; "collect it all" produces noise
|
||||
6. **Treating evaluation as one-time setup** — user behavior evolves, requirements change, failure modes emerge; evaluation is continuous
|
||||
186
gsd-core/references/ai-frameworks.md
Normal file
186
gsd-core/references/ai-frameworks.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# AI Framework Decision Matrix
|
||||
|
||||
> Reference used by `gsd-framework-selector` and `gsd-ai-researcher`.
|
||||
> Distilled from official docs, benchmarks, and developer reports (2026).
|
||||
|
||||
---
|
||||
|
||||
## Quick Picks
|
||||
|
||||
| Situation | Pick |
|
||||
|-----------|------|
|
||||
| Simplest path to a working agent (OpenAI) | OpenAI Agents SDK |
|
||||
| Simplest path to a working agent (model-agnostic) | CrewAI |
|
||||
| Production RAG / document Q&A | LlamaIndex |
|
||||
| Complex stateful workflows with branching | LangGraph |
|
||||
| Multi-agent teams with defined roles | CrewAI |
|
||||
| Code-aware autonomous agents (Anthropic) | Claude Agent SDK |
|
||||
| "I don't know my requirements yet" | LangChain |
|
||||
| Regulated / audit-trail required | LangGraph |
|
||||
| Enterprise Microsoft/.NET shops | AutoGen/AG2 |
|
||||
| Google Cloud / Gemini-committed teams | Google ADK |
|
||||
| Pure NLP pipelines with explicit control | Haystack |
|
||||
|
||||
---
|
||||
|
||||
## Framework Profiles
|
||||
|
||||
### CrewAI
|
||||
- **Type:** Multi-agent orchestration
|
||||
- **Language:** Python only
|
||||
- **Model support:** Model-agnostic
|
||||
- **Learning curve:** Beginner (role/task/crew maps to real teams)
|
||||
- **Best for:** Content pipelines, research automation, business process workflows, rapid prototyping
|
||||
- **Avoid if:** Fine-grained state management, TypeScript, fault-tolerant checkpointing, complex conditional branching
|
||||
- **Strengths:** Fastest multi-agent prototyping, 5.76x faster than LangGraph on QA tasks, built-in memory (short/long/entity/contextual), Flows architecture, standalone (no LangChain dep)
|
||||
- **Weaknesses:** Limited checkpointing, coarse error handling, Python only
|
||||
- **Eval concerns:** Task decomposition accuracy, inter-agent handoff, goal completion rate, loop detection
|
||||
|
||||
### LlamaIndex
|
||||
- **Type:** RAG and data ingestion
|
||||
- **Language:** Python + TypeScript
|
||||
- **Model support:** Model-agnostic
|
||||
- **Learning curve:** Intermediate
|
||||
- **Best for:** Legal research, internal knowledge assistants, enterprise document search, any system where retrieval quality is the #1 priority
|
||||
- **Avoid if:** Primary need is agent orchestration, multi-agent collaboration, or chatbot conversation flow
|
||||
- **Strengths:** Best-in-class document parsing (LlamaParse), 35% retrieval accuracy improvement, 20-30% faster queries, mixed retrieval strategies (vector + graph + reranker)
|
||||
- **Weaknesses:** Data framework first — agent orchestration is secondary
|
||||
- **Eval concerns:** Context faithfulness, hallucination, answer relevance, retrieval precision/recall
|
||||
|
||||
### LangChain
|
||||
- **Type:** General-purpose LLM framework
|
||||
- **Language:** Python + TypeScript
|
||||
- **Model support:** Model-agnostic (widest ecosystem)
|
||||
- **Learning curve:** Intermediate–Advanced
|
||||
- **Best for:** Evolving requirements, many third-party integrations, teams wanting one framework for everything, RAG + agents + chains
|
||||
- **Avoid if:** Simple well-defined use case, RAG-primary (use LlamaIndex), complex stateful workflows (use LangGraph), performance at scale is critical
|
||||
- **Strengths:** Largest community and integration ecosystem, 25% faster development vs scratch, covers RAG/agents/chains/memory
|
||||
- **Weaknesses:** Abstraction overhead, p99 latency degrades under load, complexity creep risk
|
||||
- **Eval concerns:** End-to-end task completion, chain correctness, retrieval quality
|
||||
|
||||
### LangGraph
|
||||
- **Type:** Stateful agent workflows (graph-based)
|
||||
- **Language:** Python + TypeScript (full parity)
|
||||
- **Model support:** Model-agnostic (inherits LangChain integrations)
|
||||
- **Learning curve:** Intermediate–Advanced (graph mental model)
|
||||
- **Best for:** Production-grade stateful workflows, regulated industries, audit trails, human-in-the-loop flows, fault-tolerant multi-step agents
|
||||
- **Avoid if:** Simple chatbot, purely linear workflow, rapid prototyping
|
||||
- **Strengths:** Best checkpointing (every node), time-travel debugging, native Postgres/Redis persistence, streaming support, chosen by 62% of developers for stateful agent work (2026)
|
||||
- **Weaknesses:** More upfront scaffolding, steeper curve, overkill for simple cases
|
||||
- **Eval concerns:** State transition correctness, goal completion rate, tool use accuracy, safety guardrails
|
||||
|
||||
### OpenAI Agents SDK
|
||||
- **Type:** Native OpenAI agent framework
|
||||
- **Language:** Python + TypeScript
|
||||
- **Model support:** Optimized for OpenAI (supports 100+ via Chat Completions compatibility)
|
||||
- **Learning curve:** Beginner (4 primitives: Agents, Handoffs, Guardrails, Tracing)
|
||||
- **Best for:** OpenAI-committed teams, rapid agent prototyping, voice agents (gpt-realtime), teams wanting visual builder (AgentKit)
|
||||
- **Avoid if:** Model flexibility needed, complex multi-agent collaboration, persistent state management required, vendor lock-in concern
|
||||
- **Strengths:** Simplest mental model, built-in tracing and guardrails, Handoffs for agent delegation, Realtime Agents for voice
|
||||
- **Weaknesses:** OpenAI vendor lock-in, no built-in persistent state, younger ecosystem
|
||||
- **Eval concerns:** Instruction following, safety guardrails, escalation accuracy, tone consistency
|
||||
|
||||
### Claude Agent SDK (Anthropic)
|
||||
- **Type:** Code-aware autonomous agent framework
|
||||
- **Language:** Python + TypeScript
|
||||
- **Model support:** Claude models only
|
||||
- **Learning curve:** Intermediate (18 hook events, MCP, tool decorators)
|
||||
- **Best for:** Developer tooling, code generation/review agents, autonomous coding assistants, MCP-heavy architectures, safety-critical applications
|
||||
- **Avoid if:** Model flexibility needed, stable/mature API required, use case unrelated to code/tool-use
|
||||
- **Strengths:** Deepest MCP integration, built-in filesystem/shell access, 18 lifecycle hooks, automatic context compaction, extended thinking, safety-first design
|
||||
- **Weaknesses:** Claude-only vendor lock-in, newer/evolving API, smaller community
|
||||
- **Eval concerns:** Tool use correctness, safety, code quality, instruction following
|
||||
|
||||
### AutoGen / AG2 / Microsoft Agent Framework
|
||||
- **Type:** Multi-agent conversational framework
|
||||
- **Language:** Python (AG2), Python + .NET (Microsoft Agent Framework)
|
||||
- **Model support:** Model-agnostic
|
||||
- **Learning curve:** Intermediate–Advanced
|
||||
- **Best for:** Research applications, conversational problem-solving, code generation + execution loops, Microsoft/.NET shops
|
||||
- **Avoid if:** You want ecosystem stability, deterministic workflows, or "safest long-term bet" (fragmentation risk)
|
||||
- **Strengths:** Most sophisticated conversational agent patterns, code generation + execution loop, async event-driven (v0.4+), cross-language interop (Microsoft Agent Framework)
|
||||
- **Weaknesses:** Ecosystem fragmented (AutoGen maintenance mode, AG2 fork, Microsoft Agent Framework preview) — genuine long-term risk
|
||||
- **Eval concerns:** Conversation goal completion, consensus quality, code execution correctness
|
||||
|
||||
### Google ADK (Agent Development Kit)
|
||||
- **Type:** Multi-agent orchestration framework
|
||||
- **Language:** Python + Java
|
||||
- **Model support:** Optimized for Gemini; supports other models via LiteLLM
|
||||
- **Learning curve:** Intermediate (agent/tool/session model, familiar if you know LangGraph)
|
||||
- **Best for:** Google Cloud / Vertex AI shops, multi-agent workflows needing built-in session management and memory, teams already committed to Gemini, agent pipelines that need Google Search / BigQuery tool integration
|
||||
- **Avoid if:** Model flexibility is required beyond Gemini, no Google Cloud dependency acceptable, TypeScript-only stack
|
||||
- **Strengths:** First-party Google support, built-in session/memory/artifact management, tight Vertex AI and Google Search integration, own eval framework (RAGAS-compatible), multi-agent by design (sequential, parallel, loop patterns), Java SDK for enterprise teams
|
||||
- **Weaknesses:** Gemini vendor lock-in in practice, younger community than LangChain/LlamaIndex, less third-party integration depth
|
||||
- **Eval concerns:** Multi-agent task decomposition, tool use correctness, session state consistency, goal completion rate
|
||||
|
||||
### Haystack
|
||||
- **Type:** NLP pipeline framework
|
||||
- **Language:** Python
|
||||
- **Model support:** Model-agnostic
|
||||
- **Learning curve:** Intermediate
|
||||
- **Best for:** Explicit, auditable NLP pipelines, document processing with fine-grained control, enterprise search, regulated industries needing transparency
|
||||
- **Avoid if:** Rapid prototyping, multi-agent workflows, or you want a large community
|
||||
- **Strengths:** Explicit pipeline control, strong for structured data pipelines, good documentation
|
||||
- **Weaknesses:** Smaller community, less agent-oriented than alternatives
|
||||
- **Eval concerns:** Extraction accuracy, pipeline output validity, retrieval quality
|
||||
|
||||
---
|
||||
|
||||
## Decision Dimensions
|
||||
|
||||
### By System Type
|
||||
|
||||
| System Type | Primary Framework(s) | Key Eval Concerns |
|
||||
|-------------|---------------------|-------------------|
|
||||
| RAG / Knowledge Q&A | LlamaIndex, LangChain | Context faithfulness, hallucination, retrieval precision/recall |
|
||||
| Multi-agent orchestration | CrewAI, LangGraph, Google ADK | Task decomposition, handoff quality, goal completion |
|
||||
| Conversational assistants | OpenAI Agents SDK, Claude Agent SDK | Tone, safety, instruction following, escalation |
|
||||
| Structured data extraction | LangChain, LlamaIndex | Schema compliance, extraction accuracy |
|
||||
| Autonomous task agents | LangGraph, OpenAI Agents SDK | Safety guardrails, tool correctness, cost adherence |
|
||||
| Content generation | Claude Agent SDK, OpenAI Agents SDK | Brand voice, factual accuracy, tone |
|
||||
| Code automation | Claude Agent SDK | Code correctness, safety, test pass rate |
|
||||
|
||||
### By Team Size and Stage
|
||||
|
||||
| Context | Recommendation |
|
||||
|---------|----------------|
|
||||
| Solo dev, prototyping | OpenAI Agents SDK or CrewAI (fastest to running) |
|
||||
| Solo dev, RAG | LlamaIndex (batteries included) |
|
||||
| Team, production, stateful | LangGraph (best fault tolerance) |
|
||||
| Team, evolving requirements | LangChain (broadest escape hatches) |
|
||||
| Team, multi-agent | CrewAI (simplest role abstraction) |
|
||||
| Enterprise, .NET | AutoGen AG2 / Microsoft Agent Framework |
|
||||
|
||||
### By Model Commitment
|
||||
|
||||
| Preference | Framework |
|
||||
|-----------|-----------|
|
||||
| OpenAI-only | OpenAI Agents SDK |
|
||||
| Anthropic/Claude-only | Claude Agent SDK |
|
||||
| Google/Gemini-committed | Google ADK |
|
||||
| Model-agnostic (full flexibility) | LangChain, LlamaIndex, CrewAI, LangGraph, Haystack |
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
1. **Using LangChain for simple chatbots** — Direct SDK call is less code, faster, and easier to debug
|
||||
2. **Using CrewAI for complex stateful workflows** — Checkpointing gaps will bite you in production
|
||||
3. **Using OpenAI Agents SDK with non-OpenAI models** — Loses the integration benefits you chose it for
|
||||
4. **Using LlamaIndex as a multi-agent framework** — It can do agents, but that's not its strength
|
||||
5. **Defaulting to LangChain without evaluating alternatives** — "Everyone uses it" ≠ right for your use case
|
||||
6. **Starting a new project on AutoGen (not AG2)** — AutoGen is in maintenance mode; use AG2 or wait for Microsoft Agent Framework GA
|
||||
7. **Choosing LangGraph for simple linear flows** — The graph overhead is not worth it; use LangChain chains instead
|
||||
8. **Ignoring vendor lock-in** — Provider-native SDKs (OpenAI, Claude) trade flexibility for integration depth; decide consciously
|
||||
|
||||
---
|
||||
|
||||
## Combination Plays (Multi-Framework Stacks)
|
||||
|
||||
| Production Pattern | Stack |
|
||||
|-------------------|-------|
|
||||
| RAG with observability | LlamaIndex + LangSmith or Langfuse |
|
||||
| Stateful agent with RAG | LangGraph + LlamaIndex |
|
||||
| Multi-agent with tracing | CrewAI + Langfuse |
|
||||
| OpenAI agents with evals | OpenAI Agents SDK + Promptfoo or Braintrust |
|
||||
| Claude agents with MCP | Claude Agent SDK + LangSmith or Arize Phoenix |
|
||||
131
gsd-core/references/artifact-types.md
Normal file
131
gsd-core/references/artifact-types.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 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/gsd-core/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
|
||||
|
||||
### Spike README.md / MANIFEST.md (per-spike, via /gsd:spike)
|
||||
- **Shape**: YAML frontmatter (spike, name, validates, verdict, related, tags) + run instructions + results
|
||||
- **Lifecycle**: Created by `/gsd:spike` → Verified → Wrapped up by `/gsd-spike-wrap-up`
|
||||
- **Location**: `.planning/spikes/NNN-name/README.md`, `.planning/spikes/MANIFEST.md`
|
||||
- **Consumed by**: `/gsd-spike-wrap-up` for curation; `pause-work` for spike context handoff
|
||||
|
||||
### Sketch README.md / MANIFEST.md / index.html (per-sketch)
|
||||
- **Shape**: YAML frontmatter (sketch, name, question, winner, tags) + variants as tabbed HTML
|
||||
- **Lifecycle**: Created by `/gsd:sketch` → Evaluated → Wrapped up by `/gsd-sketch-wrap-up`
|
||||
- **Location**: `.planning/sketches/NNN-name/README.md`, `.planning/sketches/NNN-name/index.html`, `.planning/sketches/MANIFEST.md`
|
||||
- **Consumed by**: `/gsd-sketch-wrap-up` for curation; `pause-work` for sketch context handoff
|
||||
|
||||
### WRAP-UP-SUMMARY.md (per wrap-up session)
|
||||
- **Shape**: Curation results, included/excluded items, feature/design area groupings
|
||||
- **Lifecycle**: Created by `/gsd-spike-wrap-up` or `/gsd-sketch-wrap-up`
|
||||
- **Location**: `.planning/spikes/WRAP-UP-SUMMARY.md` or `.planning/sketches/WRAP-UP-SUMMARY.md`
|
||||
- **Consumed by**: Project history; not read by automated workflows
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
```
|
||||
277
gsd-core/references/autonomous-smart-discuss.md
Normal file
277
gsd-core/references/autonomous-smart-discuss.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# Smart Discuss — Autonomous Mode
|
||||
|
||||
Smart discuss is the autonomous-optimized variant of `gsd-discuss-phase`. It proposes grey area answers in batch tables — the user accepts or overrides per area — then writes an identical CONTEXT.md to what discuss-phase produces.
|
||||
|
||||
**Inputs:** `PHASE_NUM` from execute_phase. Run init to get phase paths:
|
||||
|
||||
```bash
|
||||
PHASE_STATE=$(gsd-tools query init.phase-op ${PHASE_NUM})
|
||||
```
|
||||
|
||||
Parse from JSON: `phase_dir`, `phase_slug`, `padded_phase`, `phase_name`.
|
||||
|
||||
---
|
||||
|
||||
## Sub-step 1: Load prior context
|
||||
|
||||
Read project-level and prior phase context to avoid re-asking decided questions.
|
||||
|
||||
**Read project files:**
|
||||
|
||||
```bash
|
||||
cat .planning/PROJECT.md 2>/dev/null || true
|
||||
cat .planning/REQUIREMENTS.md 2>/dev/null || true
|
||||
cat .planning/STATE.md 2>/dev/null || true
|
||||
```
|
||||
|
||||
Extract from these:
|
||||
- **PROJECT.md** — Vision, principles, non-negotiables, user preferences
|
||||
- **REQUIREMENTS.md** — Acceptance criteria, constraints, must-haves vs nice-to-haves
|
||||
- **STATE.md** — Current progress, decisions logged so far
|
||||
|
||||
**Read all prior CONTEXT.md files:**
|
||||
|
||||
```bash
|
||||
(find .planning/phases -name "*-CONTEXT.md" 2>/dev/null || true) | sort
|
||||
```
|
||||
|
||||
For each CONTEXT.md where phase number < current phase:
|
||||
- Read the `<decisions>` section — these are locked preferences
|
||||
- Read `<specifics>` — particular references or "I want it like X" moments
|
||||
- Note patterns (e.g., "user consistently prefers minimal UI", "user rejected verbose output")
|
||||
|
||||
**Build internal prior_decisions context** (do not write to file):
|
||||
|
||||
```
|
||||
<prior_decisions>
|
||||
## Project-Level
|
||||
- [Key principle or constraint from PROJECT.md]
|
||||
- [Requirement affecting this phase from REQUIREMENTS.md]
|
||||
|
||||
## From Prior Phases
|
||||
### Phase N: [Name]
|
||||
- [Decision relevant to current phase]
|
||||
- [Preference that establishes a pattern]
|
||||
</prior_decisions>
|
||||
```
|
||||
|
||||
If no prior context exists, continue without — expected for early phases.
|
||||
|
||||
---
|
||||
|
||||
## Sub-step 2: Scout Codebase
|
||||
|
||||
Lightweight codebase scan to inform grey area identification and proposals. Keep under ~5% context.
|
||||
|
||||
**Check for existing codebase maps:**
|
||||
|
||||
```bash
|
||||
ls .planning/codebase/*.md 2>/dev/null || true
|
||||
```
|
||||
|
||||
**If codebase maps exist:** Read the most relevant ones (CONVENTIONS.md, STRUCTURE.md, STACK.md based on phase type). Extract reusable components, established patterns, integration points. Skip to building context below.
|
||||
|
||||
**If no codebase maps, do targeted grep:**
|
||||
|
||||
Extract key terms from the phase goal. Search for related files:
|
||||
|
||||
```bash
|
||||
grep -rl "{term1}\|{term2}" src/ app/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | head -10 || true
|
||||
ls src/components/ src/hooks/ src/lib/ src/utils/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
Read the 3-5 most relevant files to understand existing patterns.
|
||||
|
||||
**Build internal codebase_context** (do not write to file):
|
||||
- **Reusable assets** — existing components, hooks, utilities usable in this phase
|
||||
- **Established patterns** — how the codebase does state management, styling, data fetching
|
||||
- **Integration points** — where new code connects (routes, nav, providers)
|
||||
|
||||
---
|
||||
|
||||
## Sub-step 3: Analyze Phase and Generate Proposals
|
||||
|
||||
**Get phase details:**
|
||||
|
||||
```bash
|
||||
DETAIL=$(gsd-tools query roadmap.get-phase ${PHASE_NUM})
|
||||
```
|
||||
|
||||
Extract `goal`, `requirements`, `success_criteria` from the JSON response.
|
||||
|
||||
**Infrastructure detection — check FIRST before generating grey areas:**
|
||||
|
||||
A phase is pure infrastructure when ALL of these are true:
|
||||
1. Goal keywords match: "scaffolding", "plumbing", "setup", "configuration", "migration", "refactor", "rename", "restructure", "upgrade", "infrastructure"
|
||||
2. AND success criteria are all technical: "file exists", "test passes", "config valid", "command runs"
|
||||
3. AND no user-facing behavior is described (no "users can", "displays", "shows", "presents")
|
||||
|
||||
**If infrastructure-only:** Skip Sub-step 4. Jump directly to Sub-step 5 with minimal CONTEXT.md. Display:
|
||||
|
||||
```
|
||||
Phase ${PHASE_NUM}: Infrastructure phase — skipping discuss, writing minimal context.
|
||||
```
|
||||
|
||||
Use these defaults for the CONTEXT.md:
|
||||
- `<domain>`: Phase boundary from ROADMAP goal
|
||||
- `<decisions>`: Single "### Claude's Discretion" subsection — "All implementation choices are at Claude's discretion — pure infrastructure phase"
|
||||
- `<code_context>`: Whatever the codebase scout found
|
||||
- `<specifics>`: "No specific requirements — infrastructure phase"
|
||||
- `<deferred>`: "None"
|
||||
|
||||
**If NOT infrastructure — generate grey area proposals:**
|
||||
|
||||
Determine domain type from the phase goal:
|
||||
- Something users **SEE** → visual: layout, interactions, states, density
|
||||
- Something users **CALL** → interface: contracts, responses, errors, auth
|
||||
- Something users **RUN** → execution: invocation, output, behavior modes, flags
|
||||
- Something users **READ** → content: structure, tone, depth, flow
|
||||
- Something being **ORGANIZED** → organization: criteria, grouping, exceptions, naming
|
||||
|
||||
Check prior_decisions — skip grey areas already decided in prior phases.
|
||||
|
||||
Generate **3-4 grey areas** with **~4 questions each**. For each question:
|
||||
- **Pre-select a recommended answer** based on: prior decisions (consistency), codebase patterns (reuse), domain conventions (standard approaches), ROADMAP success criteria
|
||||
- Generate **1-2 alternatives** per question
|
||||
- **Annotate** with prior decision context ("You decided X in Phase N") and code context ("Component Y exists with Z variants") where relevant
|
||||
|
||||
---
|
||||
|
||||
## Sub-step 4: Present Proposals Per Area
|
||||
|
||||
Present grey areas **one at a time**. For each area (M of N):
|
||||
|
||||
Display a table:
|
||||
|
||||
```
|
||||
### Grey Area {M}/{N}: {Area Name}
|
||||
|
||||
| # | Question | ✅ Recommended | Alternative(s) |
|
||||
|---|----------|---------------|-----------------|
|
||||
| 1 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
|
||||
| 2 | {question} | {answer} — {rationale} | {alt1} |
|
||||
| 3 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
|
||||
| 4 | {question} | {answer} — {rationale} | {alt1} |
|
||||
```
|
||||
|
||||
Then prompt the user via **AskUserQuestion**:
|
||||
- **header:** "Area {M}/{N}"
|
||||
- **question:** "Accept these answers for {Area Name}?"
|
||||
- **options:** Build dynamically — always "Accept all" first, then "Change Q1" through "Change QN" for each question (up to 4), then "Discuss deeper" last. Cap at 6 explicit options max (AskUserQuestion adds "Other" automatically).
|
||||
|
||||
**On "Accept all":** Record all recommended answers for this area. Move to next area.
|
||||
|
||||
**On "Change QN":** Use AskUserQuestion with the alternatives for that specific question:
|
||||
- **header:** "{Area Name}"
|
||||
- **question:** "Q{N}: {question text}"
|
||||
- **options:** List the 1-2 alternatives plus "You decide" (maps to Claude's Discretion)
|
||||
|
||||
Record the user's choice. Re-display the updated table with the change reflected. Re-present the full acceptance prompt so the user can make additional changes or accept.
|
||||
|
||||
**On "Discuss deeper":** Switch to interactive mode for this area only — ask questions one at a time using AskUserQuestion with 2-3 concrete options per question plus "You decide". After 4 questions, prompt:
|
||||
- **header:** "{Area Name}"
|
||||
- **question:** "More questions about {area name}, or move to next?"
|
||||
- **options:** "More questions" / "Next area"
|
||||
|
||||
If "More questions", ask 4 more. If "Next area", display final summary table of captured answers for this area and move on.
|
||||
|
||||
**On "Other" (free text):** Interpret as either a specific change request or general feedback. Incorporate into the area's decisions, re-display updated table, re-present acceptance prompt.
|
||||
|
||||
**Scope creep handling:** If user mentions something outside the phase domain:
|
||||
|
||||
```
|
||||
"{Feature} sounds like a new capability — that belongs in its own phase.
|
||||
I'll note it as a deferred idea.
|
||||
|
||||
Back to {current area}: {return to current question}"
|
||||
```
|
||||
|
||||
Track deferred ideas internally for inclusion in CONTEXT.md.
|
||||
|
||||
---
|
||||
|
||||
## Sub-step 5: Write CONTEXT.md
|
||||
|
||||
After all areas are resolved (or infrastructure skip), write the CONTEXT.md file.
|
||||
|
||||
**File path:** `${phase_dir}/${padded_phase}-CONTEXT.md`
|
||||
|
||||
Use **exactly** this structure (identical to discuss-phase output):
|
||||
|
||||
```markdown
|
||||
# Phase {PHASE_NUM}: {Phase Name} - Context
|
||||
|
||||
**Gathered:** {date}
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
{Domain boundary statement from analysis — what this phase delivers}
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### {Area 1 Name}
|
||||
- {Accepted/chosen answer for Q1}
|
||||
- {Accepted/chosen answer for Q2}
|
||||
- {Accepted/chosen answer for Q3}
|
||||
- {Accepted/chosen answer for Q4}
|
||||
|
||||
### {Area 2 Name}
|
||||
- {Accepted/chosen answer for Q1}
|
||||
- {Accepted/chosen answer for Q2}
|
||||
...
|
||||
|
||||
### Claude's Discretion
|
||||
{Any "You decide" answers collected — note Claude has flexibility here}
|
||||
|
||||
</decisions>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- {From codebase scout — components, hooks, utilities}
|
||||
|
||||
### Established Patterns
|
||||
- {From codebase scout — state management, styling, data fetching}
|
||||
|
||||
### Integration Points
|
||||
- {From codebase scout — where new code connects}
|
||||
|
||||
</code_context>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
{Any specific references or "I want it like X" from discussion}
|
||||
{If none: "No specific requirements — open to standard approaches"}
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
{Ideas captured but out of scope for this phase}
|
||||
{If none: "None — discussion stayed within phase scope"}
|
||||
|
||||
</deferred>
|
||||
```
|
||||
|
||||
Write the file.
|
||||
|
||||
**Commit:**
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "docs(${PADDED_PHASE}): smart discuss context" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
|
||||
```
|
||||
|
||||
Display confirmation:
|
||||
|
||||
```
|
||||
Created: {path}
|
||||
Decisions captured: {count} across {area_count} areas
|
||||
```
|
||||
814
gsd-core/references/checkpoints.md
Normal file
814
gsd-core/references/checkpoints.md
Normal file
@@ -0,0 +1,814 @@
|
||||
<overview>
|
||||
Plans execute autonomously. Checkpoints formalize interaction points where human verification or decisions are needed.
|
||||
|
||||
**Core principle:** Claude automates everything with CLI/API. Checkpoints are for verification and decisions, not manual work.
|
||||
|
||||
**Golden rules:**
|
||||
1. **If Claude can run it, Claude runs it** - Never ask user to execute CLI commands, start servers, or run builds
|
||||
2. **Claude sets up the verification environment** - Start dev servers, seed databases, configure env vars
|
||||
3. **User only does what requires human judgment** - Visual checks, UX evaluation, "does this feel right?"
|
||||
4. **Secrets come from user, automation comes from Claude** - Ask for API keys, then Claude uses them via CLI
|
||||
5. **Auto-mode bypasses verification/decision checkpoints** — When `workflow._auto_chain_active` or `workflow.auto_advance` is true in config: human-verify auto-approves, decision auto-selects first option, human-action still stops (auth gates cannot be automated)
|
||||
</overview>
|
||||
|
||||
<checkpoint_types>
|
||||
|
||||
<type name="human-verify">
|
||||
## checkpoint:human-verify (Most Common - 90%)
|
||||
|
||||
**When:** Claude completed automated work, human confirms it works correctly.
|
||||
|
||||
> **Default mode (#3309): `workflow.human_verify_mode = end-of-phase`.** New projects do NOT halt mid-flight at `checkpoint:human-verify`. The planner suppresses those task emissions and embeds the verification details into the relevant `auto` task's `<verify><human-check>` block; the verifier harvests every `<verify><human-check>` at end-of-phase (Step 8) and consolidates them into the existing `human_needed` → `{phase_num}-UAT.md` flow in `workflows/execute-phase.md`. The user reviews everything in one batch.
|
||||
>
|
||||
> **Why this is the default:** every mid-flight halt costs a full executor cold-start (CLAUDE.md, MEMORY.md, STATE.md, plan re-read on respawn) because subagent context is discarded across the pause. A plan with N human-verify checkpoints pays the cold-start cost N+1 times — measured at "tens of thousands of tokens" per round-trip on real projects.
|
||||
>
|
||||
> Set `workflow.human_verify_mode = mid-flight` in `.planning/config.json` to opt back into the pre-#3309 behavior of halting at every checkpoint. `checkpoint:decision` and `checkpoint:human-action` are unaffected by either value — those gate the work itself, not post-hoc verification.
|
||||
|
||||
**Use for:**
|
||||
- Visual UI checks (layout, styling, responsiveness)
|
||||
- Interactive flows (click through wizard, test user flows)
|
||||
- Functional verification (feature works as expected)
|
||||
- Audio/video playback quality
|
||||
- Animation smoothness
|
||||
- Accessibility testing
|
||||
|
||||
**Structure:**
|
||||
```xml
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>[What Claude automated and deployed/built]</what-built>
|
||||
<how-to-verify>
|
||||
[Exact steps to test - URLs, commands, expected behavior]
|
||||
</how-to-verify>
|
||||
<resume-signal>[How to continue - "approved", "yes", or describe issues]</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: UI Component (shows key pattern: Claude starts server BEFORE checkpoint)**
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Build responsive dashboard layout</name>
|
||||
<files>src/components/Dashboard.tsx, src/app/dashboard/page.tsx</files>
|
||||
<action>Create dashboard with sidebar, header, and content area. Use Tailwind responsive classes for mobile.</action>
|
||||
<verify>npm run build succeeds, no TypeScript errors</verify>
|
||||
<done>Dashboard component builds without errors</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Start dev server for verification</name>
|
||||
<action>Run `npm run dev` in background, wait for "ready" message, capture port</action>
|
||||
<verify>fetch http://localhost:3000 returns 200</verify>
|
||||
<done>Dev server running at http://localhost:3000</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Responsive dashboard layout - dev server running at http://localhost:3000</what-built>
|
||||
<how-to-verify>
|
||||
Visit http://localhost:3000/dashboard and verify:
|
||||
1. Desktop (>1024px): Sidebar left, content right, header top
|
||||
2. Tablet (768px): Sidebar collapses to hamburger menu
|
||||
3. Mobile (375px): Single column layout, bottom nav appears
|
||||
4. No layout shift or horizontal scroll at any size
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" or describe layout issues</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: Xcode Build**
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Build macOS app with Xcode</name>
|
||||
<files>App.xcodeproj, Sources/</files>
|
||||
<action>Run `xcodebuild -project App.xcodeproj -scheme App build`. Check for compilation errors in output.</action>
|
||||
<verify>Build output contains "BUILD SUCCEEDED", no errors</verify>
|
||||
<done>App builds successfully</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Built macOS app at DerivedData/Build/Products/Debug/App.app</what-built>
|
||||
<how-to-verify>
|
||||
Open App.app and test:
|
||||
- App launches without crashes
|
||||
- Menu bar icon appears
|
||||
- Preferences window opens correctly
|
||||
- No visual glitches or layout issues
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" or describe issues</resume-signal>
|
||||
</task>
|
||||
```
|
||||
</type>
|
||||
|
||||
<type name="decision">
|
||||
## checkpoint:decision (9%)
|
||||
|
||||
**When:** Human must make choice that affects implementation direction.
|
||||
|
||||
**Use for:**
|
||||
- Technology selection (which auth provider, which database)
|
||||
- Architecture decisions (monorepo vs separate repos)
|
||||
- Design choices (color scheme, layout approach)
|
||||
- Feature prioritization (which variant to build)
|
||||
- Data model decisions (schema structure)
|
||||
|
||||
**Structure:**
|
||||
```xml
|
||||
<task type="checkpoint:decision" gate="blocking">
|
||||
<decision>[What's being decided]</decision>
|
||||
<context>[Why this decision matters]</context>
|
||||
<options>
|
||||
<option id="option-a">
|
||||
<name>[Option name]</name>
|
||||
<pros>[Benefits]</pros>
|
||||
<cons>[Tradeoffs]</cons>
|
||||
</option>
|
||||
<option id="option-b">
|
||||
<name>[Option name]</name>
|
||||
<pros>[Benefits]</pros>
|
||||
<cons>[Tradeoffs]</cons>
|
||||
</option>
|
||||
</options>
|
||||
<resume-signal>[How to indicate choice]</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: Auth Provider Selection**
|
||||
```xml
|
||||
<task type="checkpoint:decision" gate="blocking">
|
||||
<decision>Select authentication provider</decision>
|
||||
<context>
|
||||
Need user authentication for the app. Three solid options with different tradeoffs.
|
||||
</context>
|
||||
<options>
|
||||
<option id="supabase">
|
||||
<name>Supabase Auth</name>
|
||||
<pros>Built-in with Supabase DB we're using, generous free tier, row-level security integration</pros>
|
||||
<cons>Less customizable UI, tied to Supabase ecosystem</cons>
|
||||
</option>
|
||||
<option id="clerk">
|
||||
<name>Clerk</name>
|
||||
<pros>Beautiful pre-built UI, best developer experience, excellent docs</pros>
|
||||
<cons>Paid after 10k MAU, vendor lock-in</cons>
|
||||
</option>
|
||||
<option id="nextauth">
|
||||
<name>NextAuth.js</name>
|
||||
<pros>Free, self-hosted, maximum control, widely adopted</pros>
|
||||
<cons>More setup work, you manage security updates, UI is DIY</cons>
|
||||
</option>
|
||||
</options>
|
||||
<resume-signal>Select: supabase, clerk, or nextauth</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: Database Selection**
|
||||
```xml
|
||||
<task type="checkpoint:decision" gate="blocking">
|
||||
<decision>Select database for user data</decision>
|
||||
<context>
|
||||
App needs persistent storage for users, sessions, and user-generated content.
|
||||
Expected scale: 10k users, 1M records first year.
|
||||
</context>
|
||||
<options>
|
||||
<option id="supabase">
|
||||
<name>Supabase (Postgres)</name>
|
||||
<pros>Full SQL, generous free tier, built-in auth, real-time subscriptions</pros>
|
||||
<cons>Vendor lock-in for real-time features, less flexible than raw Postgres</cons>
|
||||
</option>
|
||||
<option id="planetscale">
|
||||
<name>PlanetScale (MySQL)</name>
|
||||
<pros>Serverless scaling, branching workflow, excellent DX</pros>
|
||||
<cons>MySQL not Postgres, no foreign keys in free tier</cons>
|
||||
</option>
|
||||
<option id="convex">
|
||||
<name>Convex</name>
|
||||
<pros>Real-time by default, TypeScript-native, automatic caching</pros>
|
||||
<cons>Newer platform, different mental model, less SQL flexibility</cons>
|
||||
</option>
|
||||
</options>
|
||||
<resume-signal>Select: supabase, planetscale, or convex</resume-signal>
|
||||
</task>
|
||||
```
|
||||
</type>
|
||||
|
||||
<type name="human-action">
|
||||
## checkpoint:human-action (1% - Rare)
|
||||
|
||||
**When:** Action has NO CLI/API and requires human-only interaction, OR Claude hit an authentication gate during automation.
|
||||
|
||||
**Use ONLY for:**
|
||||
- **Authentication gates** - Claude tried CLI/API but needs credentials (this is NOT a failure)
|
||||
- Email verification links (clicking email)
|
||||
- SMS 2FA codes (phone verification)
|
||||
- Manual account approvals (platform requires human review)
|
||||
- Credit card 3D Secure flows (web-based payment authorization)
|
||||
- OAuth app approvals (web-based approval)
|
||||
|
||||
**Do NOT use for pre-planned manual work:**
|
||||
- Deploying (use CLI - auth gate if needed)
|
||||
- Creating webhooks/databases (use API/CLI - auth gate if needed)
|
||||
- Running builds/tests (use Bash tool)
|
||||
- Creating files (use Write tool)
|
||||
|
||||
**Structure:**
|
||||
```xml
|
||||
<task type="checkpoint:human-action" gate="blocking">
|
||||
<action>[What human must do - Claude already did everything automatable]</action>
|
||||
<instructions>
|
||||
[What Claude already automated]
|
||||
[The ONE thing requiring human action]
|
||||
</instructions>
|
||||
<verification>[What Claude can check afterward]</verification>
|
||||
<resume-signal>[How to continue]</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: Email Verification**
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Create SendGrid account via API</name>
|
||||
<action>Use SendGrid API to create subuser account with provided email. Request verification email.</action>
|
||||
<verify>API returns 201, account created</verify>
|
||||
<done>Account created, verification email sent</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-action" gate="blocking">
|
||||
<action>Complete email verification for SendGrid account</action>
|
||||
<instructions>
|
||||
I created the account and requested verification email.
|
||||
Check your inbox for SendGrid verification link and click it.
|
||||
</instructions>
|
||||
<verification>SendGrid API key works: curl test succeeds</verification>
|
||||
<resume-signal>Type "done" when email verified</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Example: Authentication Gate (Dynamic Checkpoint)**
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Deploy to Vercel</name>
|
||||
<files>.vercel/, vercel.json</files>
|
||||
<action>Run `vercel --yes` to deploy</action>
|
||||
<verify>vercel ls shows deployment, fetch returns 200</verify>
|
||||
</task>
|
||||
|
||||
<!-- If vercel returns "Error: Not authenticated", Claude creates checkpoint on the fly -->
|
||||
|
||||
<task type="checkpoint:human-action" gate="blocking">
|
||||
<action>Authenticate Vercel CLI so I can continue deployment</action>
|
||||
<instructions>
|
||||
I tried to deploy but got authentication error.
|
||||
Run: vercel login
|
||||
This will open your browser - complete the authentication flow.
|
||||
</instructions>
|
||||
<verification>vercel whoami returns your account email</verification>
|
||||
<resume-signal>Type "done" when authenticated</resume-signal>
|
||||
</task>
|
||||
|
||||
<!-- After authentication, Claude retries the deployment -->
|
||||
|
||||
<task type="auto">
|
||||
<name>Retry Vercel deployment</name>
|
||||
<action>Run `vercel --yes` (now authenticated)</action>
|
||||
<verify>vercel ls shows deployment, fetch returns 200</verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Key distinction:** Auth gates are created dynamically when Claude encounters auth errors. NOT pre-planned — Claude automates first, asks for credentials only when blocked.
|
||||
</type>
|
||||
</checkpoint_types>
|
||||
|
||||
<execution_protocol>
|
||||
|
||||
When Claude encounters `type="checkpoint:*"`:
|
||||
|
||||
1. **Stop immediately** - do not proceed to next task
|
||||
2. **Display checkpoint clearly** using the format below
|
||||
3. **Wait for user response** - do not hallucinate completion
|
||||
4. **Verify if possible** - check files, run tests, whatever is specified
|
||||
5. **Resume execution** - continue to next task only after confirmation
|
||||
|
||||
**For checkpoint:human-verify:**
|
||||
```
|
||||
╔═══════════════════════════════════════════════════════╗
|
||||
║ CHECKPOINT: Verification Required ║
|
||||
╚═══════════════════════════════════════════════════════╝
|
||||
|
||||
Progress: 5/8 tasks complete
|
||||
Task: Responsive dashboard layout
|
||||
|
||||
Built: Responsive dashboard at /dashboard
|
||||
|
||||
How to verify:
|
||||
1. Visit: http://localhost:3000/dashboard
|
||||
2. Desktop (>1024px): Sidebar visible, content fills remaining space
|
||||
3. Tablet (768px): Sidebar collapses to icons
|
||||
4. Mobile (375px): Sidebar hidden, hamburger menu appears
|
||||
|
||||
────────────────────────────────────────────────────────
|
||||
→ YOUR ACTION: Type "approved" or describe issues
|
||||
────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
**For checkpoint:decision:**
|
||||
```
|
||||
╔═══════════════════════════════════════════════════════╗
|
||||
║ CHECKPOINT: Decision Required ║
|
||||
╚═══════════════════════════════════════════════════════╝
|
||||
|
||||
Progress: 2/6 tasks complete
|
||||
Task: Select authentication provider
|
||||
|
||||
Decision: Which auth provider should we use?
|
||||
|
||||
Context: Need user authentication. Three options with different tradeoffs.
|
||||
|
||||
Options:
|
||||
1. supabase - Built-in with our DB, free tier
|
||||
Pros: Row-level security integration, generous free tier
|
||||
Cons: Less customizable UI, ecosystem lock-in
|
||||
|
||||
2. clerk - Best DX, paid after 10k users
|
||||
Pros: Beautiful pre-built UI, excellent documentation
|
||||
Cons: Vendor lock-in, pricing at scale
|
||||
|
||||
3. nextauth - Self-hosted, maximum control
|
||||
Pros: Free, no vendor lock-in, widely adopted
|
||||
Cons: More setup work, DIY security updates
|
||||
|
||||
────────────────────────────────────────────────────────
|
||||
→ YOUR ACTION: Select supabase, clerk, or nextauth
|
||||
────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
**For checkpoint:human-action:**
|
||||
```
|
||||
╔═══════════════════════════════════════════════════════╗
|
||||
║ CHECKPOINT: Action Required ║
|
||||
╚═══════════════════════════════════════════════════════╝
|
||||
|
||||
Progress: 3/8 tasks complete
|
||||
Task: Deploy to Vercel
|
||||
|
||||
Attempted: vercel --yes
|
||||
Error: Not authenticated. Please run 'vercel login'
|
||||
|
||||
What you need to do:
|
||||
1. Run: vercel login
|
||||
2. Complete browser authentication when it opens
|
||||
3. Return here when done
|
||||
|
||||
I'll verify: vercel whoami returns your account
|
||||
|
||||
────────────────────────────────────────────────────────
|
||||
→ YOUR ACTION: Type "done" when authenticated
|
||||
────────────────────────────────────────────────────────
|
||||
```
|
||||
</execution_protocol>
|
||||
|
||||
<authentication_gates>
|
||||
|
||||
**Auth gate = Claude tried CLI/API, got auth error.** Not a failure — a gate requiring human input to unblock.
|
||||
|
||||
**Pattern:** Claude tries automation → auth error → creates checkpoint:human-action → user authenticates → Claude retries → continues
|
||||
|
||||
**Gate protocol:**
|
||||
1. Recognize it's not a failure - missing auth is expected
|
||||
2. Stop current task - don't retry repeatedly
|
||||
3. Create checkpoint:human-action dynamically
|
||||
4. Provide exact authentication steps
|
||||
5. Verify authentication works
|
||||
6. Retry the original task
|
||||
7. Continue normally
|
||||
|
||||
**Key distinction:**
|
||||
- Pre-planned checkpoint: "I need you to do X" (wrong - Claude should automate)
|
||||
- Auth gate: "I tried to automate X but need credentials" (correct - unblocks automation)
|
||||
|
||||
</authentication_gates>
|
||||
|
||||
<automation_reference>
|
||||
|
||||
**The rule:** If it has CLI/API, Claude does it. Never ask human to perform automatable work.
|
||||
|
||||
## Service CLI Reference
|
||||
|
||||
| Service | CLI/API | Key Commands | Auth Gate |
|
||||
|---------|---------|--------------|-----------|
|
||||
| Vercel | `vercel` | `--yes`, `env add`, `--prod`, `ls` | `vercel login` |
|
||||
| Railway | `railway` | `init`, `up`, `variables set` | `railway login` |
|
||||
| Fly | `fly` | `launch`, `deploy`, `secrets set` | `fly auth login` |
|
||||
| Stripe | `stripe` + API | `listen`, `trigger`, API calls | API key in .env |
|
||||
| Supabase | `supabase` | `init`, `link`, `db push`, `gen types` | `supabase login` |
|
||||
| Upstash | `upstash` | `redis create`, `redis get` | `upstash auth login` |
|
||||
| PlanetScale | `pscale` | `database create`, `branch create` | `pscale auth login` |
|
||||
| GitHub | `gh` | `repo create`, `pr create`, `secret set` | `gh auth login` |
|
||||
| Node | `npm`/`pnpm` | `install`, `run build`, `test`, `run dev` | N/A |
|
||||
| Xcode | `xcodebuild` | `-project`, `-scheme`, `build`, `test` | N/A |
|
||||
| Convex | `npx convex` | `dev`, `deploy`, `env set`, `env get` | `npx convex login` |
|
||||
|
||||
## Environment Variable Automation
|
||||
|
||||
**Env files:** Use Write/Edit tools. Never ask human to create .env manually.
|
||||
|
||||
**Dashboard env vars via CLI:**
|
||||
|
||||
| Platform | CLI Command | Example |
|
||||
|----------|-------------|---------|
|
||||
| Convex | `npx convex env set` | `npx convex env set OPENAI_API_KEY sk-...` |
|
||||
| Vercel | `vercel env add` | `vercel env add STRIPE_KEY production` |
|
||||
| Railway | `railway variables set` | `railway variables set API_KEY=value` |
|
||||
| Fly | `fly secrets set` | `fly secrets set DATABASE_URL=...` |
|
||||
| Supabase | `supabase secrets set` | `supabase secrets set MY_SECRET=value` |
|
||||
|
||||
**Secret collection pattern:**
|
||||
```xml
|
||||
<!-- WRONG: Asking user to add env vars in dashboard -->
|
||||
<task type="checkpoint:human-action">
|
||||
<action>Add OPENAI_API_KEY to Convex dashboard</action>
|
||||
<instructions>Go to dashboard.convex.dev → Settings → Environment Variables → Add</instructions>
|
||||
</task>
|
||||
|
||||
<!-- RIGHT: Claude asks for value, then adds via CLI -->
|
||||
<task type="checkpoint:human-action">
|
||||
<action>Provide your OpenAI API key</action>
|
||||
<instructions>
|
||||
I need your OpenAI API key for Convex backend.
|
||||
Get it from: https://platform.openai.com/api-keys
|
||||
Paste the key (starts with sk-)
|
||||
</instructions>
|
||||
<verification>I'll add it via `npx convex env set` and verify</verification>
|
||||
<resume-signal>Paste your API key</resume-signal>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Configure OpenAI key in Convex</name>
|
||||
<action>Run `npx convex env set OPENAI_API_KEY {user-provided-key}`</action>
|
||||
<verify>`npx convex env get OPENAI_API_KEY` returns the key (masked)</verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
## Dev Server Automation
|
||||
|
||||
| Framework | Start Command | Ready Signal | Default URL |
|
||||
|-----------|---------------|--------------|-------------|
|
||||
| Next.js | `npm run dev` | "Ready in" or "started server" | http://localhost:3000 |
|
||||
| Vite | `npm run dev` | "ready in" | http://localhost:5173 |
|
||||
| Convex | `npx convex dev` | "Convex functions ready" | N/A (backend only) |
|
||||
| Express | `npm start` | "listening on port" | http://localhost:3000 |
|
||||
| Django | `python manage.py runserver` | "Starting development server" | http://localhost:8000 |
|
||||
|
||||
**Server lifecycle:**
|
||||
```bash
|
||||
# Run in background, capture PID
|
||||
npm run dev &
|
||||
DEV_SERVER_PID=$!
|
||||
|
||||
# Wait for ready (max 30s) — uses fetch() for cross-platform compatibility
|
||||
timeout 30 bash -c 'until node -e "fetch(\"http://localhost:3000\").then(r=>{process.exit(r.ok?0:1)}).catch(()=>process.exit(1))" 2>/dev/null; do sleep 1; done'
|
||||
```
|
||||
|
||||
**Port conflicts:** Kill stale process (`lsof -ti:3000 | xargs kill`) or use alternate port (`--port 3001`).
|
||||
|
||||
**Server stays running** through checkpoints. Only kill when plan complete, switching to production, or port needed for different service.
|
||||
|
||||
## CLI Installation Handling
|
||||
|
||||
| CLI | Auto-install? | Command |
|
||||
|-----|---------------|---------|
|
||||
| npm/pnpm/yarn | No - ask user | User chooses package manager |
|
||||
| vercel | Yes | `npm i -g vercel` |
|
||||
| gh (GitHub) | Yes | `brew install gh` (macOS) or `apt install gh` (Linux) |
|
||||
| stripe | Yes | `npm i -g stripe` |
|
||||
| supabase | Yes | `npm i -g supabase` |
|
||||
| convex | No - use npx | `npx convex` (no install needed) |
|
||||
| fly | Yes | `brew install flyctl` or curl installer |
|
||||
| railway | Yes | `npm i -g @railway/cli` |
|
||||
|
||||
**Protocol:** Try command → "command not found" → auto-installable? → yes: install silently, retry → no: checkpoint asking user to install.
|
||||
|
||||
## Pre-Checkpoint Automation Failures
|
||||
|
||||
| Failure | Response |
|
||||
|---------|----------|
|
||||
| Server won't start | Check error, fix issue, retry (don't proceed to checkpoint) |
|
||||
| Port in use | Kill stale process or use alternate port |
|
||||
| Missing dependency | Run `npm install`, retry |
|
||||
| Build error | Fix the error first (bug, not checkpoint issue) |
|
||||
| Auth error | Create auth gate checkpoint |
|
||||
| Network timeout | Retry with backoff, then checkpoint if persistent |
|
||||
|
||||
**Never present a checkpoint with broken verification environment.** If the local server isn't responding, don't ask user to "visit localhost:3000".
|
||||
|
||||
> **Cross-platform note:** Use `node -e "fetch('http://localhost:3000').then(r=>console.log(r.status))"` instead of `curl` for health checks. `curl` is broken on Windows MSYS/Git Bash due to SSL/path mangling issues.
|
||||
|
||||
```xml
|
||||
<!-- WRONG: Checkpoint with broken environment -->
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Dashboard (server failed to start)</what-built>
|
||||
<how-to-verify>Visit http://localhost:3000...</how-to-verify>
|
||||
</task>
|
||||
|
||||
<!-- RIGHT: Fix first, then checkpoint -->
|
||||
<task type="auto">
|
||||
<name>Fix server startup issue</name>
|
||||
<action>Investigate error, fix root cause, restart server</action>
|
||||
<verify>fetch http://localhost:3000 returns 200</verify>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Dashboard - server running at http://localhost:3000</what-built>
|
||||
<how-to-verify>Visit http://localhost:3000/dashboard...</how-to-verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
## Automatable Quick Reference
|
||||
|
||||
| Action | Automatable? | Claude does it? |
|
||||
|--------|--------------|-----------------|
|
||||
| Deploy to Vercel | Yes (`vercel`) | YES |
|
||||
| Create Stripe webhook | Yes (API) | YES |
|
||||
| Write .env file | Yes (Write tool) | YES |
|
||||
| Create Upstash DB | Yes (`upstash`) | YES |
|
||||
| Run tests | Yes (`npm test`) | YES |
|
||||
| Start dev server | Yes (`npm run dev`) | YES |
|
||||
| Add env vars to Convex | Yes (`npx convex env set`) | YES |
|
||||
| Add env vars to Vercel | Yes (`vercel env add`) | YES |
|
||||
| Seed database | Yes (CLI/API) | YES |
|
||||
| Click email verification link | No | NO |
|
||||
| Enter credit card with 3DS | No | NO |
|
||||
| Complete OAuth in browser | No | NO |
|
||||
| Visually verify UI looks correct | No | NO |
|
||||
| Test interactive user flows | No | NO |
|
||||
|
||||
</automation_reference>
|
||||
|
||||
<writing_guidelines>
|
||||
|
||||
**DO:**
|
||||
- Automate everything with CLI/API before checkpoint
|
||||
- Be specific: "Visit https://myapp.vercel.app" not "check deployment"
|
||||
- Number verification steps
|
||||
- State expected outcomes: "You should see X"
|
||||
- Provide context: why this checkpoint exists
|
||||
|
||||
**DON'T:**
|
||||
- Ask human to do work Claude can automate ❌
|
||||
- Assume knowledge: "Configure the usual settings" ❌
|
||||
- Skip steps: "Set up database" (too vague) ❌
|
||||
- Mix multiple verifications in one checkpoint ❌
|
||||
|
||||
**Placement:**
|
||||
- **After automation completes** - not before Claude does the work
|
||||
- **After UI buildout** - before declaring phase complete
|
||||
- **Before dependent work** - decisions before implementation
|
||||
- **At integration points** - after configuring external services
|
||||
|
||||
**Bad placement:** Before automation ❌ | Too frequent ❌ | Too late (dependent tasks already needed the result) ❌
|
||||
</writing_guidelines>
|
||||
|
||||
<examples>
|
||||
|
||||
### Example 1: Database Setup (No Checkpoint Needed)
|
||||
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Create Upstash Redis database</name>
|
||||
<files>.env</files>
|
||||
<action>
|
||||
1. Run `upstash redis create myapp-cache --region us-east-1`
|
||||
2. Capture connection URL from output
|
||||
3. Write to .env: UPSTASH_REDIS_URL={url}
|
||||
4. Verify connection with test command
|
||||
</action>
|
||||
<verify>
|
||||
- upstash redis list shows database
|
||||
- .env contains UPSTASH_REDIS_URL
|
||||
- Test connection succeeds
|
||||
</verify>
|
||||
<done>Redis database created and configured</done>
|
||||
</task>
|
||||
|
||||
<!-- NO CHECKPOINT NEEDED - Claude automated everything and verified programmatically -->
|
||||
```
|
||||
|
||||
### Example 2: Full Auth Flow (Single checkpoint at end)
|
||||
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Create user schema</name>
|
||||
<files>src/db/schema.ts</files>
|
||||
<action>Define User, Session, Account tables with Drizzle ORM</action>
|
||||
<verify>npm run db:generate succeeds</verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Create auth API routes</name>
|
||||
<files>src/app/api/auth/[...nextauth]/route.ts</files>
|
||||
<action>Set up NextAuth with GitHub provider, JWT strategy</action>
|
||||
<verify>TypeScript compiles, no errors</verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Create login UI</name>
|
||||
<files>src/app/login/page.tsx, src/components/LoginButton.tsx</files>
|
||||
<action>Create login page with GitHub OAuth button</action>
|
||||
<verify>npm run build succeeds</verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Start dev server for auth testing</name>
|
||||
<action>Run `npm run dev` in background, wait for ready signal</action>
|
||||
<verify>fetch http://localhost:3000 returns 200</verify>
|
||||
<done>Dev server running at http://localhost:3000</done>
|
||||
</task>
|
||||
|
||||
<!-- ONE checkpoint at end verifies the complete flow -->
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Complete authentication flow - dev server running at http://localhost:3000</what-built>
|
||||
<how-to-verify>
|
||||
1. Visit: http://localhost:3000/login
|
||||
2. Click "Sign in with GitHub"
|
||||
3. Complete GitHub OAuth flow
|
||||
4. Verify: Redirected to /dashboard, user name displayed
|
||||
5. Refresh page: Session persists
|
||||
6. Click logout: Session cleared
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" or describe issues</resume-signal>
|
||||
</task>
|
||||
```
|
||||
</examples>
|
||||
|
||||
<anti_patterns>
|
||||
|
||||
### ❌ BAD: Asking user to start dev server
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Dashboard component</what-built>
|
||||
<how-to-verify>
|
||||
1. Run: npm run dev
|
||||
2. Visit: http://localhost:3000/dashboard
|
||||
3. Check layout is correct
|
||||
</how-to-verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Why bad:** Claude can run `npm run dev`. User should only visit URLs, not execute commands.
|
||||
|
||||
### ✅ GOOD: Claude starts server, user visits
|
||||
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Start dev server</name>
|
||||
<action>Run `npm run dev` in background</action>
|
||||
<verify>fetch http://localhost:3000 returns 200</verify>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Dashboard at http://localhost:3000/dashboard (server running)</what-built>
|
||||
<how-to-verify>
|
||||
Visit http://localhost:3000/dashboard and verify:
|
||||
1. Layout matches design
|
||||
2. No console errors
|
||||
</how-to-verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
### ❌ BAD: Asking human to deploy / ✅ GOOD: Claude automates
|
||||
|
||||
```xml
|
||||
<!-- BAD: Asking user to deploy via dashboard -->
|
||||
<task type="checkpoint:human-action" gate="blocking">
|
||||
<action>Deploy to Vercel</action>
|
||||
<instructions>Visit vercel.com/new → Import repo → Click Deploy → Copy URL</instructions>
|
||||
</task>
|
||||
|
||||
<!-- GOOD: Claude deploys, user verifies -->
|
||||
<task type="auto">
|
||||
<name>Deploy to Vercel</name>
|
||||
<action>Run `vercel --yes`. Capture URL.</action>
|
||||
<verify>vercel ls shows deployment, fetch returns 200</verify>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Deployed to {url}</what-built>
|
||||
<how-to-verify>Visit {url}, check homepage loads</how-to-verify>
|
||||
<resume-signal>Type "approved"</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
### ❌ BAD: Too many checkpoints / ✅ GOOD: Single checkpoint
|
||||
|
||||
```xml
|
||||
<!-- BAD: Checkpoint after every task -->
|
||||
<task type="auto">Create schema</task>
|
||||
<task type="checkpoint:human-verify">Check schema</task>
|
||||
<task type="auto">Create API route</task>
|
||||
<task type="checkpoint:human-verify">Check API</task>
|
||||
<task type="auto">Create UI form</task>
|
||||
<task type="checkpoint:human-verify">Check form</task>
|
||||
|
||||
<!-- GOOD: One checkpoint at end -->
|
||||
<task type="auto">Create schema</task>
|
||||
<task type="auto">Create API route</task>
|
||||
<task type="auto">Create UI form</task>
|
||||
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Complete auth flow (schema + API + UI)</what-built>
|
||||
<how-to-verify>Test full flow: register, login, access protected page</how-to-verify>
|
||||
<resume-signal>Type "approved"</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
### ❌ BAD: Vague verification / ✅ GOOD: Specific steps
|
||||
|
||||
```xml
|
||||
<!-- BAD -->
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Dashboard</what-built>
|
||||
<how-to-verify>Check it works</how-to-verify>
|
||||
</task>
|
||||
|
||||
<!-- GOOD -->
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Responsive dashboard - server running at http://localhost:3000</what-built>
|
||||
<how-to-verify>
|
||||
Visit http://localhost:3000/dashboard and verify:
|
||||
1. Desktop (>1024px): Sidebar visible, content area fills remaining space
|
||||
2. Tablet (768px): Sidebar collapses to icons
|
||||
3. Mobile (375px): Sidebar hidden, hamburger menu in header
|
||||
4. No horizontal scroll at any size
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" or describe layout issues</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
### ❌ BAD: Asking user to run CLI commands
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-action">
|
||||
<action>Run database migrations</action>
|
||||
<instructions>Run: npx prisma migrate deploy && npx prisma db seed</instructions>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Why bad:** Claude can run these commands. User should never execute CLI commands.
|
||||
|
||||
### ❌ BAD: Asking user to copy values between services
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-action">
|
||||
<action>Configure webhook URL in Stripe</action>
|
||||
<instructions>Copy deployment URL → Stripe Dashboard → Webhooks → Add endpoint → Copy secret → Add to .env</instructions>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Why bad:** Stripe has an API. Claude should create the webhook via API and write to .env directly.
|
||||
|
||||
</anti_patterns>
|
||||
|
||||
<type name="tdd-review">
|
||||
## checkpoint:tdd-review (TDD Mode Only)
|
||||
|
||||
**When:** All waves in a phase complete and `workflow.tdd_mode` is enabled. Inserted by the execute-phase orchestrator after `aggregate_results`.
|
||||
|
||||
**Purpose:** Collaborative review of TDD gate compliance across all `type: tdd` plans in the phase. Advisory — does not block execution.
|
||||
|
||||
**Use for:**
|
||||
- Verifying RED/GREEN/REFACTOR commit sequence for each TDD plan
|
||||
- Surfacing gate violations (missing RED or GREEN commits)
|
||||
- Reviewing test quality (tests fail for the right reason)
|
||||
- Confirming minimal GREEN implementations
|
||||
|
||||
**Structure:**
|
||||
```xml
|
||||
<task type="checkpoint:tdd-review" gate="advisory">
|
||||
<what-checked>TDD gate compliance for {count} plans in Phase {X}</what-checked>
|
||||
<gate-results>
|
||||
| Plan | RED | GREEN | REFACTOR | Status |
|
||||
|------|-----|-------|----------|--------|
|
||||
| {id} | ✓ | ✓ | ✓ | Pass |
|
||||
</gate-results>
|
||||
<violations>[List of gate violations, or "None"]</violations>
|
||||
<resume-signal>Review complete — proceed to phase verification</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Auto-mode behavior:** When `workflow._auto_chain_active` or `workflow.auto_advance` is true, the TDD review checkpoint auto-approves (advisory gate — never blocks).
|
||||
</type>
|
||||
|
||||
<summary>
|
||||
|
||||
Checkpoints formalize human-in-the-loop points for verification and decisions, not manual work.
|
||||
|
||||
**The golden rule:** If Claude CAN automate it, Claude MUST automate it.
|
||||
|
||||
**Checkpoint priority:**
|
||||
1. **checkpoint:human-verify** (90%) - Claude automated everything, human confirms visual/functional correctness
|
||||
2. **checkpoint:decision** (9%) - Human makes architectural/technology choices
|
||||
3. **checkpoint:human-action** (1%) - Truly unavoidable manual steps with no API/CLI
|
||||
|
||||
**When NOT to use checkpoints:**
|
||||
- Things Claude can verify programmatically (tests, builds)
|
||||
- File operations (Claude can read files)
|
||||
- Code correctness (tests and static analysis)
|
||||
- Anything automatable via CLI/API
|
||||
</summary>
|
||||
114
gsd-core/references/common-bug-patterns.md
Normal file
114
gsd-core/references/common-bug-patterns.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Common Bug Patterns
|
||||
|
||||
Checklist of frequent bug patterns to scan before forming hypotheses. Ordered by frequency. Check these FIRST — they cover ~80% of bugs across all technology stacks.
|
||||
|
||||
<patterns>
|
||||
|
||||
## Null / Undefined Access
|
||||
|
||||
- **Null property access** — accessing property on `null` or `undefined`, missing null check or optional chaining
|
||||
- **Missing return value** — function returns `undefined` instead of expected value, missing `return` statement or wrong branch
|
||||
- **Destructuring null** — array/object destructuring on `null`/`undefined`, API returned error shape instead of data
|
||||
- **Undefaulted optional** — optional parameter used without default, caller omitted argument
|
||||
|
||||
## Off-by-One / Boundary
|
||||
|
||||
- **Wrong loop bound** — loop starts at 1 instead of 0, or ends at `length` instead of `length - 1`
|
||||
- **Fence-post error** — "N items need N-1 separators" miscounted
|
||||
- **Inclusive vs exclusive** — range boundary `<` vs `<=`, slice/substring end index
|
||||
- **Empty collection** — `.length === 0` falls through to logic assuming items exist
|
||||
|
||||
## Async / Timing
|
||||
|
||||
- **Missing await** — async function called without `await`, gets Promise object instead of resolved value
|
||||
- **Race condition** — two async operations read/write same state without coordination
|
||||
- **Stale closure** — callback captures old variable value, not current one
|
||||
- **Initialization order** — event handler fires before setup complete
|
||||
- **Leaked timer** — timeout/interval not cleaned up, fires after component/context destroyed
|
||||
|
||||
## State Management
|
||||
|
||||
- **Shared mutation** — object/array modified in place affects other consumers
|
||||
- **Stale render** — state updated but UI not re-rendered, missing reactive trigger or wrong reference
|
||||
- **Stale handler state** — closure captures state at bind time, not current value
|
||||
- **Dual source of truth** — same data stored in two places, one gets out of sync
|
||||
- **Invalid transition** — state machine allows transition missing guard condition
|
||||
|
||||
## Import / Module
|
||||
|
||||
- **Circular dependency** — module A imports B, B imports A, one gets `undefined`
|
||||
- **Export mismatch** — default vs named export, `import X` vs `import { X }`
|
||||
- **Wrong extension** — `.js` vs `.cjs` vs `.mjs`, `.ts` vs `.tsx`
|
||||
- **Path case sensitivity** — works on Windows/macOS, fails on Linux
|
||||
- **Missing extension** — ESM requires explicit file extensions in imports
|
||||
|
||||
## Type / Coercion
|
||||
|
||||
- **String vs number compare** — `"5" > "10"` is `true` (lexicographic), `5 > 10` is `false`
|
||||
- **Implicit coercion** — `==` instead of `===`, truthy/falsy surprises (`0`, `""`, `[]`)
|
||||
- **Numeric precision** — `0.1 + 0.2 !== 0.3`, large integers lose precision
|
||||
- **Falsy valid value** — value is `0` or `""` which is valid but falsy
|
||||
|
||||
## Environment / Config
|
||||
|
||||
- **Missing env var** — environment variable missing or wrong value in dev vs prod vs CI
|
||||
- **Hardcoded path** — works on one machine, fails on another
|
||||
- **Port conflict** — port already in use, previous process still running
|
||||
- **Permission denied** — different user/group in deployment
|
||||
- **Missing dependency** — not in package.json or not installed
|
||||
|
||||
## Data Shape / API Contract
|
||||
|
||||
- **Changed response shape** — backend updated, frontend expects old format
|
||||
- **Wrong container type** — array where object expected or vice versa, `data` vs `data.results` vs `data[0]`
|
||||
- **Missing required field** — required field omitted in payload, backend returns validation error
|
||||
- **Date format mismatch** — ISO string vs timestamp vs locale string
|
||||
- **Encoding mismatch** — UTF-8 vs Latin-1, URL encoding, HTML entities
|
||||
|
||||
## Regex / String
|
||||
|
||||
- **Sticky lastIndex** — regex `g` flag with `.test()` then `.exec()`, `lastIndex` not reset between calls
|
||||
- **Missing escape** — `.` matches any char, `$` is special, backslash needs doubling
|
||||
- **Greedy overmatch** — `.*` eats through delimiters, need `.*?`
|
||||
- **Wrong quote type** — string interpolation needs backticks for template literals
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **Swallowed error** — empty `catch {}` or logs but doesn't rethrow/handle
|
||||
- **Wrong error type** — catches base `Error` when specific type needed
|
||||
- **Error in handler** — cleanup code throws, masking original error
|
||||
- **Unhandled rejection** — missing `.catch()` or try/catch around `await`
|
||||
|
||||
## Scope / Closure
|
||||
|
||||
- **Variable shadowing** — inner scope declares same name, hides outer variable
|
||||
- **Loop variable capture** — all closures share same `var i`, use `let` or bind
|
||||
- **Lost this binding** — callback loses context, need `.bind()` or arrow function
|
||||
- **Scope confusion** — `var` hoisted to function, `let`/`const` block-scoped
|
||||
|
||||
</patterns>
|
||||
|
||||
<usage>
|
||||
|
||||
## How to Use This Checklist
|
||||
|
||||
1. **Before forming any hypothesis**, scan the relevant categories based on the symptom
|
||||
2. **Match symptom to pattern** — if the bug involves "undefined is not an object", check Null/Undefined first
|
||||
3. **Each checked pattern is a hypothesis candidate** — verify or eliminate with evidence
|
||||
4. **If no pattern matches**, proceed to open-ended investigation
|
||||
|
||||
### Symptom-to-Category Quick Map
|
||||
|
||||
| Symptom | Check First |
|
||||
|---------|------------|
|
||||
| "Cannot read property of undefined/null" | Null/Undefined Access |
|
||||
| "X is not a function" | Import/Module, Type/Coercion |
|
||||
| Works sometimes, fails sometimes | Async/Timing, State Management |
|
||||
| Works locally, fails in CI/prod | Environment/Config |
|
||||
| Wrong data displayed | Data Shape, State Management |
|
||||
| Off by one item / missing last item | Off-by-One/Boundary |
|
||||
| "Unexpected token" / parse error | Data Shape, Type/Coercion |
|
||||
| Memory leak / growing resource usage | Async/Timing (cleanup), Scope/Closure |
|
||||
| Infinite loop / max call stack | State Management, Async/Timing |
|
||||
|
||||
</usage>
|
||||
85
gsd-core/references/context-budget.md
Normal file
85
gsd-core/references/context-budget.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Context Budget Rules
|
||||
|
||||
Standard rules for keeping orchestrator context lean. Reference this in workflows that spawn subagents or read significant content.
|
||||
|
||||
See also: `references/universal-anti-patterns.md` for the complete set of universal rules.
|
||||
|
||||
---
|
||||
|
||||
## Universal Rules
|
||||
|
||||
Every workflow that spawns agents or reads significant content must follow these rules:
|
||||
|
||||
1. **Never** read agent definition files (`agents/*.md`) -- `subagent_type` auto-loads them
|
||||
2. **Never** inline large files into subagent prompts -- tell agents to read files from disk instead
|
||||
3. **Read depth scales with context window** -- check `context_window` in `.planning/config.json`:
|
||||
- At < 500000 tokens (default 200k): read only frontmatter, status fields, or summaries. Never read full SUMMARY.md, VERIFICATION.md, or RESEARCH.md bodies.
|
||||
- At >= 500000 tokens (1M model): MAY read full subagent output bodies when the content is needed for inline presentation or decision-making. Still avoid unnecessary reads.
|
||||
4. **Delegate** heavy work to subagents -- the orchestrator routes, it doesn't execute
|
||||
5. **Proactive warning**: If you've already consumed significant context (large file reads, multiple subagent results), warn the user: "Context budget is getting heavy. Consider checkpointing progress."
|
||||
|
||||
## Read Depth by Context Window
|
||||
|
||||
| Context Window | Subagent Output Reading | SUMMARY.md | VERIFICATION.md | PLAN.md (other phases) |
|
||||
|---------------|------------------------|------------|-----------------|------------------------|
|
||||
| < 500k (200k model) | Frontmatter only | Frontmatter only | Frontmatter only | Current phase only |
|
||||
| >= 500k (1M model) | Full body permitted | Full body permitted | Full body permitted | Current phase only |
|
||||
|
||||
**How to check:** Read `.planning/config.json` and inspect `context_window`. If the field is absent, treat as 200k (conservative default).
|
||||
|
||||
## Context Degradation Tiers
|
||||
|
||||
Monitor context usage and adjust behavior accordingly:
|
||||
|
||||
| Tier | Usage | Behavior |
|
||||
|------|-------|----------|
|
||||
| PEAK | 0-30% | Full operations. Read bodies, spawn multiple agents, inline results. |
|
||||
| GOOD | 30-50% | Normal operations. Prefer frontmatter reads, delegate aggressively. |
|
||||
| DEGRADING | 50-70% | Economize. Frontmatter-only reads, minimal inlining, warn user about budget. |
|
||||
| POOR | 70%+ | Emergency mode. Checkpoint progress immediately. No new reads unless critical. |
|
||||
|
||||
## Context Degradation Warning Signs
|
||||
|
||||
Quality degrades gradually before panic thresholds fire. Watch for these early signals:
|
||||
|
||||
- **Silent partial completion** -- agent claims task is done but implementation is incomplete. Self-check catches file existence but not semantic completeness. Always verify agent output meets the plan's must_haves, not just that files exist.
|
||||
- **Increasing vagueness** -- agent starts using phrases like "appropriate handling" or "standard patterns" instead of specific code. This indicates context pressure even before budget warnings fire.
|
||||
- **Skipped steps** -- agent omits protocol steps it would normally follow. If an agent's success criteria has 8 items but it only reports 5, suspect context pressure.
|
||||
|
||||
When delegating to agents, the orchestrator cannot verify semantic correctness of agent output -- only structural completeness. This is a fundamental limitation. Mitigate with must_haves.truths and spot-check verification.
|
||||
|
||||
## MCP Tool Schema Cost (Harness Concern)
|
||||
|
||||
Every enabled MCP server injects its tool schema into **every turn**, regardless of whether you call any of its tools. Heavyweight servers can cost 20k+ tokens per turn each — often dwarfing whatever GSD itself can save through `model_profile` tuning. This is a Claude Code harness concern, not a GSD concern: GSD does **not** manage MCP enablement. The toggle lives in `.claude/settings.json` under `enabledMcpjsonServers` and `disabledMcpjsonServers`.
|
||||
|
||||
### Why this is the biggest cost lever you don't own
|
||||
|
||||
Tool schemas count against the same context budget as model context, prompts, and conversation history. If a project has 5 unused MCP servers averaging 5k tokens of schema each, every turn pays a 25k-token tax before the assistant reads a single project file. Trimming MCPs has a **multiplier effect** that compounds with whichever `model_profile` you've chosen — every-turn overhead drops regardless of which model is in use.
|
||||
|
||||
### Pre-Phase MCP Audit
|
||||
|
||||
Before starting a long phase (especially `/gsd:execute-phase`, `/gsd:plan-phase`, or anything that fans out across many subagents), run this audit:
|
||||
|
||||
- [ ] **Browser / playwright tools enabled?** If this phase has no UI work, disable them. They're among the heaviest per-turn schemas.
|
||||
- [ ] **Platform-specific tools enabled?** Mac-tools / Windows-tools / OS-specific helpers should be disabled when not actively needed for the phase at hand.
|
||||
- [ ] **Cross-project / stale MCPs?** Servers added for a different project that are still enabled here. These are often forgotten and pay a per-turn tax for zero benefit.
|
||||
- [ ] **Duplicate or shadow servers?** Two MCPs offering similar tools (e.g. two different filesystem helpers). Keep one.
|
||||
|
||||
Each item disabled removes its schema from every subsequent turn for the rest of the session.
|
||||
|
||||
### How to toggle
|
||||
|
||||
The keys live in `.claude/settings.json` (project) or `~/.claude/settings.json` (global) — **not** in `.planning/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"enabledMcpjsonServers": ["context7"],
|
||||
"disabledMcpjsonServers": ["playwright", "mac-tools"]
|
||||
}
|
||||
```
|
||||
|
||||
Either list works — `enabledMcpjsonServers` is an explicit allow-list, `disabledMcpjsonServers` is a block-list against the default. See the [Claude Code MCP documentation](https://docs.anthropic.com/en/docs/claude-code/mcp) for the canonical reference; this section just flags it as a context-budget lever GSD users routinely overlook.
|
||||
|
||||
### Composition with model_profile
|
||||
|
||||
Trimming MCPs and tuning `model_profile` are independent levers that **compound**. Disabling a 25k-token MCP saves 25k per turn whether you're running `quality` (opus everywhere) or `budget` (sonnet/haiku); the savings are additive, not in lieu of model tuning. Don't pick one — do both, and audit MCPs first because the per-turn savings show up immediately and stack across every subagent the orchestrator spawns.
|
||||
253
gsd-core/references/continuation-format.md
Normal file
253
gsd-core/references/continuation-format.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# Continuation Format
|
||||
|
||||
Standard format for presenting next steps after completing a command or workflow.
|
||||
|
||||
## Core Structure
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**{identifier}: {name}** — {one-line description}
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`{command to copy-paste}`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `{alternative option 1}` — description
|
||||
- `{alternative option 2}` — description
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
> If `project_code` is not set in the init context, omit the project identity suffix:
|
||||
> `## ▶ Next Up` (no ` — [CODE] Title`).
|
||||
|
||||
## Format Rules
|
||||
|
||||
1. **Always show what it is** — name + description, never just a command path
|
||||
2. **Pull context from source** — ROADMAP.md for phases, PLAN.md `<objective>` for plans
|
||||
3. **Command in inline code** — backticks, easy to copy-paste, renders as clickable link
|
||||
4. **`/clear` first** — always show `/clear` before the command so users run it in the correct order
|
||||
5. **"Also available" not "Other options"** — sounds more app-like
|
||||
6. **Visual separators** — `---` above and below to make it stand out
|
||||
7. **Project identity in heading** — include `[PROJECT_CODE] PROJECT_TITLE` from init context so handoffs are self-identifying across sessions. If `project_code` is not set, omit the suffix entirely (just `## ▶ Next Up`)
|
||||
|
||||
## Variants
|
||||
|
||||
### Execute Next Plan
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:execute-phase 2`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- Review plan before executing
|
||||
- `/gsd:discuss-phase 2 --assumptions` — check assumptions
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Execute Final Plan in Phase
|
||||
|
||||
Add note that this is the last plan and what comes after:
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
|
||||
<sub>Final plan in Phase 2</sub>
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:execute-phase 2`
|
||||
|
||||
---
|
||||
|
||||
**After this completes:**
|
||||
- Phase 2 → Phase 3 transition
|
||||
- Next: **Phase 3: Core Features** — User dashboard and settings
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Plan a Phase
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Phase 2: Authentication** — JWT login flow with refresh tokens
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:plan-phase 2`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase 2` — gather context first
|
||||
- `/gsd:plan-phase --research-phase 2` — investigate unknowns
|
||||
- Review roadmap
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Phase Complete, Ready for Next
|
||||
|
||||
Show completion status before next action:
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ✓ Phase 2 Complete
|
||||
|
||||
3/3 plans executed
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Phase 3: Core Features** — User dashboard, settings, and data export
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:plan-phase 3`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase 3` — gather context first
|
||||
- `/gsd:plan-phase --research-phase 3` — investigate unknowns
|
||||
- Review what Phase 2 built
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Multiple Equal Options
|
||||
|
||||
When there's no clear primary action:
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Phase 3: Core Features** — User dashboard, settings, and data export
|
||||
|
||||
`/clear` then one of:
|
||||
|
||||
**To plan directly:** `/gsd:plan-phase 3`
|
||||
|
||||
**To discuss context first:** `/gsd:discuss-phase 3`
|
||||
|
||||
**To research unknowns:** `/gsd:plan-phase --research-phase 3`
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Milestone Complete
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## 🎉 Milestone v1.0 Complete
|
||||
|
||||
All 4 phases shipped
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Start v1.1** — questioning → research → requirements → roadmap
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:new-milestone`
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
## Pulling Context
|
||||
|
||||
### For phases (from ROADMAP.md):
|
||||
|
||||
```markdown
|
||||
### Phase 2: Authentication
|
||||
**Goal**: JWT login flow with refresh tokens
|
||||
```
|
||||
|
||||
Extract: `**Phase 2: Authentication** — JWT login flow with refresh tokens`
|
||||
|
||||
### For plans (from ROADMAP.md):
|
||||
|
||||
```markdown
|
||||
Plans:
|
||||
- [ ] 02-03: Add refresh token rotation
|
||||
```
|
||||
|
||||
Or from PLAN.md `<objective>`:
|
||||
|
||||
```xml
|
||||
<objective>
|
||||
Add refresh token rotation with sliding expiry window.
|
||||
|
||||
Purpose: Extend session lifetime without compromising security.
|
||||
</objective>
|
||||
```
|
||||
|
||||
Extract: `**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry`
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
### Don't: Command-only (no context)
|
||||
|
||||
```
|
||||
## To Continue
|
||||
|
||||
Run `/clear`, then paste:
|
||||
/gsd:execute-phase 2
|
||||
```
|
||||
|
||||
User has no idea what 02-03 is about.
|
||||
|
||||
### Don't: Missing /clear explanation
|
||||
|
||||
```
|
||||
`/gsd:plan-phase 3`
|
||||
|
||||
Run /clear first.
|
||||
```
|
||||
|
||||
Doesn't explain why. User might skip it.
|
||||
|
||||
### Don't: "Other options" language
|
||||
|
||||
```
|
||||
Other options:
|
||||
- Review roadmap
|
||||
```
|
||||
|
||||
Sounds like an afterthought. Use "Also available:" instead.
|
||||
|
||||
### Don't: Fenced code blocks for commands
|
||||
|
||||
```
|
||||
```
|
||||
/gsd:plan-phase 3
|
||||
```
|
||||
```
|
||||
|
||||
Fenced blocks inside templates create nesting ambiguity. Use inline backticks instead.
|
||||
76
gsd-core/references/debugger-philosophy.md
Normal file
76
gsd-core/references/debugger-philosophy.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Debugger Philosophy
|
||||
|
||||
Evergreen debugging disciplines — applies across every bug, every language, every system. Loaded by `gsd-debugger` via `@file` include.
|
||||
|
||||
## User = Reporter, Claude = Investigator
|
||||
|
||||
The user knows:
|
||||
- What they expected to happen
|
||||
- What actually happened
|
||||
- Error messages they saw
|
||||
- When it started / if it ever worked
|
||||
|
||||
The user does NOT know (don't ask):
|
||||
- What's causing the bug
|
||||
- Which file has the problem
|
||||
- What the fix should be
|
||||
|
||||
Ask about experience. Investigate the cause yourself.
|
||||
|
||||
## Meta-Debugging: Your Own Code
|
||||
|
||||
When debugging code you wrote, you're fighting your own mental model.
|
||||
|
||||
**Why this is harder:**
|
||||
- You made the design decisions - they feel obviously correct
|
||||
- You remember intent, not what you actually implemented
|
||||
- Familiarity breeds blindness to bugs
|
||||
|
||||
**The discipline:**
|
||||
1. **Treat your code as foreign** - Read it as if someone else wrote it
|
||||
2. **Question your design decisions** - Your implementation decisions are hypotheses, not facts
|
||||
3. **Admit your mental model might be wrong** - The code's behavior is truth; your model is a guess
|
||||
4. **Prioritize code you touched** - If you modified 100 lines and something breaks, those are prime suspects
|
||||
|
||||
**The hardest admission:** "I implemented this wrong." Not "requirements were unclear" - YOU made an error.
|
||||
|
||||
## Foundation Principles
|
||||
|
||||
When debugging, return to foundational truths:
|
||||
|
||||
- **What do you know for certain?** Observable facts, not assumptions
|
||||
- **What are you assuming?** "This library should work this way" - have you verified?
|
||||
- **Strip away everything you think you know.** Build understanding from observable facts.
|
||||
|
||||
## Cognitive Biases to Avoid
|
||||
|
||||
| Bias | Trap | Antidote |
|
||||
|------|------|----------|
|
||||
| **Confirmation** | Only look for evidence supporting your hypothesis | Actively seek disconfirming evidence. "What would prove me wrong?" |
|
||||
| **Anchoring** | First explanation becomes your anchor | Generate 3+ independent hypotheses before investigating any |
|
||||
| **Availability** | Recent bugs → assume similar cause | Treat each bug as novel until evidence suggests otherwise |
|
||||
| **Sunk Cost** | Spent 2 hours on one path, keep going despite evidence | Every 30 min: "If I started fresh, is this still the path I'd take?" |
|
||||
|
||||
## Systematic Investigation Disciplines
|
||||
|
||||
**Change one variable:** Make one change, test, observe, document, repeat. Multiple changes = no idea what mattered.
|
||||
|
||||
**Complete reading:** Read entire functions, not just "relevant" lines. Read imports, config, tests. Skimming misses crucial details.
|
||||
|
||||
**Embrace not knowing:** "I don't know why this fails" = good (now you can investigate). "It must be X" = dangerous (you've stopped thinking).
|
||||
|
||||
## When to Restart
|
||||
|
||||
Consider starting over when:
|
||||
1. **2+ hours with no progress** - You're likely tunnel-visioned
|
||||
2. **3+ "fixes" that didn't work** - Your mental model is wrong
|
||||
3. **You can't explain the current behavior** - Don't add changes on top of confusion
|
||||
4. **You're debugging the debugger** - Something fundamental is wrong
|
||||
5. **The fix works but you don't know why** - This isn't fixed, this is luck
|
||||
|
||||
**Restart protocol:**
|
||||
1. Close all files and terminals
|
||||
2. Write down what you know for certain
|
||||
3. Write down what you've ruled out
|
||||
4. List new hypotheses (different from before)
|
||||
5. Begin again from Phase 1: Evidence Gathering
|
||||
64
gsd-core/references/decimal-phase-calculation.md
Normal file
64
gsd-core/references/decimal-phase-calculation.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Decimal Phase Calculation
|
||||
|
||||
Calculate the next decimal phase number for urgent insertions.
|
||||
|
||||
## Using gsd-tools
|
||||
|
||||
```bash
|
||||
# Get next decimal phase after phase 6
|
||||
gsd-tools query phase.next-decimal 6
|
||||
```
|
||||
|
||||
Output:
|
||||
```json
|
||||
{
|
||||
"found": true,
|
||||
"base_phase": "06",
|
||||
"next": "06.1",
|
||||
"existing": []
|
||||
}
|
||||
```
|
||||
|
||||
With existing decimals:
|
||||
```json
|
||||
{
|
||||
"found": true,
|
||||
"base_phase": "06",
|
||||
"next": "06.3",
|
||||
"existing": ["06.1", "06.2"]
|
||||
}
|
||||
```
|
||||
|
||||
## Extract Values
|
||||
|
||||
```bash
|
||||
DECIMAL_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --pick next)
|
||||
BASE_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --pick base_phase)
|
||||
```
|
||||
|
||||
Or with --raw flag:
|
||||
```bash
|
||||
DECIMAL_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --raw)
|
||||
# Returns just: 06.1
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
| Existing Phases | Next Phase |
|
||||
|-----------------|------------|
|
||||
| 06 only | 06.1 |
|
||||
| 06, 06.1 | 06.2 |
|
||||
| 06, 06.1, 06.2 | 06.3 |
|
||||
| 06, 06.1, 06.3 (gap) | 06.4 |
|
||||
|
||||
## Directory Naming
|
||||
|
||||
Decimal phase directories use the full decimal number:
|
||||
|
||||
```bash
|
||||
SLUG=$(gsd-tools query generate-slug "$DESCRIPTION" --raw)
|
||||
PHASE_DIR=".planning/phases/${DECIMAL_PHASE}-${SLUG}"
|
||||
mkdir -p "$PHASE_DIR"
|
||||
```
|
||||
|
||||
Example: `.planning/phases/06.1-fix-critical-auth-bug/`
|
||||
91
gsd-core/references/doc-conflict-engine.md
Normal file
91
gsd-core/references/doc-conflict-engine.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Doc Conflict Engine
|
||||
|
||||
Shared conflict-detection contract for workflows that ingest external content into `.planning/` (e.g., `/gsd:import`, `/gsd:ingest-docs`). Defines the report format, severity semantics, and safety-gate behavior. The specific checks that populate each severity bucket are workflow-specific and defined by the calling workflow.
|
||||
|
||||
---
|
||||
|
||||
## Severity Semantics
|
||||
|
||||
- **[BLOCKER]** — Unsafe to proceed. The workflow MUST exit without writing any destination files. Used for contradictions of locked decisions, missing prerequisites, and impossible targets.
|
||||
- **[WARNING]** — Ambiguous or partially overlapping. The workflow MUST surface the warning and obtain explicit user approval before writing. Never auto-approve.
|
||||
- **[INFO]** — Informational only. No gate; no user prompt required. Included in the report for transparency.
|
||||
|
||||
---
|
||||
|
||||
## Report Format
|
||||
|
||||
Plain-text, never markdown tables (no `|---|`). The report is rendered to the user verbatim.
|
||||
|
||||
```
|
||||
## Conflict Detection Report
|
||||
|
||||
### BLOCKERS ({N})
|
||||
|
||||
[BLOCKER] {Short title}
|
||||
Found: {what the incoming content says}
|
||||
Expected: {what existing project context requires}
|
||||
→ {Specific action to resolve}
|
||||
|
||||
### WARNINGS ({N})
|
||||
|
||||
[WARNING] {Short title}
|
||||
Found: {what was detected}
|
||||
Impact: {what could go wrong}
|
||||
→ {Suggested action}
|
||||
|
||||
### INFO ({N})
|
||||
|
||||
[INFO] {Short title}
|
||||
Note: {relevant information}
|
||||
```
|
||||
|
||||
Every entry requires `Found:` plus one of `Expected:`/`Impact:`/`Note:` plus (for BLOCKER/WARNING) a `→` remediation line.
|
||||
|
||||
---
|
||||
|
||||
## Safety Gate
|
||||
|
||||
**If any [BLOCKER] exists:**
|
||||
|
||||
Display:
|
||||
```
|
||||
GSD > BLOCKED: {N} blockers must be resolved before {operation} can proceed.
|
||||
```
|
||||
|
||||
Exit WITHOUT writing any destination files. The gate must hold regardless of WARNING/INFO counts.
|
||||
|
||||
**If only WARNINGS and/or INFO (no blockers):**
|
||||
|
||||
Render the full report, then prompt for approval via the `approve-revise-abort` or `yes-no` pattern from `references/gate-prompts.md`. Respect text mode (see the workflow's own text-mode handling). If the user aborts, exit cleanly with a cancellation message.
|
||||
|
||||
**If the report is empty (no entries in any bucket):**
|
||||
|
||||
Proceed silently or display `GSD > No conflicts detected.` Either is acceptable; workflows choose based on verbosity context.
|
||||
|
||||
---
|
||||
|
||||
## Workflow Responsibilities
|
||||
|
||||
Each workflow that consumes this contract must define:
|
||||
|
||||
1. **Its own check list per bucket** — which conditions are BLOCKER vs WARNING vs INFO. These are domain-specific (plan ingestion checks are not doc ingestion checks).
|
||||
2. **The loaded context** — what it reads (ROADMAP.md, PROJECT.md, REQUIREMENTS.md, CONTEXT.md, intel files) before running checks.
|
||||
3. **The operation noun** — substituted into the BLOCKED banner (`import`, `ingest`, etc.).
|
||||
|
||||
The workflow MUST NOT:
|
||||
|
||||
- Introduce new severity levels beyond BLOCKER/WARNING/INFO
|
||||
- Render the report as a markdown table
|
||||
- Write any destination file when BLOCKERs exist
|
||||
- Auto-approve past WARNINGs without user input
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
Do NOT:
|
||||
|
||||
- Use markdown tables (`|---|`) in the conflict report — use plain-text labels as shown above
|
||||
- Bypass the safety gate when BLOCKERs exist — no exceptions for "minor" blockers
|
||||
- Fold WARNINGs into INFO to skip the approval prompt — if user input is needed, it is a WARNING
|
||||
- Re-invent severity labels per workflow — the three-level taxonomy is fixed
|
||||
125
gsd-core/references/domain-probes.md
Normal file
125
gsd-core/references/domain-probes.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Domain-Aware Probing Patterns
|
||||
|
||||
Shared reference for `/gsd-begin`, `/gsd:discuss-phase`, and domain exploration workflows.
|
||||
|
||||
When the user mentions a technology area, use these probes to ask insightful follow-up questions. Don't run through them as a checklist -- pick the 2-3 most relevant based on context. The goal is to surface hidden assumptions and trade-offs the user may not have considered yet.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "login" or "auth" | OAuth (which providers?), JWT, or session-based? Do you need social login or just email/password? |
|
||||
| "users" or "accounts" | MFA required? Password reset flow? Email verification? |
|
||||
| "sessions" | Session duration and refresh strategy? Server-side sessions or stateless tokens? |
|
||||
| "roles" or "permissions" | RBAC, ABAC, or simple role checks? How many distinct roles? |
|
||||
| "API keys" | Key rotation strategy? Scoped permissions per key? Rate limiting per key? |
|
||||
|
||||
---
|
||||
|
||||
## Real-Time Updates
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "real-time" or "live updates" | WebSockets, SSE, or polling? What specifically needs to be real-time vs. eventual? |
|
||||
| "notifications" | Push notifications (browser/mobile), in-app only, or both? Persistence and read receipts? |
|
||||
| "collaboration" or "multiplayer" | Conflict resolution strategy? Operational transforms or CRDTs? Expected concurrent users? |
|
||||
| "chat" or "messaging" | Message history and search? Typing indicators? Read receipts? |
|
||||
| "streaming" | Reconnection strategy? What happens when the connection drops -- queue or discard? |
|
||||
|
||||
---
|
||||
|
||||
## Dashboard
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "dashboard" | What data sources feed it? How many distinct views? |
|
||||
| "charts" or "graphs" | Interactive or static? Drill-down capability? Export to CSV/PDF? |
|
||||
| "metrics" or "KPIs" | Refresh strategy -- real-time, periodic polling, or on-demand? Acceptable staleness? |
|
||||
| "admin panel" | Role-based visibility? Which actions beyond viewing (edit, delete, approve)? |
|
||||
| "mobile" or "responsive" | Simplified mobile view or full parity? Touch interactions for charts? |
|
||||
|
||||
---
|
||||
|
||||
## API Design
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "API" | REST, GraphQL, or RPC-style? Internal only or public-facing? |
|
||||
| "endpoints" or "routes" | Versioning strategy (URL path, header, query param)? Breaking change policy? |
|
||||
| "pagination" | Cursor-based or offset? Expected result set sizes? Stable ordering guarantee? |
|
||||
| "rate limiting" | Per-user, per-IP, or per-API-key? Burst allowance? How to communicate limits to clients? |
|
||||
| "errors" | Structured error format? Error codes vs. messages? How much detail in production errors? |
|
||||
|
||||
---
|
||||
|
||||
## Database
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "database" or "storage" | SQL or NoSQL? What drives the choice -- relational integrity, flexibility, scale? |
|
||||
| "ORM" or "queries" | ORM (which one?) or raw queries? Query builder as middle ground? |
|
||||
| "migrations" | Migration tool? Rollback strategy? How do you handle data migrations vs. schema migrations? |
|
||||
| "seeding" or "test data" | Seed data for development? Realistic fake data or minimal fixtures? |
|
||||
| "scale" or "performance" | Read/write ratio? Read replicas? Connection pooling strategy? |
|
||||
|
||||
---
|
||||
|
||||
## Search
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "search" | Full-text or exact match? Dedicated search engine (Elasticsearch, Meilisearch) or database-level? |
|
||||
| "filtering" or "facets" | Faceted filtering? How many filter dimensions? Combined filters (AND/OR)? |
|
||||
| "autocomplete" or "typeahead" | Debounce strategy? Minimum character threshold? Result ranking? |
|
||||
| "indexing" | Index size and update frequency? Real-time indexing or batch? Acceptable index lag? |
|
||||
| "fuzzy" or "typo tolerance" | Fuzzy matching? Synonym support? Language-specific stemming? |
|
||||
|
||||
---
|
||||
|
||||
## File Upload/Storage
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "upload" or "file upload" | Local filesystem or cloud (S3, GCS, Azure Blob)? Direct upload or through server? |
|
||||
| "images" or "media" | Processing pipeline -- resize, compress, thumbnail generation? Format conversion? |
|
||||
| "size limits" | Max file size? Max total storage per user? What happens when limits are hit? |
|
||||
| "CDN" | CDN for delivery? Cache invalidation for updated files? Signed URLs for access control? |
|
||||
| "documents" or "attachments" | Virus scanning? Preview generation? Versioning of uploaded files? |
|
||||
|
||||
---
|
||||
|
||||
## Caching
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "caching" or "performance" | Where to cache -- browser, CDN, application layer, database query cache? |
|
||||
| "invalidation" | Invalidation strategy -- TTL, event-driven, or manual? Cache-aside vs. write-through? |
|
||||
| "stale data" | Acceptable staleness window? Stale-while-revalidate pattern? |
|
||||
| "Redis" or "Memcached" | Cache topology -- single node or clustered? Persistence needed or pure cache? |
|
||||
| "CDN" or "edge" | Edge caching for static assets? Dynamic content at the edge? Cache key strategy? |
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "testing" or "tests" | Unit, integration, and E2E balance? Where do you invest most testing effort? |
|
||||
| "mocking" or "stubs" | Mock external services or use test containers? Database mocking strategy? |
|
||||
| "CI" or "pipeline" | Tests in CI? Parallel test execution? Test-on-PR or test-on-push? |
|
||||
| "coverage" | Coverage targets? Coverage as gate or advisory? Which metrics (line, branch, function)? |
|
||||
| "E2E" or "browser testing" | Playwright, Cypress, or other? Headed vs. headless? Visual regression testing? |
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
| User mentions | Agent probes with domain knowledge |
|
||||
|---|---|
|
||||
| "deploy" or "hosting" | Container, serverless, or traditional VM/VPS? Managed platform (Vercel, Railway) or self-hosted? |
|
||||
| "CI/CD" or "pipeline" | GitHub Actions, GitLab CI, or other? Deploy on merge to main or manual trigger? |
|
||||
| "environments" | How many environments (dev, staging, prod)? Environment parity strategy? |
|
||||
| "rollback" | Rollback strategy? Blue-green, canary, or instant rollback? Database rollback considerations? |
|
||||
| "secrets" or "config" | Secret management -- env vars, vault, or platform-native? Per-environment config strategy? |
|
||||
81
gsd-core/references/execute-mvp-tdd.md
Normal file
81
gsd-core/references/execute-mvp-tdd.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Execute-Phase — MVP+TDD Gate (Runtime Enforcement)
|
||||
|
||||
> Loaded by `execute-phase` workflow and `gsd-executor` agent only when **both** `MVP_MODE=true` AND `TDD_MODE=true` for the phase. Defines the runtime gate that blocks behavior-adding tasks until a failing-test commit exists.
|
||||
|
||||
## When this gate fires
|
||||
|
||||
- `MVP_MODE` is `true` (resolved from CLI flag → ROADMAP `**Mode:**` field → config; see `references/planner-mvp-mode.md`).
|
||||
- `TDD_MODE` is `true` (resolved from `--tdd` flag → `workflow.tdd_mode` config).
|
||||
- The current task being executed has `tdd="true"` in its `<task>` frontmatter (set by the planner per Phase 1).
|
||||
- The task's `<behavior>` block lists at least one expected behavior.
|
||||
|
||||
If any of these is false, the gate is inactive — execution proceeds normally.
|
||||
|
||||
## What the gate checks
|
||||
|
||||
For each task gated by MVP+TDD, the executor MUST verify (before running the implementation step):
|
||||
|
||||
1. **A failing-test commit exists.** Search git log on the current branch for a commit matching `test({phase}-{plan})` whose subject mentions the same plan as the current task. The commit must touch a test file (`*.test.*`, `*.spec.*`, `tests/**`).
|
||||
2. **The test was actually red.** The commit message body or the executor's recent shell history must show the test failed when first run. Acceptable evidence:
|
||||
- Commit message contains `RED:` prefix or `(RED)` tag
|
||||
- Recent terminal output shows `FAIL` or non-zero exit on the new test before any implementation commit
|
||||
3. **No implementation commit yet.** No `feat({phase}-{plan})` commit may exist for the same plan ID before the failing-test commit.
|
||||
|
||||
If any check fails, the gate trips.
|
||||
|
||||
## What "behavior-adding task" means
|
||||
|
||||
A task is behavior-adding when:
|
||||
- Its frontmatter has `tdd="true"` AND
|
||||
- Its `<behavior>` block names at least one user-visible outcome (not a config-only or doc-only task) AND
|
||||
- Its `<files>` list includes at least one source file (not exclusively docs/tests/config files such as `*.md`, `*.json`, `*.test.*`, `*.spec.*`, `*.yml`, `*.yaml`, `*.toml`, `*.ini`, `.env*`)
|
||||
|
||||
Pure documentation, configuration, or test-only tasks are skipped by this gate even when both modes are active.
|
||||
|
||||
## What happens when the gate trips
|
||||
|
||||
The executor MUST:
|
||||
|
||||
1. Halt before running the task's implementation step.
|
||||
2. Emit a structured halt report:
|
||||
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
MVP+TDD GATE TRIPPED — Plan {plan_id}, Task {task_id}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Reason: {missing_red_commit | red_commit_not_failing | feat_before_test}
|
||||
|
||||
Behavior expected to be tested:
|
||||
- {first behavior bullet}
|
||||
|
||||
Required next step:
|
||||
1. Write a failing test for the behavior above.
|
||||
2. Commit it as: test({phase}-{plan}): {short description}
|
||||
3. Re-run /gsd execute-phase
|
||||
```
|
||||
|
||||
3. Exit the current execution wave cleanly. Do NOT roll back any prior commits in the same wave.
|
||||
4. Update `STATE.md` with `last_gate_trip: {plan_id}/{task_id}` so the user can resume after writing the test.
|
||||
|
||||
## Escalation: end-of-phase TDD review under MVP+TDD
|
||||
|
||||
The existing end-of-phase TDD review (in `workflows/execute-phase.md`'s `tdd_review_checkpoint` step) is normally **advisory** — it surfaces gate violations but does not block phase completion.
|
||||
|
||||
Under MVP+TDD, escalate this to **blocking**:
|
||||
- If any TDD plan is missing a RED or GREEN commit, the executor MUST refuse to mark the phase complete.
|
||||
- The user is shown the same review table, but the verdict line reads:
|
||||
> "Phase blocked: {N} TDD plan(s) violate the RED→GREEN gate sequence under MVP+TDD. Resolve and re-run /gsd execute-phase, or override with `/gsd execute-phase {phase} --force-mvp-gate` to ship anyway."
|
||||
|
||||
The `--force-mvp-gate` flag is documented but not introduced by this plan — it is the escape hatch the spec mentions; if the user later builds it, the workflow already references the contract.
|
||||
|
||||
## What this gate does NOT do
|
||||
|
||||
- It does not enforce REFACTOR commits. REFACTOR remains optional (per `references/tdd.md`).
|
||||
- It does not check test quality (the test could be trivially passing). That's the planner's job.
|
||||
- It does not run tests. The executor only inspects git log + file system. Running tests is the implementation step's job.
|
||||
- It does not gate config-only or doc-only tasks (see "behavior-adding task" definition).
|
||||
|
||||
## Compatibility with existing TDD discipline
|
||||
|
||||
This gate is additive to `references/tdd.md`. Tasks not under MVP+TDD continue to use the existing advisory TDD discipline (RED/GREEN/REFACTOR commits with end-of-phase review checkpoint). Only the runtime gate and the blocking escalation are new.
|
||||
110
gsd-core/references/executor-examples.md
Normal file
110
gsd-core/references/executor-examples.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Executor Extended Examples
|
||||
|
||||
> Reference file for gsd-executor agent. Loaded on-demand via `@` reference.
|
||||
> For sub-200K context windows, this content is stripped from the agent prompt and available here for on-demand loading.
|
||||
|
||||
## Deviation Rule Examples
|
||||
|
||||
### Rule 1 — Auto-fix bugs
|
||||
|
||||
**Examples of Rule 1 triggers:**
|
||||
- Wrong queries returning incorrect data
|
||||
- Logic errors in conditionals
|
||||
- Type errors and type mismatches
|
||||
- Null pointer exceptions / undefined access
|
||||
- Broken validation (accepts invalid input)
|
||||
- Security vulnerabilities (XSS, SQL injection)
|
||||
- Race conditions in async code
|
||||
- Memory leaks from uncleaned resources
|
||||
|
||||
### Rule 2 — Auto-add missing critical functionality
|
||||
|
||||
**Examples of Rule 2 triggers:**
|
||||
- Missing error handling (unhandled promise rejections, no try/catch on I/O)
|
||||
- No input validation on user-facing endpoints
|
||||
- Missing null checks before property access
|
||||
- No auth on protected routes
|
||||
- Missing authorization checks (user can access other users' data)
|
||||
- No CSRF/CORS configuration
|
||||
- No rate limiting on public endpoints
|
||||
- Missing DB indexes on frequently queried columns
|
||||
- No error logging (failures silently swallowed)
|
||||
|
||||
### Rule 3 — Auto-fix blocking issues
|
||||
|
||||
**Examples of Rule 3 triggers:**
|
||||
- Missing dependency not in package.json
|
||||
- Wrong types preventing compilation
|
||||
- Broken imports (wrong path, wrong export name)
|
||||
- Missing env var required at runtime
|
||||
- DB connection error (wrong URL, missing credentials)
|
||||
- Build config error (wrong entry point, missing loader)
|
||||
- Missing referenced file (import points to non-existent module)
|
||||
- Circular dependency preventing module load
|
||||
|
||||
### Rule 4 — Ask about architectural changes
|
||||
|
||||
**Examples of Rule 4 triggers:**
|
||||
- New DB table (not just adding a column)
|
||||
- Major schema changes (renaming tables, changing relationships)
|
||||
- New service layer (adding a queue, cache, or message bus)
|
||||
- Switching libraries/frameworks (e.g., replacing Express with Fastify)
|
||||
- Changing auth approach (switching from session to JWT)
|
||||
- New infrastructure (adding Redis, S3, etc.)
|
||||
- Breaking API changes (removing or renaming endpoints)
|
||||
|
||||
## Edge Case Decision Guide
|
||||
|
||||
| Scenario | Rule | Rationale |
|
||||
|----------|------|-----------|
|
||||
| Missing validation on input | Rule 2 | Security requirement |
|
||||
| Crashes on null input | Rule 1 | Bug — incorrect behavior |
|
||||
| Need new database table | Rule 4 | Architectural decision |
|
||||
| Need new column on existing table | Rule 1 or 2 | Depends on context |
|
||||
| Pre-existing linting warnings | Out of scope | Not caused by current task |
|
||||
| Unrelated test failures | Out of scope | Not caused by current task |
|
||||
|
||||
**Decision heuristic:** "Does this affect correctness, security, or ability to complete the current task?"
|
||||
- YES → Rules 1-3 (fix automatically)
|
||||
- MAYBE → Rule 4 (ask the user)
|
||||
- NO → Out of scope (log to deferred-items.md)
|
||||
|
||||
## Checkpoint Examples
|
||||
|
||||
### Good checkpoint placement
|
||||
|
||||
```xml
|
||||
<!-- Automate everything, then verify at the end -->
|
||||
<task type="auto">Create database schema</task>
|
||||
<task type="auto">Create API endpoints</task>
|
||||
<task type="auto">Create UI components</task>
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Complete auth flow (schema + API + UI)</what-built>
|
||||
<how-to-verify>
|
||||
1. Visit http://localhost:3000/register
|
||||
2. Create account with test@example.com
|
||||
3. Log in with those credentials
|
||||
4. Verify dashboard loads with user name
|
||||
</how-to-verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
### Bad checkpoint placement
|
||||
|
||||
```xml
|
||||
<!-- Too many checkpoints — causes verification fatigue -->
|
||||
<task type="auto">Create schema</task>
|
||||
<task type="checkpoint:human-verify">Check schema</task>
|
||||
<task type="auto">Create API</task>
|
||||
<task type="checkpoint:human-verify">Check API</task>
|
||||
<task type="auto">Create UI</task>
|
||||
<task type="checkpoint:human-verify">Check UI</task>
|
||||
```
|
||||
|
||||
### Auth gate handling
|
||||
|
||||
When an auth error occurs during `type="auto"` execution:
|
||||
1. Recognize it as an auth gate (not a bug) — indicators: "Not authenticated", "401", "403", "Please run X login"
|
||||
2. STOP the current task
|
||||
3. Return a `checkpoint:human-action` with exact auth steps
|
||||
4. In SUMMARY.md, document auth gates as normal flow, not deviations
|
||||
73
gsd-core/references/few-shot-examples/plan-checker.md
Normal file
73
gsd-core/references/few-shot-examples/plan-checker.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
component: plan-checker
|
||||
version: 1
|
||||
last_calibrated: 2026-03-24
|
||||
---
|
||||
|
||||
# Plan-Checker Few-Shot Examples
|
||||
|
||||
## Positive Examples
|
||||
|
||||
### Example 1: BLOCKER flagged for vague task action missing file and function names
|
||||
|
||||
**Input:** Plan task with action: "Implement the authentication feature for the API routes."
|
||||
|
||||
**Output:**
|
||||
|
||||
> ```yaml
|
||||
> issues:
|
||||
> - dimension: task_completeness
|
||||
> severity: BLOCKER
|
||||
> finding: "Task T1 action says 'implement the authentication feature' without naming target files, functions to create, or middleware to apply. Executor cannot determine what to build."
|
||||
> affected_field: "<action>"
|
||||
> suggested_fix: "Specify: create authMiddleware in src/middleware/auth.js, apply to routes in src/routes/api.js lines 12-45, verify with integration test"
|
||||
> ```
|
||||
|
||||
**Why this is good:** The checker cited the specific dimension (task_completeness), quoted the problematic text, explained why it is a blocker (executor cannot determine what to build), and gave a concrete fix with file paths and function names. The finding is actionable -- the planner knows exactly what to add.
|
||||
|
||||
### Example 2: BLOCKER for same-wave file conflict between two plans
|
||||
|
||||
**Input:** Two plans in wave 1 -- Plan 01 modifies `gsd-core/workflows/execute-phase.md`, Plan 02 also modifies `gsd-core/workflows/execute-phase.md`. No `depends_on` declared.
|
||||
|
||||
**Output:**
|
||||
|
||||
> ```yaml
|
||||
> issues:
|
||||
> - dimension: dependency_correctness
|
||||
> severity: BLOCKER
|
||||
> finding: "Plans 01 and 02 both modify gsd-core/workflows/execute-phase.md in wave 1 with no depends_on relationship. Concurrent execution will cause merge conflicts or lost changes."
|
||||
> affected_field: "files_modified"
|
||||
> suggested_fix: "Either move Plan 02 to wave 2 with depends_on: ['01'] or consolidate the file changes into a single plan"
|
||||
> ```
|
||||
|
||||
**Why this is good:** The checker identified a real structural problem -- two plans modifying the same file in the same wave without a dependency relationship. It cited dependency_correctness, named both plans, the conflicting file, and provided two alternative fixes.
|
||||
|
||||
## Negative Examples
|
||||
|
||||
### Example 1: All dimensions pass when verify commands are missing
|
||||
|
||||
**Input:** Plan with 3 tasks. Task T2 has `<verify></verify>` (empty). Task T3 has `<verify>echo "done"</verify>` (trivial, cannot distinguish pass from fail).
|
||||
|
||||
**Output:**
|
||||
|
||||
> ## CHECK PASSED
|
||||
> Plans: 1 | Tasks: 3 | Dimensions: 10 | Issues: 0
|
||||
|
||||
**Why this is bad:** The checker missed two violations. verification_derivation requires verify commands to be runnable and test actual output -- an empty verify block is a BLOCKER. Verify commands must distinguish pass from fail -- `echo "done"` always returns 0 regardless of implementation state. Both should have been flagged.
|
||||
|
||||
### Example 2: False positive INFO for a correctly-sized plan
|
||||
|
||||
**Input:** Plan with 3 tasks, 6 unique files, 1 dependency. All within limits.
|
||||
|
||||
**Output:**
|
||||
|
||||
> ```yaml
|
||||
> issues:
|
||||
> - dimension: scope_sanity
|
||||
> severity: INFO
|
||||
> finding: "Plan has 3 tasks -- consider splitting into smaller plans for faster iteration"
|
||||
> affected_field: "task count"
|
||||
> suggested_fix: "Split tasks into separate plans"
|
||||
> ```
|
||||
|
||||
**Why this is bad:** The checker flagged a non-issue. scope_sanity allows 2-3 tasks per plan -- 3 tasks is within limits. The checker applied a personal preference ("smaller is better") rather than the documented threshold. This wastes planner time on false positives and erodes trust in the checker's judgment. A correct check would produce no issue for this plan.
|
||||
109
gsd-core/references/few-shot-examples/verifier.md
Normal file
109
gsd-core/references/few-shot-examples/verifier.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
component: verifier
|
||||
version: 2
|
||||
last_calibrated: 2026-03-25
|
||||
calibration_source: "Adapted from thinking-partner verification corpus"
|
||||
---
|
||||
|
||||
# Verifier Few-Shot Examples
|
||||
|
||||
## Positive Examples
|
||||
|
||||
### Example 1: Thorough multi-level artifact verification with real gap discovery
|
||||
|
||||
**Input:** Must-have artifact: `gsd-core/workflows/context-bridge.md: >50 lines`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **L1 (Existence):** EXISTS -- `gsd-core/workflows/context-bridge.md` found, 187 lines.
|
||||
> **L2 (Substantive):** SUBSTANTIVE -- No TODO/FIXME markers, 4 defined sections (`updateContextTier`, `getContextBudget`, `injectContextWarning`, `resetTierState`), non-trivial logic with config reads and threshold calculations.
|
||||
> **L3 (Wired):** WIRED -- Referenced by `gsd-core/workflows/execute-phase.md` at step 3. Called by `agents/gsd-executor.md` via @-reference include. Arguments verified: receives planning directory path matching the expected parameter.
|
||||
> **Status: PASSED**
|
||||
|
||||
**Why this is good:** The verifier checked all three levels independently with specific evidence at each level -- file path, line count, exported symbols, import location, and argument verification. It did not stop at "file exists" but traced wiring through to actual usage with correct arguments.
|
||||
|
||||
### Example 2: Correct FAILED classification with grep evidence
|
||||
|
||||
**Input:** Must-have truth: `validate-commit.js rejects commits missing scope parentheses`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **Method:** Ran `grep -n "scope" gsd-core/bin/validate-commit.js` to locate scope validation logic.
|
||||
> **Evidence:** Lines 34-41 show regex `/^(feat|fix|refactor|test|docs|chore|wip)\(/` which requires opening paren after type. However, no test for MISSING closing paren exists -- the regex accepts `feat(: description` (missing scope content and closing paren).
|
||||
> **Ran:** `echo "feat(: test" | node gsd-core/bin/validate-commit.js` -- exit code 0 (accepted).
|
||||
> **Status: FAILED** -- Commit messages with empty scope `feat(: desc)` are accepted. The truth "rejects commits missing scope parentheses" does not hold for empty-scope edge case.
|
||||
|
||||
**Why this is good:** The verifier did not trust the code's intent -- it ran an actual test with an edge case input and reported the specific failure. Evidence includes the regex, the test command, the exit code, and why the truth does not hold.
|
||||
|
||||
### Example 3: Catching missing wiring (calibration-derived gap pattern)
|
||||
|
||||
**Input:** Must-have key_link: `check-subagent-output.js imports and calls feedback-loop.js extractFeedback()`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **Method:** Ran `grep -n "feedback-loop\|extractFeedback" gsd-core/bin/check-subagent-output.js`.
|
||||
> **Evidence:** Zero matches. The file `feedback-loop.js` exists (172 lines, substantive), and `tests/feedback-loop.test.js` passes (229 lines). But `check-subagent-output.js` never imports or calls it.
|
||||
> **Cross-check:** `grep -rn "require.*feedback-loop" gsd-core/bin/` returns zero results across all scripts.
|
||||
> **Status: FAILED** -- The artifact exists and is tested, but is completely orphaned. The key_link "imports and calls" does not hold. This is a **missing wiring** gap.
|
||||
|
||||
**Why this is good:** The verifier caught a common calibration pattern: code that exists, is tested, but is never actually wired into the system. L1 and L2 pass, but L3 (wiring) fails. This pattern accounts for 37% of all gaps found in calibration corpus.
|
||||
|
||||
### Example 4: Catching missing config schema entries (calibration-derived gap pattern)
|
||||
|
||||
**Input:** Must-have truth: `Config toggles features.architecture_graph and features.architecture_guard exist with defaults`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **Method:** Ran `grep "architecture_graph\|architecture_guard" gsd-core/bin/lib/config-schema.json`.
|
||||
> **Evidence:** Zero matches in schema. However, `grep "architecture" gsd-core/bin/lib/config.cjs` shows both flags in CONFIG_DEFAULTS (lines 426, 428).
|
||||
> **Gap:** Defaults exist in code but schema validation doesn't know about them. `configValidate()` would strip these fields on load, making the defaults unreachable.
|
||||
> **Status: FAILED** -- Config flags work in code but are invisible to schema validation. This is a **missing wiring** gap between config layers.
|
||||
|
||||
**Why this is good:** The verifier checked multiple config layers (schema vs defaults vs code) rather than just one. Config wiring requires schema + defaults + code to agree -- checking only one layer misses layer-mismatch bugs.
|
||||
|
||||
### Example 5: Distinguishing planning gaps from execution failures
|
||||
|
||||
**Input:** Must-have truth: `All MSYS regex patterns consolidated into shared module`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **Method:** Ran `grep -rn "\/\[a-zA-Z\]\/" gsd-core/bin/` to find inline MSYS regex.
|
||||
> **Evidence:** 2 matches in `commands/gsd/misc.md` (lines 26, 487). These were NOT in the original plan scope -- Phase 148 extracted code into misc.md AFTER Phase 149's plan was written.
|
||||
> **Assessment:** The executor correctly completed all planned tasks. The gap is a **planning ordering issue**, not an execution failure.
|
||||
> **Status: PASS_WITH_NOTES** -- Executor did what was planned. Unconsolidated regex noted as follow-up, not as a failure of this phase.
|
||||
|
||||
**Why this is good:** The verifier distinguished between what was planned vs what exists now. Code that changed AFTER plan creation is a planning gap, not an executor failure. This prevents false FAIL verdicts on correctly-executed work.
|
||||
|
||||
## Calibration-Derived Gap Patterns
|
||||
|
||||
Based on analysis of verification corpus (80% pass rate, 8 gaps):
|
||||
|
||||
| Pattern | Count | % of Gaps | What to Check |
|
||||
|---------|-------|-----------|---------------|
|
||||
| Missing wiring | 3 | 37% | File exists + tested but never imported/called by consumer |
|
||||
| Missing tests | 2 | 25% | Feature works but test file excluded from CI or never runs |
|
||||
| Other | 3 | 38% | Config layer mismatches, planning ordering issues, schema gaps |
|
||||
|
||||
## Negative Examples
|
||||
|
||||
### Example 1: Blanket pass with no per-criterion evidence
|
||||
|
||||
**Input:** Must-haves: 5 truths, 3 artifacts, 2 key_links from plan frontmatter.
|
||||
|
||||
**Output:**
|
||||
|
||||
> All must-haves have been verified. The implementation matches the plan requirements. Files exist and are properly connected. Status: PASSED.
|
||||
> must_haves_checked: 10, must_haves_passed: 10
|
||||
|
||||
**Why this is bad:** No individual must-have is listed or checked. No file paths, no line numbers, no grep output, no level-by-level breakdown. The verifier restated the must-haves as passing without showing any evidence. This would miss stubs, orphaned exports, and broken wiring.
|
||||
|
||||
### Example 2: File existence check without substance or wiring verification
|
||||
|
||||
**Input:** Must-have artifact: `gsd-core/bin/lib/audit-checks/index.cjs: >100 lines`
|
||||
|
||||
**Output:**
|
||||
|
||||
> **L1 (Existence):** EXISTS -- File found at `gsd-core/bin/lib/audit-checks/index.cjs`, 142 lines.
|
||||
> **Status: PASSED**
|
||||
|
||||
**Why this is bad:** The verifier stopped at Level 1. The file has 142 lines but could contain `// TODO: implement all checks` with stub functions returning empty objects. Level 2 (substantive) and Level 3 (wired) were skipped entirely. A file that exists but is never imported or contains only placeholder code should not pass.
|
||||
100
gsd-core/references/gate-prompts.md
Normal file
100
gsd-core/references/gate-prompts.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Gate Prompt Patterns
|
||||
|
||||
Reusable prompt patterns for structured gate checks in workflows and agents.
|
||||
|
||||
**For checkpoint box format details, see `references/ui-brand.md`** -- checkpoint boxes use double-line border drawing with 62-character inner width.
|
||||
|
||||
## Rules
|
||||
|
||||
- `header` must be max 12 characters
|
||||
- `multiSelect` is always `false` for gate checks
|
||||
- Always handle the "Other" case (user typed a freeform response instead of selecting)
|
||||
- Max 4 options per prompt -- if more are needed, use a 2-step flow
|
||||
|
||||
---
|
||||
|
||||
## Pattern: approve-revise-abort
|
||||
3-option gate for plan approval, gap-closure approval.
|
||||
- question: "Approve these {noun}?"
|
||||
- header: "Approve?"
|
||||
- options: Approve | Request changes | Abort
|
||||
|
||||
## Pattern: yes-no
|
||||
Simple 2-option confirmation for re-planning, rebuild, replace plans, commit.
|
||||
- question: "{Specific question about the action}"
|
||||
- header: "Confirm"
|
||||
- options: Yes | No
|
||||
|
||||
## Pattern: stale-continue
|
||||
2-option refresh gate for staleness warnings, timestamp freshness.
|
||||
- question: "{Artifact} may be outdated. Refresh or continue?"
|
||||
- header: "Stale"
|
||||
- options: Refresh | Continue anyway
|
||||
|
||||
## Pattern: yes-no-pick
|
||||
3-option selection for seed selection, item inclusion.
|
||||
- question: "Include {items} in planning?"
|
||||
- header: "Include?"
|
||||
- options: Yes, all | Let me pick | No
|
||||
|
||||
## Pattern: multi-option-failure
|
||||
4-option failure handler for build failures.
|
||||
- question: "Plan {id} failed. How should we proceed?"
|
||||
- header: "Failed"
|
||||
- options: Retry | Skip | Rollback | Abort
|
||||
|
||||
## Pattern: multi-option-escalation
|
||||
4-option escalation for review escalation (max retries exceeded).
|
||||
- question: "Phase {N} has failed verification {attempt} times. How should we proceed?"
|
||||
- header: "Escalate"
|
||||
- options: Accept gaps | Re-plan (via /gsd:plan-phase) | Debug (via /gsd:debug) | Retry
|
||||
|
||||
## Pattern: multi-option-gaps
|
||||
4-option gap handler for review gaps-found.
|
||||
- question: "{count} verification gaps need attention. How should we proceed?"
|
||||
- header: "Gaps"
|
||||
- options: Auto-fix | Override | Manual | Skip
|
||||
|
||||
## Pattern: multi-option-priority
|
||||
4-option priority selection for milestone gap priority.
|
||||
- question: "Which gaps should we address?"
|
||||
- header: "Priority"
|
||||
- options: Must-fix only | Must + should | Everything | Let me pick
|
||||
|
||||
## Pattern: toggle-confirm
|
||||
2-option confirmation for enabling/disabling boolean features.
|
||||
- question: "Enable {feature_name}?"
|
||||
- header: "Toggle"
|
||||
- options: Enable | Disable
|
||||
|
||||
## Pattern: action-routing
|
||||
Up to 4 suggested next actions with selection (status, resume workflows).
|
||||
- question: "What would you like to do next?"
|
||||
- header: "Next Step"
|
||||
- options: {primary action} | {alternative 1} | {alternative 2} | Something else
|
||||
- Note: Dynamically generate options from workflow state. Always include "Something else" as last option.
|
||||
|
||||
## Pattern: scope-confirm
|
||||
3-option confirmation for quick task scope validation.
|
||||
- question: "This task looks complex. Proceed as quick task or use full planning?"
|
||||
- header: "Scope"
|
||||
- options: Quick task | Full plan (via /gsd:plan-phase) | Revise
|
||||
|
||||
## Pattern: depth-select
|
||||
3-option depth selection for planning workflow preferences.
|
||||
- question: "How thorough should planning be?"
|
||||
- header: "Depth"
|
||||
- options: Quick (3-5 phases, skip research) | Standard (5-8 phases, default) | Comprehensive (8-12 phases, deep research)
|
||||
|
||||
## Pattern: context-handling
|
||||
3-option handler for existing CONTEXT.md in discuss workflow.
|
||||
- question: "Phase {N} already has a CONTEXT.md. How should we handle it?"
|
||||
- header: "Context"
|
||||
- options: Overwrite | Append | Cancel
|
||||
|
||||
## Pattern: gray-area-option
|
||||
Dynamic template for presenting gray area choices in discuss workflow.
|
||||
- question: "{Gray area title}"
|
||||
- header: "Decision"
|
||||
- options: {Option 1} | {Option 2} | Let Claude decide
|
||||
- Note: Options generated at runtime. Always include "Let Claude decide" as last option.
|
||||
70
gsd-core/references/gates.md
Normal file
70
gsd-core/references/gates.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Gates Taxonomy
|
||||
|
||||
Canonical gate types used across GSD workflows. Every validation checkpoint maps to one of these four types.
|
||||
|
||||
---
|
||||
|
||||
## Gate Types
|
||||
|
||||
### Pre-flight Gate
|
||||
**Purpose:** Validates preconditions before starting an operation.
|
||||
**Behavior:** Blocks entry if conditions unmet. No partial work created.
|
||||
**Recovery:** Fix the missing precondition, then retry.
|
||||
**Examples:**
|
||||
- Plan-phase checks for REQUIREMENTS.md before planning
|
||||
- Execute-phase validates PLAN.md exists before execution
|
||||
- Discuss-phase confirms phase exists in ROADMAP.md
|
||||
|
||||
### Revision Gate
|
||||
**Purpose:** Evaluates output quality and routes to revision if insufficient.
|
||||
**Behavior:** Loops back to producer with specific feedback. Bounded by iteration cap.
|
||||
**Recovery:** Producer addresses feedback; checker re-evaluates. The loop also escalates early if issue count does not decrease between consecutive iterations (stall detection). After max iterations, escalates unconditionally.
|
||||
**Examples:**
|
||||
- Plan-checker reviewing PLAN.md (max 3 iterations)
|
||||
- Verifier checking phase deliverables against success criteria
|
||||
|
||||
### Escalation Gate
|
||||
**Purpose:** Surfaces unresolvable issues to the developer for a decision.
|
||||
**Behavior:** Pauses workflow, presents options, waits for human input.
|
||||
**Recovery:** Developer chooses action; workflow resumes on selected path.
|
||||
**Examples:**
|
||||
- Revision loop exhausted after 3 iterations
|
||||
- Merge conflict during worktree cleanup
|
||||
- Ambiguous requirement needing clarification
|
||||
|
||||
### Abort Gate
|
||||
**Purpose:** Terminates the operation to prevent damage or waste.
|
||||
**Behavior:** Stops immediately, preserves state, reports reason.
|
||||
**Recovery:** Developer investigates root cause, fixes, restarts from checkpoint.
|
||||
**Examples:**
|
||||
- Context window critically low during execution
|
||||
- STATE.md in error state blocking /gsd-next
|
||||
- Verification finds critical missing deliverables
|
||||
|
||||
---
|
||||
|
||||
## Gate Matrix
|
||||
|
||||
| Workflow | Phase | Gate Type | Artifacts Checked | Failure Behavior |
|
||||
|----------|-------|-----------|-------------------|------------------|
|
||||
| plan-phase | Entry | Pre-flight | REQUIREMENTS.md, ROADMAP.md | Block with missing-file message |
|
||||
| plan-phase | Step 12 | Revision | PLAN.md quality | Loop to planner (max 3) |
|
||||
| plan-phase | Post-revision | Escalation | Unresolved issues | Surface to developer |
|
||||
| execute-phase | Entry | Pre-flight | PLAN.md | Block with missing-plan message |
|
||||
| execute-phase | Completion | Revision | SUMMARY.md completeness | Re-run incomplete tasks |
|
||||
| verify-work | Entry | Pre-flight | SUMMARY.md | Block with missing-summary |
|
||||
| verify-work | Evaluation | Escalation | Failed criteria | Surface gaps to developer |
|
||||
| next | Entry | Abort | Error state, checkpoints | Stop with diagnostic |
|
||||
|
||||
---
|
||||
|
||||
## Implementing Gates
|
||||
|
||||
Use this taxonomy when designing or auditing workflow validation points:
|
||||
|
||||
- **Pre-flight** gates belong at workflow entry points. They are cheap, deterministic checks that prevent wasted work. If you can verify a precondition with a file-existence check or a config read, use a pre-flight gate.
|
||||
- **Revision** gates belong after a producer step where quality varies. Always pair them with an iteration cap to prevent infinite loops. The cap should reflect the cost of each iteration -- expensive operations get fewer retries.
|
||||
- **Escalation** gates belong wherever automated resolution is impossible or ambiguous. They are the safety valve between revision loops and abort. Present the developer with clear options and enough context to decide.
|
||||
- **Abort** gates belong at points where continuing would cause damage, waste significant resources, or produce meaningless output. They should preserve state so work can resume after the root cause is fixed.
|
||||
|
||||
**Selection heuristic:** Start with pre-flight. If the check happens after work is produced, it is a revision gate. If the revision loop cannot resolve the issue, escalate. If continuing is dangerous, abort.
|
||||
298
gsd-core/references/git-integration.md
Normal file
298
gsd-core/references/git-integration.md
Normal file
@@ -0,0 +1,298 @@
|
||||
<overview>
|
||||
Git integration for GSD framework.
|
||||
</overview>
|
||||
|
||||
<core_principle>
|
||||
|
||||
**Commit outcomes, not process.**
|
||||
|
||||
The git log should read like a changelog of what shipped, not a diary of planning activity.
|
||||
</core_principle>
|
||||
|
||||
<commit_points>
|
||||
|
||||
| Event | Commit? | Why |
|
||||
| ----------------------- | ------- | ------------------------------------------------ |
|
||||
| BRIEF + ROADMAP created | YES | Project initialization |
|
||||
| PLAN.md created | NO | Intermediate - commit with plan completion |
|
||||
| RESEARCH.md created | NO | Intermediate |
|
||||
| DISCOVERY.md created | NO | Intermediate |
|
||||
| **Task completed** | YES | Atomic unit of work (1 commit per task) |
|
||||
| **Plan completed** | YES | Metadata commit (SUMMARY + STATE + ROADMAP) |
|
||||
| Handoff created | YES | WIP state preserved |
|
||||
|
||||
</commit_points>
|
||||
|
||||
<git_check>
|
||||
|
||||
```bash
|
||||
[ -d .git ] && echo "GIT_EXISTS" || echo "NO_GIT"
|
||||
```
|
||||
|
||||
If NO_GIT: Run `git init` silently. GSD projects always get their own repo.
|
||||
</git_check>
|
||||
|
||||
<commit_formats>
|
||||
|
||||
<format name="initialization">
|
||||
## Project Initialization (brief + roadmap together)
|
||||
|
||||
```
|
||||
docs: initialize [project-name] ([N] phases)
|
||||
|
||||
[One-liner from PROJECT.md]
|
||||
|
||||
Phases:
|
||||
1. [phase-name]: [goal]
|
||||
2. [phase-name]: [goal]
|
||||
3. [phase-name]: [goal]
|
||||
```
|
||||
|
||||
What to commit:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "docs: initialize [project-name] ([N] phases)" --files .planning/
|
||||
```
|
||||
|
||||
</format>
|
||||
|
||||
<format name="task-completion">
|
||||
## Task Completion (During Plan Execution)
|
||||
|
||||
Each task gets its own commit immediately after completion.
|
||||
|
||||
> **Parallel agents:** When running as a parallel executor (spawned by execute-phase),
|
||||
> run commits normally — let pre-commit hooks run. Do NOT pass `--no-verify` by default
|
||||
> (#2924). Hooks should fire on the introducing commit; silent bypass violates project
|
||||
> CLAUDE.md guidance. If a project explicitly opts out via
|
||||
> `workflow.worktree_skip_hooks=true`, the orchestrator surfaces that flag in the
|
||||
> executor prompt; absent that signal, hooks run normally.
|
||||
|
||||
```
|
||||
{type}({phase}-{plan}): {task-name}
|
||||
|
||||
- [Key change 1]
|
||||
- [Key change 2]
|
||||
- [Key change 3]
|
||||
```
|
||||
|
||||
**Commit types:**
|
||||
- `feat` - New feature/functionality
|
||||
- `fix` - Bug fix
|
||||
- `test` - Test-only (TDD RED phase)
|
||||
- `refactor` - Code cleanup (TDD REFACTOR phase)
|
||||
- `perf` - Performance improvement
|
||||
- `chore` - Dependencies, config, tooling
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Standard task
|
||||
git add src/api/auth.ts src/types/user.ts
|
||||
git commit -m "feat(08-02): create user registration endpoint
|
||||
|
||||
- POST /auth/register validates email and password
|
||||
- Checks for duplicate users
|
||||
- Returns JWT token on success
|
||||
"
|
||||
|
||||
# TDD task - RED phase
|
||||
git add src/__tests__/jwt.test.ts
|
||||
git commit -m "test(07-02): add failing test for JWT generation
|
||||
|
||||
- Tests token contains user ID claim
|
||||
- Tests token expires in 1 hour
|
||||
- Tests signature verification
|
||||
"
|
||||
|
||||
# TDD task - GREEN phase
|
||||
git add src/utils/jwt.ts
|
||||
git commit -m "feat(07-02): implement JWT generation
|
||||
|
||||
- Uses jose library for signing
|
||||
- Includes user ID and expiry claims
|
||||
- Signs with HS256 algorithm
|
||||
"
|
||||
```
|
||||
|
||||
</format>
|
||||
|
||||
<format name="plan-completion">
|
||||
## Plan Completion (After All Tasks Done)
|
||||
|
||||
After all tasks committed, one final metadata commit captures plan completion.
|
||||
|
||||
```
|
||||
docs({phase}-{plan}): complete [plan-name] plan
|
||||
|
||||
Tasks completed: [N]/[N]
|
||||
- [Task 1 name]
|
||||
- [Task 2 name]
|
||||
- [Task 3 name]
|
||||
|
||||
SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
```
|
||||
|
||||
What to commit:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md
|
||||
```
|
||||
|
||||
**Note:** Code files NOT included - already committed per-task.
|
||||
|
||||
</format>
|
||||
|
||||
<format name="handoff">
|
||||
## Handoff (WIP)
|
||||
|
||||
```
|
||||
wip: [phase-name] paused at task [X]/[Y]
|
||||
|
||||
Current: [task name]
|
||||
[If blocked:] Blocked: [reason]
|
||||
```
|
||||
|
||||
What to commit:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/
|
||||
```
|
||||
|
||||
</format>
|
||||
</commit_formats>
|
||||
|
||||
<example_log>
|
||||
|
||||
**Old approach (per-plan commits):**
|
||||
```
|
||||
a7f2d1 feat(checkout): Stripe payments with webhook verification
|
||||
3e9c4b feat(products): catalog with search, filters, and pagination
|
||||
8a1b2c feat(auth): JWT with refresh rotation using jose
|
||||
5c3d7e feat(foundation): Next.js 15 + Prisma + Tailwind scaffold
|
||||
2f4a8d docs: initialize ecommerce-app (5 phases)
|
||||
```
|
||||
|
||||
**New approach (per-task commits):**
|
||||
```
|
||||
# Phase 04 - Checkout
|
||||
1a2b3c docs(04-01): complete checkout flow plan
|
||||
4d5e6f feat(04-01): add webhook signature verification
|
||||
7g8h9i feat(04-01): implement payment session creation
|
||||
0j1k2l feat(04-01): create checkout page component
|
||||
|
||||
# Phase 03 - Products
|
||||
3m4n5o docs(03-02): complete product listing plan
|
||||
6p7q8r feat(03-02): add pagination controls
|
||||
9s0t1u feat(03-02): implement search and filters
|
||||
2v3w4x feat(03-01): create product catalog schema
|
||||
|
||||
# Phase 02 - Auth
|
||||
5y6z7a docs(02-02): complete token refresh plan
|
||||
8b9c0d feat(02-02): implement refresh token rotation
|
||||
1e2f3g test(02-02): add failing test for token refresh
|
||||
4h5i6j docs(02-01): complete JWT setup plan
|
||||
7k8l9m feat(02-01): add JWT generation and validation
|
||||
0n1o2p chore(02-01): install jose library
|
||||
|
||||
# Phase 01 - Foundation
|
||||
3q4r5s docs(01-01): complete scaffold plan
|
||||
6t7u8v feat(01-01): configure Tailwind and globals
|
||||
9w0x1y feat(01-01): set up Prisma with database
|
||||
2z3a4b feat(01-01): create Next.js 15 project
|
||||
|
||||
# Initialization
|
||||
5c6d7e docs: initialize ecommerce-app (5 phases)
|
||||
```
|
||||
|
||||
Each plan produces 2-4 commits (tasks + metadata). Clear, granular, bisectable.
|
||||
|
||||
</example_log>
|
||||
|
||||
<anti_patterns>
|
||||
|
||||
**Still don't commit (intermediate artifacts):**
|
||||
- PLAN.md creation (commit with plan completion)
|
||||
- RESEARCH.md (intermediate)
|
||||
- DISCOVERY.md (intermediate)
|
||||
- Minor planning tweaks
|
||||
- "Fixed typo in roadmap"
|
||||
|
||||
**Do commit (outcomes):**
|
||||
- Each task completion (feat/fix/test/refactor)
|
||||
- Plan completion metadata (docs)
|
||||
- Project initialization (docs)
|
||||
|
||||
**Key principle:** Commit working code and shipped outcomes, not planning process.
|
||||
|
||||
</anti_patterns>
|
||||
|
||||
<commit_strategy_rationale>
|
||||
|
||||
## Why Per-Task Commits?
|
||||
|
||||
**Context engineering for AI:**
|
||||
- Git history becomes primary context source for future Claude sessions
|
||||
- `git log --grep="{phase}-{plan}"` shows all work for a plan
|
||||
- `git diff <hash>^..<hash>` shows exact changes per task
|
||||
- Less reliance on parsing SUMMARY.md = more context for actual work
|
||||
|
||||
**Failure recovery:**
|
||||
- Task 1 committed ✅, Task 2 failed ❌
|
||||
- Claude in next session: sees task 1 complete, can retry task 2
|
||||
- Can `git reset --hard` to last successful task
|
||||
|
||||
**Debugging:**
|
||||
- `git bisect` finds exact failing task, not just failing plan
|
||||
- `git blame` traces line to specific task context
|
||||
- Each commit is independently revertable
|
||||
|
||||
**Observability:**
|
||||
- Solo developer + Claude workflow benefits from granular attribution
|
||||
- Atomic commits are git best practice
|
||||
- "Commit noise" irrelevant when consumer is Claude, not humans
|
||||
|
||||
</commit_strategy_rationale>
|
||||
|
||||
<sub_repos_support>
|
||||
|
||||
## Multi-Repo Workspace Support (sub_repos)
|
||||
|
||||
For workspaces with separate git repos (e.g., `backend/`, `frontend/`, `shared/`), GSD routes commits to each repo independently.
|
||||
|
||||
### Configuration
|
||||
|
||||
In `.planning/config.json`, list sub-repo directories under `planning.sub_repos`:
|
||||
|
||||
```json
|
||||
{
|
||||
"planning": {
|
||||
"commit_docs": false,
|
||||
"sub_repos": ["backend", "frontend", "shared"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set `commit_docs: false` so planning docs stay local and are not committed to any sub-repo.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Auto-detection:** During `/gsd:new-project`, directories with their own `.git` folder are detected and offered for selection as sub-repos. On subsequent runs, `loadConfig` auto-syncs the `sub_repos` list with the filesystem — adding newly created repos and removing deleted ones. This means `config.json` may be rewritten automatically when repos change on disk.
|
||||
2. **File grouping:** Code files are grouped by their sub-repo prefix (e.g., `backend/src/api/users.ts` belongs to the `backend/` repo).
|
||||
3. **Independent commits:** Each sub-repo receives its own atomic commit via `gsd-tools.cjs commit-to-subrepo`. File paths are made relative to the sub-repo root before staging.
|
||||
4. **Planning stays local:** The `.planning/` directory is not committed; it acts as cross-repo coordination.
|
||||
|
||||
### Commit Routing
|
||||
|
||||
Instead of the standard `commit` command, use `commit-to-subrepo` when `sub_repos` is configured:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit-to-subrepo "feat(02-01): add user API" \
|
||||
--files backend/src/api/users.ts backend/src/types/user.ts frontend/src/components/UserForm.tsx
|
||||
```
|
||||
|
||||
This stages `src/api/users.ts` and `src/types/user.ts` in the `backend/` repo, and `src/components/UserForm.tsx` in the `frontend/` repo, then commits each independently with the same message.
|
||||
|
||||
Files that don't match any configured sub-repo are reported as unmatched.
|
||||
|
||||
</sub_repos_support>
|
||||
40
gsd-core/references/git-planning-commit.md
Normal file
40
gsd-core/references/git-planning-commit.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Git Planning Commit
|
||||
|
||||
Commit planning artifacts via `gsd-tools query commit`, which checks `commit_docs` config and gitignore status (same behavior as legacy `gsd-tools.cjs commit`).
|
||||
|
||||
## Commit via CLI
|
||||
|
||||
Pass the message first, then file paths via `--files`. Both `commit` and `commit-to-subrepo` use `--files` to declare the paths to commit.
|
||||
|
||||
Always use this for `.planning/` files — it handles `commit_docs` and gitignore checks automatically:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "docs({scope}): {description}" --files .planning/STATE.md .planning/ROADMAP.md
|
||||
```
|
||||
|
||||
The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.planning/` is gitignored. No manual conditional checks needed.
|
||||
|
||||
## Amend previous commit
|
||||
|
||||
To fold `.planning/` file changes into the previous commit:
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "" --files .planning/codebase/*.md --amend
|
||||
```
|
||||
|
||||
## Commit Message Patterns
|
||||
|
||||
| Command | Scope | Example |
|
||||
|---------|-------|---------|
|
||||
| plan-phase | phase | `docs(phase-03): create authentication plans` |
|
||||
| execute-phase | phase | `docs(phase-03): complete authentication phase` |
|
||||
| new-milestone | milestone | `docs: start milestone v1.1` |
|
||||
| remove-phase | chore | `chore: remove phase 17 (dashboard)` |
|
||||
| insert-phase | phase | `docs: insert phase 16.1 (critical fix)` |
|
||||
| add-phase | phase | `docs: add phase 07 (settings page)` |
|
||||
|
||||
## When to Skip
|
||||
|
||||
- `commit_docs: false` in config
|
||||
- `.planning/` is gitignored
|
||||
- No changes to commit (check with `git status --porcelain .planning/`)
|
||||
123
gsd-core/references/ios-scaffold.md
Normal file
123
gsd-core/references/ios-scaffold.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# iOS App Scaffold Reference
|
||||
|
||||
Rules and patterns for scaffolding iOS applications. Apply when any plan involves creating a new iOS app target.
|
||||
|
||||
---
|
||||
|
||||
## Critical Rule: Never Use Package.swift as the Primary Build System for iOS Apps
|
||||
|
||||
**NEVER use `Package.swift` with `.executableTarget` (or `.target`) to scaffold an iOS app.** Swift Package Manager executable targets compile as macOS command-line tools — they do not produce `.app` bundles, cannot be signed for iOS devices, and cannot be submitted to the App Store.
|
||||
|
||||
**Prohibited pattern:**
|
||||
```swift
|
||||
// Package.swift — DO NOT USE for iOS apps
|
||||
.executableTarget(name: "MyApp", dependencies: [])
|
||||
// or
|
||||
.target(name: "MyApp", dependencies: [])
|
||||
```
|
||||
|
||||
Using this pattern produces a macOS CLI binary, not an iOS app. The app will not build for any iOS simulator or device.
|
||||
|
||||
---
|
||||
|
||||
## Required Pattern: XcodeGen
|
||||
|
||||
All iOS app scaffolding MUST use XcodeGen to generate the `.xcodeproj`.
|
||||
|
||||
### Step 1 — Install XcodeGen (if not present)
|
||||
|
||||
```bash
|
||||
brew install xcodegen
|
||||
```
|
||||
|
||||
### Step 2 — Create `project.yml`
|
||||
|
||||
`project.yml` is the XcodeGen spec that describes the project structure. Minimum viable spec:
|
||||
|
||||
```yaml
|
||||
name: MyApp
|
||||
options:
|
||||
bundleIdPrefix: com.example
|
||||
deploymentTarget:
|
||||
iOS: "17.0"
|
||||
settings:
|
||||
SWIFT_VERSION: "5.10"
|
||||
IPHONEOS_DEPLOYMENT_TARGET: "17.0"
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
sources: [Sources/MyApp]
|
||||
settings:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.example.MyApp
|
||||
INFOPLIST_FILE: Sources/MyApp/Info.plist
|
||||
scheme:
|
||||
testTargets:
|
||||
- MyAppTests
|
||||
MyAppTests:
|
||||
type: bundle.unit-test
|
||||
platform: iOS
|
||||
sources: [Tests/MyAppTests]
|
||||
dependencies:
|
||||
- target: MyApp
|
||||
```
|
||||
|
||||
### Step 3 — Generate the .xcodeproj
|
||||
|
||||
```bash
|
||||
xcodegen generate
|
||||
```
|
||||
|
||||
This creates `MyApp.xcodeproj` in the project root. Commit `project.yml` but add `*.xcodeproj` to `.gitignore` (regenerate on checkout).
|
||||
|
||||
### Step 4 — Standard project layout
|
||||
|
||||
```
|
||||
MyApp/
|
||||
├── project.yml # XcodeGen spec — commit this
|
||||
├── .gitignore # includes *.xcodeproj
|
||||
├── Sources/
|
||||
│ └── MyApp/
|
||||
│ ├── MyAppApp.swift # @main entry point
|
||||
│ ├── ContentView.swift
|
||||
│ └── Info.plist
|
||||
└── Tests/
|
||||
└── MyAppTests/
|
||||
└── MyAppTests.swift
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## iOS Deployment Target Compatibility
|
||||
|
||||
Always verify SwiftUI API availability against the project's `IPHONEOS_DEPLOYMENT_TARGET` before using any SwiftUI component.
|
||||
|
||||
| API | Minimum iOS |
|
||||
|-----|-------------|
|
||||
| `NavigationView` | iOS 13 |
|
||||
| `NavigationStack` | iOS 16 |
|
||||
| `NavigationSplitView` | iOS 16 |
|
||||
| `List(selection:)` with multi-select | iOS 17 |
|
||||
| `ScrollView` scroll position APIs | iOS 17 |
|
||||
| `Observable` macro (`@Observable`) | iOS 17 |
|
||||
| `SwiftData` | iOS 17 |
|
||||
| `@Bindable` | iOS 17 |
|
||||
| `TipKit` | iOS 17 |
|
||||
|
||||
**Rule:** If a plan requires a SwiftUI API that exceeds the project's deployment target, either:
|
||||
1. Raise the deployment target in `project.yml` (and document the decision), or
|
||||
2. Wrap the call in `if #available(iOS NN, *) { ... }` with a fallback implementation.
|
||||
|
||||
Do NOT silently use an API that requires a higher iOS version than the declared deployment target — the app will crash at runtime on older devices.
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
After running `xcodegen generate`, verify the project builds:
|
||||
|
||||
```bash
|
||||
xcodebuild -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16' build
|
||||
```
|
||||
|
||||
A successful build (exit code 0) confirms the scaffold is valid for iOS.
|
||||
2
gsd-core/references/mandatory-initial-read.md
Normal file
2
gsd-core/references/mandatory-initial-read.md
Normal file
@@ -0,0 +1,2 @@
|
||||
**CRITICAL: Mandatory Initial Read**
|
||||
If the prompt contains a `<required_reading>` block, you MUST use the `Read` tool to load every file listed there before performing any other actions. This is your primary context.
|
||||
38
gsd-core/references/model-profile-resolution.md
Normal file
38
gsd-core/references/model-profile-resolution.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Model Profile Resolution
|
||||
|
||||
Resolve model profile once at the start of orchestration, then use it for all Task spawns.
|
||||
|
||||
## Resolution Pattern
|
||||
|
||||
```bash
|
||||
MODEL_PROFILE=$(cat .planning/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "balanced")
|
||||
```
|
||||
|
||||
Default: `balanced` if not set or config missing.
|
||||
|
||||
## Lookup Table
|
||||
|
||||
@~/.claude/gsd-core/references/model-profiles.md
|
||||
|
||||
Look up the agent in the table for the resolved profile. Pass the model parameter to Task calls:
|
||||
|
||||
```
|
||||
Task(
|
||||
prompt="...",
|
||||
subagent_type="gsd-planner",
|
||||
model="{resolved_model}" # "inherit", "sonnet", or "haiku"
|
||||
)
|
||||
```
|
||||
|
||||
**Note:** Opus-tier agents resolve to `"inherit"` (not `"opus"`). This causes the agent to use the parent session's model, avoiding conflicts with organization policies that may block specific opus versions.
|
||||
|
||||
If `model_profile` is `"adaptive"`, agents resolve to role-based assignments (opus/sonnet/haiku based on agent type).
|
||||
|
||||
If `model_profile` is `"inherit"`, all agents resolve to `"inherit"` (useful for OpenCode `/model`).
|
||||
|
||||
## Usage
|
||||
|
||||
1. Resolve once at orchestration start
|
||||
2. Store the profile value
|
||||
3. Look up each agent's model from the table when spawning
|
||||
4. Pass model parameter to each Task call (values: `"inherit"`, `"sonnet"`, `"haiku"`)
|
||||
245
gsd-core/references/model-profiles.md
Normal file
245
gsd-core/references/model-profiles.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# Model Profiles
|
||||
|
||||
Model profiles control which Claude model each GSD agent uses. This allows balancing quality vs token spend, or inheriting the currently selected session model.
|
||||
|
||||
## Profile Definitions
|
||||
|
||||
| Agent | `quality` | `balanced` | `budget` | `adaptive` | `inherit` |
|
||||
|-------|-----------|------------|----------|------------|-----------|
|
||||
| gsd-planner | opus | opus | sonnet | opus | inherit |
|
||||
| gsd-roadmapper | opus | sonnet | sonnet | sonnet | inherit |
|
||||
| gsd-executor | opus | sonnet | sonnet | sonnet | inherit |
|
||||
| gsd-phase-researcher | opus | sonnet | haiku | sonnet | inherit |
|
||||
| gsd-project-researcher | opus | sonnet | haiku | sonnet | inherit |
|
||||
| gsd-research-synthesizer | sonnet | sonnet | haiku | haiku | inherit |
|
||||
| gsd-debugger | opus | sonnet | sonnet | opus | inherit |
|
||||
| gsd-codebase-mapper | sonnet | haiku | haiku | haiku | inherit |
|
||||
| gsd-verifier | sonnet | sonnet | haiku | sonnet | inherit |
|
||||
| gsd-plan-checker | sonnet | sonnet | haiku | haiku | inherit |
|
||||
| gsd-integration-checker | sonnet | sonnet | haiku | haiku | inherit |
|
||||
| gsd-nyquist-auditor | sonnet | sonnet | haiku | haiku | inherit |
|
||||
|
||||
## Per-Phase-Type Model Map (#3023)
|
||||
|
||||
`.planning/config.json` accepts a coarse per-**phase-type** map under the `models` key. Use this when you want tuning at the phase level ("Opus for planning and execution, Sonnet for the rest") without learning the agent taxonomy.
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "balanced",
|
||||
"models": {
|
||||
"planning": "opus",
|
||||
"discuss": "opus",
|
||||
"research": "sonnet",
|
||||
"execution": "opus",
|
||||
"verification": "sonnet",
|
||||
"completion": "sonnet"
|
||||
},
|
||||
"model_overrides": {
|
||||
"gsd-codebase-mapper": "haiku"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase-type → agent mapping
|
||||
|
||||
| Phase type | Agents |
|
||||
|---|---|
|
||||
| `planning` | gsd-planner, gsd-roadmapper, gsd-pattern-mapper |
|
||||
| `discuss` | (reserved — no subagent today) |
|
||||
| `research` | gsd-phase-researcher, gsd-project-researcher, gsd-research-synthesizer, gsd-codebase-mapper, gsd-ui-researcher |
|
||||
| `execution` | gsd-executor, gsd-debugger, gsd-doc-writer |
|
||||
| `verification` | gsd-verifier, gsd-plan-checker, gsd-integration-checker, gsd-nyquist-auditor, gsd-ui-checker, gsd-ui-auditor, gsd-doc-verifier |
|
||||
| `completion` | (reserved — no subagent today) |
|
||||
|
||||
### Resolution precedence (highest to lowest)
|
||||
|
||||
1. **Per-agent `model_overrides[agent]`** — full IDs accepted; targeted exceptions
|
||||
2. **Phase-type `models[phase_type]`** — tier alias only (`opus` / `sonnet` / `haiku` / `inherit`)
|
||||
3. **Profile table** — the per-agent column from the active `model_profile`
|
||||
4. **Runtime default** — when nothing else applies
|
||||
|
||||
### Why two layers above the profile?
|
||||
|
||||
- **Profile** is a global tier strategy (everyone runs balanced).
|
||||
- **`models`** is coarse phase-level tuning without learning agent names.
|
||||
- **`model_overrides`** is per-agent precision (e.g. force `haiku` on `gsd-codebase-mapper` for a fan-out).
|
||||
|
||||
The three layers compose: `models` defaults a phase, `model_overrides` carves an exception out of it.
|
||||
|
||||
## Profile Philosophy
|
||||
|
||||
**quality** - Maximum reasoning power
|
||||
- Opus for all decision-making agents
|
||||
- Sonnet for read-only verification
|
||||
- Use when: quota available, critical architecture work
|
||||
|
||||
**balanced** (default) - Smart allocation
|
||||
- Opus only for planning (where architecture decisions happen)
|
||||
- Sonnet for execution and research (follows explicit instructions)
|
||||
- Sonnet for verification (needs reasoning, not just pattern matching)
|
||||
- Use when: normal development, good balance of quality and cost
|
||||
|
||||
**budget** - Minimal Opus usage
|
||||
- Sonnet for anything that writes code
|
||||
- Haiku for research and verification
|
||||
- Use when: conserving quota, high-volume work, less critical phases
|
||||
|
||||
**adaptive** — Role-based cost optimization
|
||||
- Opus for planning and debugging (where reasoning quality has highest impact)
|
||||
- Sonnet for execution, research, and verification (follows explicit instructions)
|
||||
- Haiku for mapping, checking, and auditing (high volume, structured output)
|
||||
- Use when: optimizing cost without sacrificing plan quality, solo development on paid API tiers
|
||||
|
||||
**inherit** - Follow the current session model
|
||||
- All agents resolve to `inherit`
|
||||
- Best when you switch models interactively (for example OpenCode or Kilo `/model`)
|
||||
- **Required when using non-Anthropic providers** (OpenRouter, local models, etc.) — otherwise GSD may call Anthropic models directly, incurring unexpected costs
|
||||
- Use when: you want GSD to follow your currently selected runtime model
|
||||
|
||||
## Using Non-Claude Runtimes (Codex, OpenCode, Gemini CLI, Kilo)
|
||||
|
||||
When installed for a non-Claude runtime, the GSD installer sets `resolve_model_ids: "omit"` in `~/.gsd/defaults.json`. This returns an empty model parameter for all agents, so each agent uses the runtime's default model. No manual setup is needed.
|
||||
|
||||
To assign different models to different agents, add `model_overrides` with model IDs your runtime recognizes:
|
||||
|
||||
```json
|
||||
{
|
||||
"resolve_model_ids": "omit",
|
||||
"model_overrides": {
|
||||
"gsd-planner": "o3",
|
||||
"gsd-executor": "o4-mini",
|
||||
"gsd-debugger": "o3",
|
||||
"gsd-codebase-mapper": "o4-mini"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The same tiering logic applies: stronger models for planning and debugging, cheaper models for execution and mapping.
|
||||
|
||||
## Using Claude Code with Non-Anthropic Providers (OpenRouter, Local)
|
||||
|
||||
If you're using Claude Code with OpenRouter, a local model, or any non-Anthropic provider, set the `inherit` profile to prevent GSD from calling Anthropic models for subagents:
|
||||
|
||||
```bash
|
||||
# Via settings command
|
||||
/gsd:settings
|
||||
# → Select "Inherit" for model profile
|
||||
|
||||
# Or manually in .planning/config.json
|
||||
{
|
||||
"model_profile": "inherit"
|
||||
}
|
||||
```
|
||||
|
||||
Without `inherit`, GSD's default `balanced` profile spawns specific Anthropic models (`opus`, `sonnet`, `haiku`) for each agent type, which can result in additional API costs through your non-Anthropic provider.
|
||||
|
||||
## Dynamic Routing with Failure-Tier Escalation (#3024)
|
||||
|
||||
When `dynamic_routing.enabled = true` in `.planning/config.json`, the resolver picks a model from a tier-mapped table based on the agent's *default tier* (light / standard / heavy) and escalates to the next tier up on orchestrator-detected soft failure.
|
||||
|
||||
```json
|
||||
{
|
||||
"dynamic_routing": {
|
||||
"enabled": true,
|
||||
"tier_models": {
|
||||
"light": "haiku",
|
||||
"standard": "sonnet",
|
||||
"heavy": "opus"
|
||||
},
|
||||
"escalate_on_failure": true,
|
||||
"max_escalations": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Agent default tiers** (each agent in `MODEL_PROFILES` declares one):
|
||||
|
||||
| Tier | Agents | Use case |
|
||||
|---|---|---|
|
||||
| `light` | gsd-codebase-mapper, gsd-pattern-mapper, gsd-research-synthesizer, gsd-plan-checker, gsd-integration-checker, gsd-nyquist-auditor, gsd-ui-checker, gsd-ui-auditor, gsd-doc-verifier | Cheap/fast — pure mappers, scanners, low-stakes audits |
|
||||
| `standard` | gsd-executor, gsd-phase-researcher, gsd-project-researcher, gsd-verifier, gsd-doc-writer, gsd-ui-researcher | Default workhorse — research, writing, primary verification |
|
||||
| `heavy` | gsd-planner, gsd-roadmapper, gsd-debugger | Deep reasoning — already at top, can't escalate further |
|
||||
|
||||
**Escalation flow** (orchestrator-driven):
|
||||
|
||||
1. Orchestrator spawns agent with `attempt: 0` → resolver returns `tier_models[default_tier]`
|
||||
2. If orchestrator marks the result a soft failure, it re-spawns with `attempt: 1` → resolver returns `tier_models[next_tier_up]`
|
||||
3. `max_escalations` caps total retries (default 1). Beyond the cap the resolver returns the cap-tier model so the orchestrator can log without burning further budget.
|
||||
4. Hard failures (exceptions) bypass escalation and surface immediately.
|
||||
|
||||
**Precedence with other tier sources** (highest → lowest):
|
||||
|
||||
1. `model_overrides[<agent>]` — full ID, always wins
|
||||
2. `dynamic_routing.tier_models[escalated_tier]` — when `enabled: true`
|
||||
3. `models[<phase_type>]` — coarse phase-level (#3023)
|
||||
4. `model_profile` — global tier strategy
|
||||
|
||||
When `dynamic_routing.enabled = false` (default), behavior is identical to today.
|
||||
|
||||
## Resolution Logic
|
||||
|
||||
Orchestrators resolve model before spawning. The full precedence ladder
|
||||
is (highest → lowest):
|
||||
|
||||
```text
|
||||
1. Read .planning/config.json
|
||||
2. Check model_overrides[<agent>] (full IDs accepted; targeted exceptions)
|
||||
3. If dynamic_routing.enabled, return tier_models[escalated_tier]
|
||||
(see §Dynamic Routing — escalation steps tier up per attempt counter)
|
||||
4. If no dynamic_routing match, check models[phase_type] for a phase-type tier
|
||||
(see §Per-Phase-Type Model Map for the agent → phase-type mapping)
|
||||
5. If no phase-type slot, look up agent in profile table
|
||||
6. Pass model parameter to Task call
|
||||
```
|
||||
|
||||
The same precedence applies to `reasoning_effort` resolution on runtimes
|
||||
that support it (Codex), so `model` and `reasoning_effort` always derive
|
||||
from the same tier source — a `models[phase_type]` or
|
||||
`dynamic_routing` override flips both.
|
||||
|
||||
## Per-Agent Overrides
|
||||
|
||||
Override specific agents without changing the entire profile:
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "balanced",
|
||||
"model_overrides": {
|
||||
"gsd-executor": "opus",
|
||||
"gsd-planner": "haiku"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Overrides take precedence over the profile. Valid values: `opus`, `sonnet`, `haiku`, `inherit`, or any fully-qualified model ID (e.g., `"o3"`, `"openai/o3"`, `"google/gemini-2.5-pro"`).
|
||||
|
||||
## Switching Profiles
|
||||
|
||||
Runtime: `/gsd-set-profile <profile>`
|
||||
|
||||
Per-project default: Set in `.planning/config.json`:
|
||||
```json
|
||||
{
|
||||
"model_profile": "balanced"
|
||||
}
|
||||
```
|
||||
|
||||
## Design Rationale
|
||||
|
||||
**Why Opus for gsd-planner?**
|
||||
Planning involves architecture decisions, goal decomposition, and task design. This is where model quality has the highest impact.
|
||||
|
||||
**Why Sonnet for gsd-executor?**
|
||||
Executors follow explicit PLAN.md instructions. The plan already contains the reasoning; execution is implementation.
|
||||
|
||||
**Why Sonnet (not Haiku) for verifiers in balanced?**
|
||||
Verification requires goal-backward reasoning - checking if code *delivers* what the phase promised, not just pattern matching. Sonnet handles this well; Haiku may miss subtle gaps.
|
||||
|
||||
**Why Haiku for gsd-codebase-mapper?**
|
||||
Read-only exploration and pattern extraction. No reasoning required, just structured output from file contents.
|
||||
|
||||
**Why `inherit` instead of passing `opus` directly?**
|
||||
Claude Code's `"opus"` alias maps to a specific model version. Organizations may block older opus versions while allowing newer ones. GSD returns `"inherit"` for opus-tier agents, causing them to use whatever opus version the user has configured in their session. This avoids version conflicts and silent fallbacks to Sonnet.
|
||||
|
||||
**Why `inherit` profile?**
|
||||
Some runtimes (including OpenCode) let users switch models at runtime (`/model`). The `inherit` profile keeps all GSD subagents aligned to that live selection.
|
||||
49
gsd-core/references/mvp-concepts.md
Normal file
49
gsd-core/references/mvp-concepts.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# MVP Concepts — index
|
||||
|
||||
Cross-reference for the six MVP-related reference files. Each file has a single, narrow purpose. This index exists so future readers (and agents resolving `@`-refs) can find the right file without grepping the directory.
|
||||
|
||||
Canonical domain terms for the concepts named below live in [CONTEXT.md](../../CONTEXT.md) under "Domain terms" — start there if you need a precise definition.
|
||||
|
||||
## File map
|
||||
|
||||
| File | Purpose | Loaded by |
|
||||
|---|---|---|
|
||||
| `references/planner-mvp-mode.md` | **Rules.** Vertical-slice planning rules, slice ordering, Walking Skeleton constraints. | `gsd-planner` agent when `MVP_MODE=true` |
|
||||
| `references/skeleton-template.md` | **Template.** Shape of `SKELETON.md` for new-project Phase 1 under `--mvp`. | `gsd-planner` agent when the Walking Skeleton gate fires |
|
||||
| `references/user-story-template.md` | **Template.** Format and slot definitions for `As a / I want to / So that`. | `gsd-mvp-phase` workflow during interactive prompting; `gsd-planner` when emitting the `## Phase Goal` header |
|
||||
| `references/spidr-splitting.md` | **Splitting discipline.** Five-axis decomposition (Spike, Paths, Interfaces, Data, Rules) for stories too large for one phase. | `gsd-mvp-phase` workflow when the user story exceeds size threshold |
|
||||
| `references/execute-mvp-tdd.md` | **Gate.** MVP+TDD runtime gate semantics: when it fires, what it checks, halt-and-report protocol, end-of-phase blocking escalation, Behavior-Adding Task definition. | `gsd-executor` agent when `MVP_MODE=true && TDD_MODE=true` |
|
||||
| `references/verify-mvp-mode.md` | **UAT framing.** Three-section UAT structure (user-flow → technical → coverage), anti-patterns, `User Flow Coverage` section in VERIFICATION.md. | `gsd-verifier` agent when the phase under verification has `mode: mvp` |
|
||||
|
||||
## Concept-to-file map
|
||||
|
||||
If you're looking for the canonical statement of a concept, this is where to find it:
|
||||
|
||||
- **MVP Mode resolution chain** — `workflows/plan-phase.md` Step 1 (CLI flag → roadmap → config → false). Mirrored in `execute-phase.md` and `verify-work.md`.
|
||||
- **`**Mode:** mvp` parser** — `gsd-core/bin/lib/roadmap.cjs` (`searchPhaseInContent` + `cmdRoadmapAnalyze`). Workflows compare against the parser output, never re-parse.
|
||||
- **User Story regex** — `/^As a .+, I want to .+, so that .+\.$/` — applied at runtime by `gsd-verifier` (the user-story-format guard) and `gsd-mvp-phase` (interactive validation).
|
||||
- **Behavior-Adding Task predicate** — `references/execute-mvp-tdd.md` (the canonical three-check definition). Applied at runtime by `gsd-executor`.
|
||||
- **Walking Skeleton gate condition** — `workflows/plan-phase.md` (Phase 1 + new project + `--mvp` + no prior summaries → emit `SKELETON.md`).
|
||||
- **MVP+TDD Gate** (RED→GREEN enforcement) — `references/execute-mvp-tdd.md`.
|
||||
- **MVP-mode UAT framing** (user-flow first, technical deferred) — `references/verify-mvp-mode.md`.
|
||||
- **Per-phase mode authoring** — `workflows/mvp-phase.md` (writes `**Mode:** mvp` to ROADMAP.md after collecting the user story).
|
||||
- **Project-wide mode prompt at init** — `workflows/new-project.md` (Vertical MVP vs Horizontal Layers question).
|
||||
|
||||
## Interactions worth knowing
|
||||
|
||||
- **`--mvp` and `--prd <file>` together on Phase 1.** Both paths converge at the planner spawn. The PRD express path creates `CONTEXT.md` from the PRD file and continues to the research step; the Walking Skeleton gate fires independently when Phase 1 + new project + `--mvp`. The planner therefore receives both `WALKING_SKELETON=true` and PRD-derived context. This is intentional: the PRD informs what the skeleton should prove.
|
||||
- **`MVP_MODE` is all-or-nothing per phase, not per task.** A phase is either MVP-mode or standard. Mixed-mode phases are not supported (PRD #2826 Q1).
|
||||
- **`TDD_MODE` is independent of `MVP_MODE`.** TDD can be on without MVP, MVP can be on without TDD. Only the *intersection* (both true) activates the MVP+TDD Gate.
|
||||
- **The `gsd-roadmapper` agent makes the MVP/standard decision once at project init** based on `PROJECT_MODE`. Per-phase opt-in/out happens later via `/gsd:mvp-phase` or `/gsd-edit-phase`.
|
||||
|
||||
## Tests
|
||||
|
||||
Structural contract tests for each integration site live under `tests/`:
|
||||
|
||||
- `plan-phase-mvp-flag.test.cjs` — plan-phase MVP_MODE resolution chain
|
||||
- `planner-mvp-mode.test.cjs` — gsd-planner agent MVP section
|
||||
- `mvp-phase-command.test.cjs`, `mvp-phase-integration.test.cjs`, `mvp-phase-spidr.test.cjs` — `/gsd:mvp-phase`
|
||||
- `execute-mvp-tdd-gate.test.cjs`, `executor-mvp-tdd-section.test.cjs` — MVP+TDD Gate
|
||||
- `verifier-mvp-section.test.cjs`, `verify-mvp-uat.test.cjs` — verifier UAT framing
|
||||
- `new-project-mvp-prompt.test.cjs` — mode prompt at init
|
||||
- `progress-mvp-display.test.cjs`, `stats-mvp-display.test.cjs`, `graphify-mvp-viz.test.cjs` — discovery surfaces
|
||||
61
gsd-core/references/phase-argument-parsing.md
Normal file
61
gsd-core/references/phase-argument-parsing.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Phase Argument Parsing
|
||||
|
||||
Parse and normalize phase arguments for commands that operate on phases.
|
||||
|
||||
## Extraction
|
||||
|
||||
From `$ARGUMENTS`:
|
||||
- Extract phase number (first numeric argument)
|
||||
- Extract flags (prefixed with `--`)
|
||||
- Remaining text is description (for insert/add commands)
|
||||
|
||||
## Using gsd-tools
|
||||
|
||||
The `find-phase` command handles normalization and validation in one step:
|
||||
|
||||
```bash
|
||||
PHASE_INFO=$(gsd-tools query find-phase "${PHASE}")
|
||||
```
|
||||
|
||||
Returns JSON with:
|
||||
- `found`: true/false
|
||||
- `directory`: Full path to phase directory
|
||||
- `phase_number`: Normalized number (e.g., "06", "06.1")
|
||||
- `phase_name`: Name portion (e.g., "foundation")
|
||||
- `plans`: Array of PLAN.md files
|
||||
- `summaries`: Array of SUMMARY.md files
|
||||
|
||||
## Manual Normalization (Legacy)
|
||||
|
||||
Zero-pad integer phases to 2 digits. Preserve decimal suffixes.
|
||||
|
||||
```bash
|
||||
# Normalize phase number
|
||||
if [[ "$PHASE" =~ ^[0-9]+$ ]]; then
|
||||
# Integer: 8 → 08
|
||||
PHASE=$(printf "%02d" "$PHASE")
|
||||
elif [[ "$PHASE" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
|
||||
# Decimal: 2.1 → 02.1
|
||||
PHASE=$(printf "%02d.%s" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")
|
||||
fi
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Use `roadmap get-phase` to validate phase exists:
|
||||
|
||||
```bash
|
||||
PHASE_CHECK=$(gsd-tools query roadmap.get-phase "${PHASE}" --pick found)
|
||||
if [ "$PHASE_CHECK" = "false" ]; then
|
||||
echo "ERROR: Phase ${PHASE} not found in roadmap"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## Directory Lookup
|
||||
|
||||
Use `find-phase` for directory lookup:
|
||||
|
||||
```bash
|
||||
PHASE_DIR=$(gsd-tools query find-phase "${PHASE}" --raw)
|
||||
```
|
||||
89
gsd-core/references/planner-antipatterns.md
Normal file
89
gsd-core/references/planner-antipatterns.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Planner Anti-Patterns and Specificity Examples
|
||||
|
||||
> Reference file for gsd-planner agent. Loaded on-demand via `@` reference.
|
||||
> For sub-200K context windows, this content is stripped from the agent prompt and available here for on-demand loading.
|
||||
|
||||
## Checkpoint Anti-Patterns
|
||||
|
||||
### Bad — Asking human to automate
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-action">
|
||||
<action>Deploy to Vercel</action>
|
||||
<instructions>Visit vercel.com, import repo, click deploy...</instructions>
|
||||
</task>
|
||||
```
|
||||
|
||||
**Why bad:** Vercel has a CLI. Claude should run `vercel --yes`. Never ask the user to do what Claude can automate via CLI/API.
|
||||
|
||||
### Bad — Too many checkpoints
|
||||
|
||||
```xml
|
||||
<task type="auto">Create schema</task>
|
||||
<task type="checkpoint:human-verify">Check schema</task>
|
||||
<task type="auto">Create API</task>
|
||||
<task type="checkpoint:human-verify">Check API</task>
|
||||
```
|
||||
|
||||
**Why bad:** Verification fatigue. Users should not be asked to verify every small step. Combine into one checkpoint at the end of meaningful work.
|
||||
|
||||
### Good — Single verification checkpoint
|
||||
|
||||
```xml
|
||||
<task type="auto">Create schema</task>
|
||||
<task type="auto">Create API</task>
|
||||
<task type="auto">Create UI</task>
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Complete auth flow (schema + API + UI)</what-built>
|
||||
<how-to-verify>Test full flow: register, login, access protected page</how-to-verify>
|
||||
</task>
|
||||
```
|
||||
|
||||
### Bad — Mixing checkpoints with implementation
|
||||
|
||||
A plan should not interleave multiple checkpoint types with implementation tasks. Checkpoints belong at natural verification boundaries, not scattered throughout.
|
||||
|
||||
## Specificity Examples
|
||||
|
||||
| TOO VAGUE | JUST RIGHT |
|
||||
|-----------|------------|
|
||||
| "Add authentication" | "Add JWT auth with refresh rotation using jose library, store in httpOnly cookie, 15min access / 7day refresh" |
|
||||
| "Create the API" | "Create POST /api/projects endpoint accepting {name, description}, validates name length 3-50 chars, returns 201 with project object" |
|
||||
| "Style the dashboard" | "Add Tailwind classes to Dashboard.tsx: grid layout (3 cols on lg, 1 on mobile), card shadows, hover states on action buttons" |
|
||||
| "Handle errors" | "Wrap API calls in try/catch, return {error: string} on 4xx/5xx, show toast via sonner on client" |
|
||||
| "Set up the database" | "Add User and Project models to schema.prisma with UUID ids, email unique constraint, createdAt/updatedAt timestamps, run prisma db push" |
|
||||
|
||||
**Specificity test:** Could a different Claude instance execute the task without asking clarifying questions? If not, add more detail.
|
||||
|
||||
## Context Section Anti-Patterns
|
||||
|
||||
### Bad — Reflexive SUMMARY chaining
|
||||
|
||||
```markdown
|
||||
<context>
|
||||
@.planning/phases/01-foundation/01-01-SUMMARY.md
|
||||
@.planning/phases/01-foundation/01-02-SUMMARY.md <!-- Does Plan 02 actually need Plan 01's output? -->
|
||||
@.planning/phases/01-foundation/01-03-SUMMARY.md <!-- Chain grows, context bloats -->
|
||||
</context>
|
||||
```
|
||||
|
||||
**Why bad:** Plans are often independent. Reflexive chaining (02 refs 01, 03 refs 02...) wastes context. Only reference prior SUMMARY files when the plan genuinely uses types/exports from that prior plan or a decision from it affects the current plan.
|
||||
|
||||
### Good — Selective context
|
||||
|
||||
```markdown
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/01-foundation/01-01-SUMMARY.md <!-- Uses User type defined in Plan 01 -->
|
||||
</context>
|
||||
```
|
||||
|
||||
## Scope Reduction Anti-Patterns
|
||||
|
||||
**Prohibited language in task actions:**
|
||||
- "v1", "v2", "simplified version", "static for now", "hardcoded for now"
|
||||
- "future enhancement", "placeholder", "basic version", "minimal implementation"
|
||||
- "will be wired later", "dynamic in future phase", "skip for now"
|
||||
|
||||
If a decision from CONTEXT.md says "display cost calculated from billing table in impulses", the plan must deliver exactly that. Not "static label /min" as a "v1". If the phase is too complex, recommend a phase split instead of silently reducing scope.
|
||||
49
gsd-core/references/planner-chunked.md
Normal file
49
gsd-core/references/planner-chunked.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Chunked Mode Return Formats
|
||||
|
||||
Used when `plan-phase` spawns `gsd-planner` with `CHUNKED_MODE=true` (triggered by `--chunked`
|
||||
flag or `workflow.plan_chunked: true` config). Splits the single long-lived planner Task into
|
||||
shorter-lived Tasks to bound the blast radius of Windows stdio hangs.
|
||||
|
||||
## Modes
|
||||
|
||||
### outline-only
|
||||
|
||||
Write **only** `{PHASE_DIR}/{PADDED_PHASE}-PLAN-OUTLINE.md`. Do not write any PLAN.md files.
|
||||
Return:
|
||||
|
||||
```markdown
|
||||
## OUTLINE COMPLETE
|
||||
|
||||
**Phase:** {phase-name}
|
||||
**Plans:** {N} plan(s) in {M} wave(s)
|
||||
|
||||
| Plan ID | Objective | Wave | Depends On | Requirements |
|
||||
|---------|-----------|------|-----------|-------------|
|
||||
| {padded_phase}-01 | [brief objective] | 1 | none | REQ-001, REQ-002 |
|
||||
| {padded_phase}-02 | [brief objective] | 1 | none | REQ-003 |
|
||||
```
|
||||
|
||||
The orchestrator reads this table, then spawns one single-plan Task per row.
|
||||
|
||||
### single-plan
|
||||
|
||||
Write **exactly one** `{PHASE_DIR}/{plan_id}-PLAN.md`. Do not write any other plan files.
|
||||
Return:
|
||||
|
||||
```markdown
|
||||
## PLAN COMPLETE
|
||||
|
||||
**Plan:** {plan-id}
|
||||
**Objective:** {brief}
|
||||
**File:** {PHASE_DIR}/{plan-id}-PLAN.md
|
||||
**Tasks:** {N}
|
||||
```
|
||||
|
||||
The orchestrator verifies the file exists on disk after each return, commits it, then moves
|
||||
to the next plan entry from the outline.
|
||||
|
||||
## Resume Behaviour
|
||||
|
||||
If the orchestrator detects that `PLAN-OUTLINE.md` already exists (from a prior interrupted
|
||||
run), it skips the outline-only Task and goes directly to single-plan Tasks, skipping any
|
||||
`{plan_id}-PLAN.md` files that already exist on disk.
|
||||
62
gsd-core/references/planner-gap-closure.md
Normal file
62
gsd-core/references/planner-gap-closure.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Gap Closure Mode — Planner Reference
|
||||
|
||||
Triggered by `--gaps` flag. Creates plans to address verification or UAT failures.
|
||||
|
||||
**Important: Skip deferred items.** When reading VERIFICATION.md, only the `gaps:` section contains actionable items that need closure plans. The `deferred:` section (if present) lists items explicitly addressed in later milestone phases — these are NOT gaps and must be ignored during gap closure planning. Creating plans for deferred items wastes effort on work already scheduled for future phases.
|
||||
|
||||
**1. Find gap sources:**
|
||||
|
||||
Use init context (from load_project_state) which provides `phase_dir`:
|
||||
|
||||
```bash
|
||||
# Check for VERIFICATION.md (code verification gaps)
|
||||
ls "$phase_dir"/*-VERIFICATION.md 2>/dev/null
|
||||
|
||||
# Check for UAT.md with diagnosed status (user testing gaps)
|
||||
grep -l "status: diagnosed" "$phase_dir"/*-UAT.md 2>/dev/null
|
||||
```
|
||||
|
||||
**2. Parse gaps:** Each gap has: truth (failed behavior), reason, artifacts (files with issues), missing (things to add/fix).
|
||||
|
||||
**3. Load existing SUMMARYs** to understand what's already built.
|
||||
|
||||
**4. Find next plan number:** If plans 01-03 exist, next is 04.
|
||||
|
||||
**5. Group gaps into plans** by: same artifact, same concern, dependency order (can't wire if artifact is stub → fix stub first).
|
||||
|
||||
**6. Create gap closure tasks:**
|
||||
|
||||
```xml
|
||||
<task name="{fix_description}" type="auto">
|
||||
<files>{artifact.path}</files>
|
||||
<action>
|
||||
{For each item in gap.missing:}
|
||||
- {missing item}
|
||||
|
||||
Reference existing code: {from SUMMARYs}
|
||||
Gap reason: {gap.reason}
|
||||
</action>
|
||||
<verify>{How to confirm gap is closed}</verify>
|
||||
<done>{Observable truth now achievable}</done>
|
||||
</task>
|
||||
```
|
||||
|
||||
**7. Assign waves using standard dependency analysis** (same as `assign_waves` step):
|
||||
- Plans with no dependencies → wave 1
|
||||
- Plans that depend on other gap closure plans → max(dependency waves) + 1
|
||||
- Also consider dependencies on existing (non-gap) plans in the phase
|
||||
|
||||
**8. Write PLAN.md files:**
|
||||
|
||||
```yaml
|
||||
---
|
||||
phase: XX-name
|
||||
plan: NN # Sequential after existing
|
||||
type: execute
|
||||
wave: N # Computed from depends_on (see assign_waves)
|
||||
depends_on: [...] # Other plans this depends on (gap or existing)
|
||||
files_modified: [...]
|
||||
autonomous: true
|
||||
gap_closure: true # Flag for tracking
|
||||
---
|
||||
```
|
||||
67
gsd-core/references/planner-graphify-auto-update.md
Normal file
67
gsd-core/references/planner-graphify-auto-update.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Graphify Auto-Update — Status Surfacing
|
||||
|
||||
> Documents how `gsd-planner` and `gsd-phase-researcher` surface the opt-in graphify auto-update state (issue #3347). The status surface lives inside `graphifyStatus()` in `gsd-core/bin/lib/graphify.cjs`; no planner-side prompt changes are required.
|
||||
|
||||
## Why this exists
|
||||
|
||||
The graph at `.planning/graphs/graph.json` is consumed automatically (every `gsd-planner` and `gsd-phase-researcher` step) but produced manually (`/gsd:graphify build` per session at best). Without auto-update, the producer-consumer gap silently widens with every commit. The existing `stale: true` annotation tells the consumer the mtime is old; it cannot tell the consumer whether the auto-build hook has been running, just failed, or is in flight.
|
||||
|
||||
When `graphify.auto_update: true`, the bundled `hooks/gsd-graphify-update.sh` PostToolUse hook fires after HEAD-advancing git operations on the default branch and dispatches `graphify update .` in a detached subprocess. The hook writes a status file synchronously before detach; the detached process rewrites it on completion.
|
||||
|
||||
## The status file
|
||||
|
||||
`.planning/graphs/.last-build-status.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ts": "2026-05-15T14:02:23Z",
|
||||
"status": "running" | "ok" | "failed",
|
||||
"exit_code": null | <int>,
|
||||
"duration_ms": null | <int>,
|
||||
"head_at_build": "<commit-sha>",
|
||||
"graphify_version": null | "<version>"
|
||||
}
|
||||
```
|
||||
|
||||
The hook writes `status: "running"` synchronously **before** detach, so the next planner invocation can see the in-flight signal even if `graphify update .` has not finished. The detached `hooks/lib/gsd-graphify-rebuild.sh` rewrites the file to `ok` or `failed` on completion (with `exit_code` and `duration_ms`).
|
||||
|
||||
## How the planner surfaces it (zero new prompt content)
|
||||
|
||||
`graphifyStatus()` in `gsd-core/bin/lib/graphify.cjs` reads `.last-build-status.json` and folds the `running` / `failed` states into the existing `stale: true` signal:
|
||||
|
||||
```javascript
|
||||
const autoUpdateStale =
|
||||
lastBuildAutoUpdate &&
|
||||
(lastBuildAutoUpdate.status === 'failed' || lastBuildAutoUpdate.status === 'running');
|
||||
|
||||
return {
|
||||
...
|
||||
stale: age > STALE_MS || Boolean(autoUpdateStale),
|
||||
...
|
||||
last_build_auto_update: lastBuildAutoUpdate || null,
|
||||
};
|
||||
```
|
||||
|
||||
The planner and researcher already run `node ... graphify status` inside their `<step name="load_graph_context">` blocks and already have the rule:
|
||||
|
||||
> If the status response has `stale: true`, note for later: "Graph is `{age_hours}h` old — treat semantic relationships as approximate."
|
||||
|
||||
That rule now fires correctly in three additional cases:
|
||||
|
||||
| Trigger | What user sees |
|
||||
|---------|----------------|
|
||||
| Auto-build status = `failed` | Existing "treat as approximate" note fires (because `stale: true`). The full `last_build_auto_update` object is in the JSON for callers that want exit-code / duration / commit-sha context. |
|
||||
| Auto-build status = `running` | Same — the next planner invocation knows the graph is mid-rebuild and treats it as approximate until the detached process completes. |
|
||||
| Auto-build status = `ok` AND mtime < 24h | Annotation is silent — the graph is fresh and the most recent auto-build succeeded. |
|
||||
|
||||
The file-missing case is silent (the operator either has not opted in or has not yet triggered a HEAD-advancing git op since enabling).
|
||||
|
||||
## Why this design
|
||||
|
||||
- **No planner-side prompt changes.** Folding into `stale: true` reuses the existing rule, which means no new content in `agents/gsd-planner.md` (which is already at the `< 48K` decomposition limit per `DEFECT.AGENT-FILE-SIZE-CAP-BREACH`).
|
||||
- **Tests catch regressions on the seam.** `tests/feat-3347-graphify-auto-update-config.test.cjs` pins `graphifyStatus` behavior for status=`failed` / `running` / `ok` / file-missing.
|
||||
- **Backwards compatible.** Callers that don't read `last_build_auto_update` see the same shape as before, with `stale` reflecting both mtime AND auto-build state. No consumer breakage.
|
||||
|
||||
## Opt-in reminder
|
||||
|
||||
The auto-update mechanism is opt-in (`graphify.auto_update: false` by default per issue #3347). Users who haven't opted in will never produce this file. `graphifyStatus()` returns `last_build_auto_update: null` and falls back to the mtime-only `stale` rule.
|
||||
57
gsd-core/references/planner-human-verify-mode.md
Normal file
57
gsd-core/references/planner-human-verify-mode.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Planner — Human Verification Mode
|
||||
|
||||
> Loaded by `gsd-planner` when deciding whether to emit `<task type="checkpoint:human-verify">` tasks. Read `workflow.human_verify_mode` from `.planning/config.json` (default `end-of-phase` since #3309).
|
||||
|
||||
## The two modes
|
||||
|
||||
### `end-of-phase` (default — issue #3309)
|
||||
|
||||
Do **not** emit any `<task type="checkpoint:human-verify">` tasks. Every mid-flight halt costs a full executor cold-start (CLAUDE.md, MEMORY.md, STATE.md, plan re-read on respawn) because subagent context is discarded across the pause; a plan with N human-verify checkpoints pays the cold-start cost N+1 times — measured at "tens of thousands of tokens" per round-trip on real projects. This is the default for that reason.
|
||||
|
||||
Instead, fold each would-be verification step into the relevant `auto` task using a `<verify><human-check>` sub-block:
|
||||
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Wire dashboard route</name>
|
||||
<files>app/dashboard/page.tsx, app/api/dashboard/route.ts</files>
|
||||
<action>...</action>
|
||||
<verify>
|
||||
<automated>npm test -- --filter=dashboard</automated>
|
||||
<human-check>
|
||||
<test>Visit http://localhost:3000/dashboard</test>
|
||||
<expected>Sidebar left, content right on desktop >1024px; collapses to hamburger at 768px</expected>
|
||||
<why_human>Visual layout — grep cannot verify breakpoint behavior</why_human>
|
||||
</human-check>
|
||||
</verify>
|
||||
<done>Layout renders correctly across breakpoints</done>
|
||||
</task>
|
||||
```
|
||||
|
||||
The verifier (Step 8) harvests every `<verify><human-check>` block at end-of-phase and consolidates them into the existing `human_needed` → `{phase_num}-UAT.md` path in `workflows/execute-phase.md`. The user reviews everything in one batch instead of paying a cold-start cost per item.
|
||||
|
||||
### `mid-flight` (opt-back-in — pre-#3309 behavior)
|
||||
|
||||
Set `gsd config-set workflow.human_verify_mode mid-flight` to restore the canonical mid-flight pattern: emit `<task type="checkpoint:human-verify">` tasks at the points where human confirmation is required, and the executor halts at each one to ask the user.
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Dev server running at http://localhost:3000</what-built>
|
||||
<how-to-verify>
|
||||
1. Visit /dashboard
|
||||
2. Sidebar collapses at 768px
|
||||
</how-to-verify>
|
||||
<resume-signal>"approved" or describe issues</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
Choose `mid-flight` when you genuinely need the work to stop before any subsequent task runs (e.g., the next task depends on visual confirmation of the previous one), and you accept the cold-start cost as the price of that hard barrier.
|
||||
|
||||
## What is *not* affected
|
||||
|
||||
`checkpoint:decision` and `checkpoint:human-action` tasks are still emitted in `end-of-phase` mode. Those gate the work itself (a choice the executor needs from the user, or an auth step only the user can perform), not post-hoc verification of completed work. Only `checkpoint:human-verify` is suppressed.
|
||||
|
||||
## Compatibility with other modes
|
||||
|
||||
- **`workflow.tdd_mode`**: orthogonal. TDD tasks still emit `tdd="true"` and `<behavior>`; the `<verify>` block carries the human-check sub-element when `human_verify_mode = end-of-phase`.
|
||||
- **`MVP_MODE`**: orthogonal. Vertical-slice ordering is unchanged. The first task remains a failing end-to-end test; later auto tasks may carry `<verify><human-check>` instead of standalone checkpoint tasks.
|
||||
- **`workflow.auto_advance` / `_auto_chain_active`**: in mid-flight mode these auto-approve checkpoint:human-verify halts. In end-of-phase mode there are no halts to auto-approve, so the flags have no effect on this code path.
|
||||
62
gsd-core/references/planner-interface-context.md
Normal file
62
gsd-core/references/planner-interface-context.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Interface Context for Executors
|
||||
|
||||
**Key insight:** "The difference between handing a contractor blueprints versus telling them 'build me a house.'"
|
||||
|
||||
When creating plans that depend on existing code or create new interfaces consumed by other plans:
|
||||
|
||||
## For plans that USE existing code:
|
||||
After determining `files_modified`, extract the key interfaces/types/exports from the codebase that executors will need:
|
||||
|
||||
```bash
|
||||
# Extract type definitions, interfaces, and exports from relevant files
|
||||
grep -n "export\\|interface\\|type\\|class\\|function" {relevant_source_files} 2>/dev/null | head -50
|
||||
```
|
||||
|
||||
Embed these in the plan's `<context>` section as an `<interfaces>` block:
|
||||
|
||||
```xml
|
||||
<interfaces>
|
||||
<!-- Key types and contracts the executor needs. Extracted from codebase. -->
|
||||
<!-- Executor should use these directly — no codebase exploration needed. -->
|
||||
|
||||
From src/types/user.ts:
|
||||
```typescript
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
From src/api/auth.ts:
|
||||
```typescript
|
||||
export function validateToken(token: string): Promise<User | null>;
|
||||
export function createSession(user: User): Promise<SessionToken>;
|
||||
```
|
||||
</interfaces>
|
||||
```
|
||||
|
||||
## For plans that CREATE new interfaces:
|
||||
If this plan creates types/interfaces that later plans depend on, include a "Wave 0" skeleton step:
|
||||
|
||||
```xml
|
||||
<task type="auto">
|
||||
<name>Task 0: Write interface contracts</name>
|
||||
<files>src/types/newFeature.ts</files>
|
||||
<action>Create type definitions that downstream plans will implement against. These are the contracts — implementation comes in later tasks.</action>
|
||||
<verify>File exists with exported types, no implementation</verify>
|
||||
<done>Interface file committed, types exported</done>
|
||||
</task>
|
||||
```
|
||||
|
||||
## When to include interfaces:
|
||||
- Plan touches files that import from other modules → extract those module's exports
|
||||
- Plan creates a new API endpoint → extract the request/response types
|
||||
- Plan modifies a component → extract its props interface
|
||||
- Plan depends on a previous plan's output → extract the types from that plan's files_modified
|
||||
|
||||
## When to skip:
|
||||
- Plan is self-contained (creates everything from scratch, no imports)
|
||||
- Plan is pure configuration (no code interfaces involved)
|
||||
- Level 0 discovery (all patterns already established)
|
||||
53
gsd-core/references/planner-mvp-mode.md
Normal file
53
gsd-core/references/planner-mvp-mode.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Planner — MVP Mode (Vertical Slice Strategy)
|
||||
|
||||
> Loaded by `gsd-planner` only when `MVP_MODE=true`. Standard horizontal-layer planning rules continue to apply for all other phases.
|
||||
|
||||
## Core Rule
|
||||
|
||||
**Decompose by feature slice, not by technical layer.** Every task must move the user-facing capability forward. After each task, a real user can click through more of the feature than they could before.
|
||||
|
||||
**Forbidden** in MVP mode:
|
||||
- "Create the database schema" as a standalone task
|
||||
- "Build the API layer" as a standalone task
|
||||
- "Wire up the UI" as a final integration task
|
||||
|
||||
**Required** in MVP mode:
|
||||
- The first non-test task produces a working end-to-end path. Stubs are allowed for non-critical branches; the happy path must be real.
|
||||
- Each subsequent task either adds a new slice OR refines an existing slice (validation, error states, edge cases).
|
||||
- The phase goal is framed as a user story: "**As a** [user], **I want to** [do X], **so that** [Y]."
|
||||
|
||||
## Task Order Pattern
|
||||
|
||||
For a feature `F`:
|
||||
|
||||
1. **Failing end-to-end test** for the happy path of `F`.
|
||||
2. **Thinnest viable slice** — UI form → API endpoint → DB read/write — that makes the test pass. Hard-coded values, missing validation, no error states are fine here.
|
||||
3. **Real data layer** — replace any stubs from Task 2 with real queries.
|
||||
4. **Validation + error states** — invalid input, network failure, empty states.
|
||||
5. **Production polish** — loading indicators, edge cases, accessibility checks.
|
||||
|
||||
Tasks 3-5 are not always all needed; gate by the phase's acceptance criteria.
|
||||
|
||||
## Walking Skeleton Mode (`WALKING_SKELETON=true`)
|
||||
|
||||
When the orchestrator sets `WALKING_SKELETON=true` (Phase 1 of a new project under `--mvp`), the plan changes shape:
|
||||
|
||||
- The "feature" is the application itself. Pick the smallest meaningful capability that proves the full stack works (e.g., "user can sign up and see their name on a dashboard").
|
||||
- The plan **must include**:
|
||||
- Project scaffold (framework init, routing, build, lint)
|
||||
- One real DB read/write
|
||||
- One real UI interaction wired to the API
|
||||
- Deployment to a dev environment (or a documented local-run command that exercises the full stack)
|
||||
- The plan **must produce** `SKELETON.md` in the phase directory alongside `PLAN.md`. Use the template at `@~/.claude/gsd-core/references/skeleton-template.md`. `SKELETON.md` records the architectural decisions that subsequent phases will build on (chosen framework, DB, deployment target, auth approach, directory layout).
|
||||
|
||||
`SKELETON.md` is the architectural backbone for every later vertical slice; treat it as a contract, not a scratchpad.
|
||||
|
||||
## Anti-Patterns to Reject
|
||||
|
||||
- **Layer cake disguised as slices.** Three "vertical" tasks where Task 1 is "all the schemas", Task 2 is "all the endpoints", Task 3 is "all the UI" — that is horizontal planning with new labels. Reject.
|
||||
- **Skeleton bloat.** Walking Skeleton is the *thinnest* working stack, not "Phase 1 of a normal app." If Skeleton has more than ~5 tasks, you are not skeletonizing.
|
||||
- **Premature SPIDR splitting.** SPIDR splitting is the `mvp-phase` command's job (Phase 2 of the PRD), not the planner's. If the phase scope feels too large, surface it via the verification loop, do not split silently.
|
||||
|
||||
## Acceptance Test for Your Plan
|
||||
|
||||
Before emitting the plan, ask: **after Task N completes, can a real user *do* something they could not do after Task N-1?** If the answer is "no, but the foundation is laid", you have a horizontal task disguised as a slice. Restructure.
|
||||
39
gsd-core/references/planner-reviews.md
Normal file
39
gsd-core/references/planner-reviews.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Reviews Mode — Planner Reference
|
||||
|
||||
Triggered when orchestrator sets Mode to `reviews`. Replanning from scratch with REVIEWS.md feedback as additional context.
|
||||
|
||||
**Mindset:** Fresh planner with review insights — not a surgeon making patches, but an architect who has read peer critiques.
|
||||
|
||||
### Step 1: Load REVIEWS.md
|
||||
Read the reviews file from `<files_to_read>`. Parse:
|
||||
- Per-reviewer feedback (strengths, concerns, suggestions)
|
||||
- Consensus Summary (agreed concerns = highest priority to address)
|
||||
- Divergent Views (investigate, make a judgment call)
|
||||
|
||||
### Step 2: Categorize Feedback
|
||||
Group review feedback into:
|
||||
- **Must address**: HIGH severity consensus concerns
|
||||
- **Should address**: MEDIUM severity concerns from 2+ reviewers
|
||||
- **Consider**: Individual reviewer suggestions, LOW severity items
|
||||
|
||||
### Step 3: Plan Fresh with Review Context
|
||||
Create new plans following the standard planning process, but with review feedback as additional constraints:
|
||||
- Each HIGH severity consensus concern MUST have a task that addresses it
|
||||
- MEDIUM concerns should be addressed where feasible without over-engineering
|
||||
- Note in task actions: "Addresses review concern: {concern}" for traceability
|
||||
|
||||
### Step 4: Return
|
||||
Use standard PLANNING COMPLETE return format, adding a reviews section:
|
||||
|
||||
```markdown
|
||||
### Review Feedback Addressed
|
||||
|
||||
| Concern | Severity | How Addressed |
|
||||
|---------|----------|---------------|
|
||||
| {concern} | HIGH | Plan {N}, Task {M}: {how} |
|
||||
|
||||
### Review Feedback Deferred
|
||||
| Concern | Reason |
|
||||
|---------|--------|
|
||||
| {concern} | {why — out of scope, disagree, etc.} |
|
||||
```
|
||||
87
gsd-core/references/planner-revision.md
Normal file
87
gsd-core/references/planner-revision.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Revision Mode — Planner Reference
|
||||
|
||||
Triggered when orchestrator provides `<revision_context>` with checker issues. NOT starting fresh — making targeted updates to existing plans.
|
||||
|
||||
**Mindset:** Surgeon, not architect. Minimal changes for specific issues.
|
||||
|
||||
### Step 1: Load Existing Plans
|
||||
|
||||
```bash
|
||||
cat .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
|
||||
```
|
||||
|
||||
Build mental model of current plan structure, existing tasks, must_haves.
|
||||
|
||||
### Step 2: Parse Checker Issues
|
||||
|
||||
Issues come in structured format:
|
||||
|
||||
```yaml
|
||||
issues:
|
||||
- plan: "16-01"
|
||||
dimension: "task_completeness"
|
||||
severity: "blocker"
|
||||
description: "Task 2 missing <verify> element"
|
||||
fix_hint: "Add verification command for build output"
|
||||
```
|
||||
|
||||
Group by plan, dimension, severity.
|
||||
|
||||
### Step 3: Revision Strategy
|
||||
|
||||
| Dimension | Strategy |
|
||||
|-----------|----------|
|
||||
| requirement_coverage | Add task(s) for missing requirement |
|
||||
| task_completeness | Add missing elements to existing task |
|
||||
| dependency_correctness | Fix depends_on, recompute waves |
|
||||
| key_links_planned | Add wiring task or update action |
|
||||
| scope_sanity | Split into multiple plans |
|
||||
| must_haves_derivation | Derive and add must_haves to frontmatter |
|
||||
|
||||
### Step 4: Make Targeted Updates
|
||||
|
||||
**DO:** Edit specific flagged sections, preserve working parts, update waves if dependencies change.
|
||||
|
||||
**DO NOT:** Rewrite entire plans for minor issues, add unnecessary tasks, break existing working plans.
|
||||
|
||||
### Step 5: Validate Changes
|
||||
|
||||
- [ ] All flagged issues addressed
|
||||
- [ ] No new issues introduced
|
||||
- [ ] Wave numbers still valid
|
||||
- [ ] Dependencies still correct
|
||||
- [ ] Files on disk updated
|
||||
|
||||
### Step 6: Commit
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
|
||||
```
|
||||
|
||||
### Step 7: Return Revision Summary
|
||||
|
||||
```markdown
|
||||
## REVISION COMPLETE
|
||||
|
||||
**Issues addressed:** {N}/{M}
|
||||
|
||||
### Changes Made
|
||||
|
||||
| Plan | Change | Issue Addressed |
|
||||
|------|--------|-----------------|
|
||||
| 16-01 | Added <verify> to Task 2 | task_completeness |
|
||||
| 16-02 | Added logout task | requirement_coverage (AUTH-02) |
|
||||
|
||||
### Files Updated
|
||||
|
||||
- .planning/phases/16-xxx/16-01-PLAN.md
|
||||
- .planning/phases/16-xxx/16-02-PLAN.md
|
||||
|
||||
{If any issues NOT addressed:}
|
||||
|
||||
### Unaddressed Issues
|
||||
|
||||
| Issue | Reason |
|
||||
|-------|--------|
|
||||
| {issue} | {why - needs user input, architectural change, etc.} |
|
||||
```
|
||||
73
gsd-core/references/planner-source-audit.md
Normal file
73
gsd-core/references/planner-source-audit.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Planner Source Audit & Authority Limits
|
||||
|
||||
Reference for `agents/gsd-planner.md` — extended rules for multi-source coverage audits and planner authority constraints.
|
||||
|
||||
## Multi-Source Coverage Audit Format
|
||||
|
||||
Before finalizing plans, produce a **source audit** covering ALL four artifact types:
|
||||
|
||||
```
|
||||
SOURCE | ID | Feature/Requirement | Plan | Status | Notes
|
||||
--------- | ------- | ---------------------------- | ----- | --------- | ------
|
||||
GOAL | — | {phase goal from ROADMAP.md} | 01-03 | COVERED |
|
||||
REQ | REQ-14 | OAuth login with Google + GH | 02 | COVERED |
|
||||
REQ | REQ-22 | Email verification flow | 03 | COVERED |
|
||||
RESEARCH | — | Rate limiting on auth routes | 01 | COVERED |
|
||||
RESEARCH | — | Refresh token rotation | NONE | ⚠ MISSING | No plan covers this
|
||||
CONTEXT | D-01 | Use jose library for JWT | 02 | COVERED |
|
||||
CONTEXT | D-04 | 15min access / 7day refresh | 02 | COVERED |
|
||||
```
|
||||
|
||||
### Four Source Types
|
||||
|
||||
1. **GOAL** — The `goal:` field from ROADMAP.md for this phase. The primary success condition.
|
||||
2. **REQ** — Every REQ-ID in `phase_req_ids`. Cross-reference REQUIREMENTS.md for descriptions.
|
||||
3. **RESEARCH** — Technical approaches, discovered constraints, and features identified in RESEARCH.md. Exclude items explicitly marked "out of scope" or "future work" by the researcher.
|
||||
4. **CONTEXT** — Every D-XX decision from CONTEXT.md `<decisions>` section.
|
||||
|
||||
### What is NOT a Gap
|
||||
|
||||
Do not flag these as MISSING:
|
||||
- Items in `## Deferred Ideas` in CONTEXT.md — developer chose to defer these
|
||||
- Items scoped to a different phase via `phase_req_ids` — not assigned to this phase
|
||||
- Items in RESEARCH.md explicitly marked "out of scope" or "future work" by the researcher
|
||||
|
||||
### Handling MISSING Items
|
||||
|
||||
If ANY row is `⚠ MISSING`, do NOT finalize the plan set silently. Return to the orchestrator:
|
||||
|
||||
```
|
||||
## ⚠ Source Audit: Unplanned Items Found
|
||||
|
||||
The following items from source artifacts have no corresponding plan:
|
||||
|
||||
1. **{SOURCE}: {item description}** (from {artifact file}, section "{section}")
|
||||
- {why this was identified as required}
|
||||
|
||||
Options:
|
||||
A) Add a plan to cover this item
|
||||
B) Split phase: move to a sub-phase
|
||||
C) Defer explicitly: add to backlog with developer confirmation
|
||||
|
||||
→ Awaiting developer decision before finalizing plan set.
|
||||
```
|
||||
|
||||
If ALL rows are COVERED → return `## PLANNING COMPLETE` as normal.
|
||||
|
||||
---
|
||||
|
||||
## Authority Limits — Constraint Examples
|
||||
|
||||
The planner's only legitimate reasons to split or flag a feature are **constraints**, not judgments about difficulty:
|
||||
|
||||
**Valid (constraints):**
|
||||
- ✓ "This task touches 9 files and would consume ~45% context — split into two tasks"
|
||||
- ✓ "No API key or endpoint is defined in any source artifact — need developer input"
|
||||
- ✓ "This feature depends on the auth system built in Phase 03, which is not yet complete"
|
||||
|
||||
**Invalid (difficulty judgments):**
|
||||
- ✗ "This is complex and would be difficult to implement correctly"
|
||||
- ✗ "Integrating with an external service could take a long time"
|
||||
- ✗ "This is a challenging feature that might be better left to a future phase"
|
||||
|
||||
If a feature has none of the three legitimate constraints (context cost, missing information, dependency conflict), it gets planned. Period.
|
||||
471
gsd-core/references/planning-config.md
Normal file
471
gsd-core/references/planning-config.md
Normal file
@@ -0,0 +1,471 @@
|
||||
<planning_config>
|
||||
|
||||
Configuration options for `.planning/` directory behavior.
|
||||
|
||||
<config_schema>
|
||||
```json
|
||||
"planning": {
|
||||
"commit_docs": true,
|
||||
"search_gitignored": false
|
||||
},
|
||||
"git": {
|
||||
"branching_strategy": "none",
|
||||
"base_branch": null,
|
||||
"phase_branch_template": "gsd/phase-{phase}-{slug}",
|
||||
"milestone_branch_template": "gsd/{milestone}-{slug}",
|
||||
"quick_branch_template": null
|
||||
},
|
||||
"manager": {
|
||||
"flags": {
|
||||
"discuss": "",
|
||||
"plan": "",
|
||||
"execute": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `commit_docs` | `true` | Whether to commit planning artifacts to git |
|
||||
| `search_gitignored` | `false` | Add `--no-ignore` to broad rg searches |
|
||||
| `git.branching_strategy` | `"none"` | Git branching approach: `"none"`, `"phase"`, or `"milestone"` |
|
||||
| `git.base_branch` | `null` (auto-detect) | Target branch for PRs and merges (e.g. `"master"`, `"develop"`). When `null`, auto-detects from `git symbolic-ref refs/remotes/origin/HEAD`, falling back to `"main"`. |
|
||||
| `git.create_tag` | `true` | Create git tags on milestone completion |
|
||||
| `git.phase_branch_template` | `"gsd/phase-{phase}-{slug}"` | Branch template for phase strategy |
|
||||
| `git.milestone_branch_template` | `"gsd/{milestone}-{slug}"` | Branch template for milestone strategy |
|
||||
| `git.quick_branch_template` | `null` | Optional branch template for quick-task runs |
|
||||
| `workflow.use_worktrees` | `true` | Whether executor agents run in isolated git worktrees. Set to `false` to disable worktrees — agents execute sequentially on the main working tree instead. Recommended for solo developers or when worktree merges cause issues. |
|
||||
| `workflow.subagent_timeout` | `300000` | Timeout in milliseconds for parallel subagent tasks (e.g. codebase mapping). Increase for large codebases or slower models. Default: 300000 (5 minutes). |
|
||||
| `workflow.inline_plan_threshold` | `2` | Plans with this many tasks or fewer execute inline (Pattern C) instead of spawning a subagent. Avoids ~14K token spawn overhead for small plans. Set to `0` to always spawn subagents. |
|
||||
| `manager.flags.discuss` | `""` | Flags passed to `/gsd:discuss-phase` when dispatched from manager (e.g. `"--auto --analyze"`) |
|
||||
| `manager.flags.plan` | `""` | Flags passed to plan workflow when dispatched from manager |
|
||||
| `manager.flags.execute` | `""` | Flags passed to execute workflow when dispatched from manager |
|
||||
| `response_language` | `null` | Language for user-facing questions and prompts across all phases/subagents (e.g. `"Portuguese"`, `"Japanese"`, `"Spanish"`). When set, all spawned agents include a directive to respond in this language. |
|
||||
</config_schema>
|
||||
|
||||
<commit_docs_behavior>
|
||||
|
||||
**When `commit_docs: true` (default):**
|
||||
- Planning files committed normally
|
||||
- SUMMARY.md, STATE.md, ROADMAP.md tracked in git
|
||||
- Full history of planning decisions preserved
|
||||
|
||||
**When `commit_docs: false`:**
|
||||
- Skip all `git add`/`git commit` for `.planning/` files
|
||||
- User must add `.planning/` to `.gitignore`
|
||||
- Useful for: OSS contributions, client projects, keeping planning private
|
||||
|
||||
**Using `gsd-tools query` (preferred):**
|
||||
|
||||
```bash
|
||||
# Commit with automatic commit_docs + gitignore checks:
|
||||
gsd-tools query commit "docs: update state" --files .planning/STATE.md
|
||||
|
||||
# Load config via state load (returns JSON):
|
||||
INIT=$(gsd-tools query state.load)
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
# commit_docs is available in the JSON output
|
||||
|
||||
# Or use init commands which include commit_docs:
|
||||
INIT=$(gsd-tools query init.execute-phase "1")
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
# commit_docs is included in all init command outputs
|
||||
```
|
||||
|
||||
**Auto-detection:** If `.planning/` is gitignored, `commit_docs` is automatically `false` regardless of config.json. This prevents git errors when users have `.planning/` in `.gitignore`.
|
||||
|
||||
**Commit via CLI (handles checks automatically):**
|
||||
|
||||
```bash
|
||||
gsd-tools query commit "docs: update state" --files .planning/STATE.md
|
||||
```
|
||||
|
||||
The CLI checks `commit_docs` config and gitignore status internally — no manual conditionals needed.
|
||||
|
||||
</commit_docs_behavior>
|
||||
|
||||
<search_behavior>
|
||||
|
||||
**When `search_gitignored: false` (default):**
|
||||
- Standard rg behavior (respects .gitignore)
|
||||
- Direct path searches work: `rg "pattern" .planning/` finds files
|
||||
- Broad searches skip gitignored: `rg "pattern"` skips `.planning/`
|
||||
|
||||
**When `search_gitignored: true`:**
|
||||
- Add `--no-ignore` to broad rg searches that should include `.planning/`
|
||||
- Only needed when searching entire repo and expecting `.planning/` matches
|
||||
|
||||
**Note:** Most GSD operations use direct file reads or explicit paths, which work regardless of gitignore status.
|
||||
|
||||
</search_behavior>
|
||||
|
||||
<setup_uncommitted_mode>
|
||||
|
||||
To use uncommitted mode:
|
||||
|
||||
1. **Set config:**
|
||||
```json
|
||||
"planning": {
|
||||
"commit_docs": false,
|
||||
"search_gitignored": true
|
||||
}
|
||||
```
|
||||
|
||||
2. **Add to .gitignore:**
|
||||
```
|
||||
.planning/
|
||||
```
|
||||
|
||||
3. **Existing tracked files:** If `.planning/` was previously tracked:
|
||||
```bash
|
||||
git rm -r --cached .planning/
|
||||
git commit -m "chore: stop tracking planning docs"
|
||||
```
|
||||
|
||||
4. **Branch merges:** When using `branching_strategy: phase` or `milestone`, the `complete-milestone` workflow automatically strips `.planning/` files from staging before merge commits when `commit_docs: false`.
|
||||
|
||||
</setup_uncommitted_mode>
|
||||
|
||||
<branching_strategy_behavior>
|
||||
|
||||
**Branching Strategies:**
|
||||
|
||||
| Strategy | When branch created | Branch scope | Merge point |
|
||||
|----------|---------------------|--------------|-------------|
|
||||
| `none` | Never | N/A | N/A |
|
||||
| `phase` | At `execute-phase` start | Single phase | User merges after phase |
|
||||
| `milestone` | At first `execute-phase` of milestone | Entire milestone | At `complete-milestone` |
|
||||
|
||||
**When `git.branching_strategy: "none"` (default):**
|
||||
- All work commits to current branch
|
||||
- Standard GSD behavior
|
||||
|
||||
**When `git.branching_strategy: "phase"`:**
|
||||
- `execute-phase` creates/switches to a branch before execution
|
||||
- Branch name from `phase_branch_template` (e.g., `gsd/phase-03-authentication`)
|
||||
- All plan commits go to that branch
|
||||
- User merges branches manually after phase completion
|
||||
- `complete-milestone` offers to merge all phase branches
|
||||
|
||||
**When `git.branching_strategy: "milestone"`:**
|
||||
- First `execute-phase` of milestone creates the milestone branch
|
||||
- Branch name from `milestone_branch_template` (e.g., `gsd/v1.0-mvp`)
|
||||
- All phases in milestone commit to same branch
|
||||
- `complete-milestone` offers to merge milestone branch to main
|
||||
|
||||
**Template variables:**
|
||||
|
||||
| Variable | Available in | Description |
|
||||
|----------|--------------|-------------|
|
||||
| `{phase}` | phase_branch_template | Zero-padded phase number (e.g., "03") |
|
||||
| `{slug}` | Both | Lowercase, hyphenated name |
|
||||
| `{milestone}` | milestone_branch_template | Milestone version (e.g., "v1.0") |
|
||||
|
||||
**Checking the config:**
|
||||
|
||||
Use `init execute-phase` which returns all config as JSON:
|
||||
```bash
|
||||
INIT=$(gsd-tools query init.execute-phase "1")
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
# JSON output includes: branching_strategy, phase_branch_template, milestone_branch_template
|
||||
```
|
||||
|
||||
Or use `state load` for the config values:
|
||||
```bash
|
||||
INIT=$(gsd-tools query state.load)
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
# Parse branching_strategy, phase_branch_template, milestone_branch_template from JSON
|
||||
```
|
||||
|
||||
**Branch creation:**
|
||||
|
||||
```bash
|
||||
# For phase strategy
|
||||
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
|
||||
PHASE_SLUG=$(echo "$PHASE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
||||
BRANCH_NAME=$(echo "$PHASE_BRANCH_TEMPLATE" | sed "s/{phase}/$PADDED_PHASE/g" | sed "s/{slug}/$PHASE_SLUG/g")
|
||||
git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
|
||||
fi
|
||||
|
||||
# For milestone strategy
|
||||
if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
|
||||
MILESTONE_SLUG=$(echo "$MILESTONE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
||||
BRANCH_NAME=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed "s/{milestone}/$MILESTONE_VERSION/g" | sed "s/{slug}/$MILESTONE_SLUG/g")
|
||||
git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
|
||||
fi
|
||||
```
|
||||
|
||||
**Merge options at complete-milestone:**
|
||||
|
||||
| Option | Git command | Result |
|
||||
|--------|-------------|--------|
|
||||
| Squash merge (recommended) | `git merge --squash` | Single clean commit per branch |
|
||||
| Merge with history | `git merge --no-ff` | Preserves all individual commits |
|
||||
| Delete without merging | `git branch -D` | Discard branch work |
|
||||
| Keep branches | (none) | Manual handling later |
|
||||
|
||||
Squash merge is recommended — keeps main branch history clean while preserving the full development history in the branch (until deleted).
|
||||
|
||||
**Use cases:**
|
||||
|
||||
| Strategy | Best for |
|
||||
|----------|----------|
|
||||
| `none` | Solo development, simple projects |
|
||||
| `phase` | Code review per phase, granular rollback, team collaboration |
|
||||
| `milestone` | Release branches, staging environments, PR per version |
|
||||
|
||||
</branching_strategy_behavior>
|
||||
|
||||
<complete_field_reference>
|
||||
|
||||
## Complete Field Reference
|
||||
|
||||
Generated from `CONFIG_DEFAULTS` (core.cjs) and `VALID_CONFIG_KEYS` (config.cjs).
|
||||
|
||||
### Core Fields
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `model_profile` | string | `"balanced"` | `"quality"`, `"balanced"`, `"budget"`, `"adaptive"`, `"inherit"` | Model selection preset for subagents |
|
||||
| `mode` | string | `"interactive"` | `"interactive"`, `"yolo"` | Operation mode: `"interactive"` shows gates and confirmations; `"yolo"` runs autonomously without prompts |
|
||||
| `granularity` | string | (none) | `"coarse"`, `"standard"`, `"fine"` | Planning depth for phase plans (migrated from deprecated `depth`) |
|
||||
| `commit_docs` | boolean | `true` | `true`, `false` | Commit .planning/ artifacts to git (auto-false if .planning/ is gitignored) |
|
||||
| `search_gitignored` | boolean | `false` | `true`, `false` | Include gitignored paths in broad rg searches via `--no-ignore` |
|
||||
| `phase_naming` | string | `"sequential"` | `"sequential"`, `"custom"` | Phase numbering: auto-increment or arbitrary string IDs |
|
||||
| `project_code` | string\|null | `null` | Any short string | Prefix for phase dirs (e.g., `"CK"` produces `CK-01-foundation`) |
|
||||
| `response_language` | string\|null | `null` | Any language name | Language for user-facing prompts (e.g., `"Portuguese"`, `"Japanese"`) |
|
||||
| `context_window` | number | `200000` | `200000`, `1000000` | Context window size; set `1000000` for 1M-context models |
|
||||
| `resolve_model_ids` | boolean\|string | `false` | `false`, `true`, `"omit"` | Map model aliases to full Claude IDs; `"omit"` returns empty string |
|
||||
| `context` | string\|null | `null` | `"dev"`, `"research"`, `"review"` | Execution context profile that adjusts agent behavior: `"dev"` for development tasks, `"research"` for investigation/exploration, `"review"` for code review workflows |
|
||||
| `review.models.<cli>` | string\|null | `null` | Any model ID string | Per-CLI model override for /gsd:review (e.g., `review.models.gemini`). Falls back to CLI default when null. |
|
||||
|
||||
### Workflow Fields
|
||||
|
||||
Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `workflow.research` | boolean | `true` | `true`, `false` | Run research agent before planning |
|
||||
| `workflow.plan_check` | boolean | `true` | `true`, `false` | Run plan-checker agent to validate plans. _Alias:_ `plan_checker` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.plan_check` is the canonical namespaced form. |
|
||||
| `workflow.verifier` | boolean | `true` | `true`, `false` | Run verifier agent after execution |
|
||||
| `workflow.nyquist_validation` | boolean | `true` | `true`, `false` | Enable Nyquist-inspired validation gates |
|
||||
| `workflow.auto_prune_state` | boolean | `false` | `true`, `false` | Automatically prune old STATE.md entries on phase completion (keeps 3 most recent phases) |
|
||||
| `workflow.auto_advance` | boolean | `false` | `true`, `false` | Auto-advance to next phase after completion |
|
||||
| `workflow.node_repair` | boolean | `true` | `true`, `false` | Attempt automatic repair of failed plan nodes |
|
||||
| `workflow.node_repair_budget` | number | `2` | Any positive integer | Max repair retries per failed node |
|
||||
| `workflow.ai_integration_phase` | boolean | `true` | `true`, `false` | Run /gsd:ai-integration-phase before planning AI system phases |
|
||||
| `workflow.ui_phase` | boolean | `true` | `true`, `false` | Generate UI-SPEC.md for frontend phases |
|
||||
| `workflow.ui_safety_gate` | boolean | `true` | `true`, `false` | Require safety gate approval for UI changes |
|
||||
| `workflow.text_mode` | boolean | `false` | `true`, `false` | Use plain-text numbered lists instead of AskUserQuestion menus |
|
||||
| `workflow.research_before_questions` | boolean | `false` | `true`, `false` | Run research before interactive questions in discuss phase |
|
||||
| `workflow.discuss_mode` | string | `"discuss"` | `"discuss"`, `"assumptions"` | Default mode for discuss-phase: `"discuss"` runs interactive questioning; `"assumptions"` analyzes codebase and surfaces assumptions instead |
|
||||
| `workflow.skip_discuss` | boolean | `false` | `true`, `false` | Skip discuss phase entirely |
|
||||
| `workflow.use_worktrees` | boolean | `true` | `true`, `false` | Run executor agents in isolated git worktrees |
|
||||
| `workflow.subagent_timeout` | number | `300000` | Any positive integer (ms) | Timeout for parallel subagent tasks (default: 5 minutes) |
|
||||
| `workflow.inline_plan_threshold` | number | `2` | `0`–`10` | Plans with ≤N tasks execute inline instead of spawning a subagent |
|
||||
| `workflow.code_review` | boolean | `true` | `true`, `false` | Enable built-in code review step in the ship workflow |
|
||||
| `workflow.code_review_depth` | string | `"standard"` | `"light"`, `"standard"`, `"deep"` | Depth level for code review analysis in the ship workflow |
|
||||
| `workflow._auto_chain_active` | boolean | `false` | `true`, `false` | Internal: tracks whether autonomous chaining is active |
|
||||
| `workflow.security_enforcement` | boolean | `true` | `true`, `false` | Enable threat-model-anchored security verification via `/gsd:secure-phase`. When `false`, security checks are skipped entirely |
|
||||
| `workflow.security_asvs_level` | number | `1` | `1`, `2`, `3` | OWASP ASVS verification level. Level 1 = opportunistic, Level 2 = standard, Level 3 = comprehensive |
|
||||
| `workflow.security_block_on` | string | `"high"` | `"high"`, `"medium"`, `"low"` | Minimum severity that blocks phase advancement |
|
||||
| `workflow.post_planning_gaps` | boolean | `true` | `true`, `false` | Post-planning gap report (#2493). After plans are generated, scans REQUIREMENTS.md and CONTEXT.md `<decisions>` against all PLAN.md files and emits a unified `Source \| Item \| Status` table. Non-blocking. Set to `false` to skip Step 13e of plan-phase. _Alias:_ `post_planning_gaps` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.post_planning_gaps` is the canonical namespaced form. |
|
||||
|
||||
### Ship Fields
|
||||
|
||||
Set via `ship.*` namespace in config.json. These fields affect `/gsd:ship` PRD-style pull request body composition only.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `ship.pr_body_sections` | array | `[]` | Array of section objects | Append-only project-specific PR body sections. Each entry has `heading`, optional `enabled`, and one or more of `source`, `template`, or `fallback`. Disabled entries remain in onboarding config but do not render. Core sections remain required and cannot be removed or replaced. |
|
||||
|
||||
### Git Fields
|
||||
|
||||
Set via `git.*` namespace (e.g., `"git": { "branching_strategy": "phase" }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `git.branching_strategy` | string | `"none"` | `"none"`, `"phase"`, `"milestone"` | Git branching approach for phase/milestone isolation |
|
||||
| `git.base_branch` | string\|null | `null` (auto-detect) | Any branch name | Target branch for PRs and merges; auto-detects from `origin/HEAD` when `null` |
|
||||
| `git.create_tag` | boolean | `true` | `true`, `false` | Create git tags on milestone completion |
|
||||
| `git.phase_branch_template` | string | `"gsd/phase-{phase}-{slug}"` | Template with `{phase}`, `{slug}` | Branch naming template for `phase` strategy |
|
||||
| `git.milestone_branch_template` | string | `"gsd/{milestone}-{slug}"` | Template with `{milestone}`, `{slug}` | Branch naming template for `milestone` strategy |
|
||||
| `git.quick_branch_template` | string\|null | `null` | Template with `{slug}` | Optional branch template for quick-task runs |
|
||||
|
||||
### Search & API Fields
|
||||
|
||||
These toggle external search integrations. Auto-detected at project creation when API keys are present.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `brave_search` | boolean | `false` | `true`, `false` | Enable Brave web search for research agent (requires `BRAVE_API_KEY`) |
|
||||
| `firecrawl` | boolean | `false` | `true`, `false` | Enable Firecrawl page scraping (requires `FIRECRAWL_API_KEY`) |
|
||||
| `exa_search` | boolean | `false` | `true`, `false` | Enable Exa semantic search (requires `EXA_API_KEY`) |
|
||||
|
||||
### Features Fields
|
||||
|
||||
Set via `features.*` namespace (e.g., `"features": { "thinking_partner": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `features.thinking_partner` | boolean | `false` | `true`, `false` | Enable conditional extended thinking at workflow decision points (used by discuss-phase and plan-phase for architectural tradeoff analysis) |
|
||||
| `features.global_learnings` | boolean | `false` | `true`, `false` | Enable injection of global learnings from `~/.gsd/learnings/` into agent prompts |
|
||||
|
||||
### Hook Fields
|
||||
|
||||
Set via `hooks.*` namespace (e.g., `"hooks": { "context_warnings": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `hooks.context_warnings` | boolean | `true` | `true`, `false` | Show warnings when context budget is exceeded |
|
||||
|
||||
### Learnings Fields
|
||||
|
||||
Set via `learnings.*` namespace (e.g., `"learnings": { "max_inject": 5 }`). Used together with `features.global_learnings`.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `learnings.max_inject` | number | `10` | Any positive integer | Maximum number of global learning entries to inject into agent prompts per session |
|
||||
|
||||
### Intel Fields
|
||||
|
||||
Set via `intel.*` namespace (e.g., `"intel": { "enabled": true }`). Controls the queryable codebase intelligence system consumed by `/gsd:map-codebase --query`.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `intel.enabled` | boolean | `false` | `true`, `false` | Enable queryable codebase intelligence system. When `true`, `/gsd:map-codebase --query` builds and queries a JSON index in `.planning/intel/`. |
|
||||
|
||||
### Manager Fields
|
||||
|
||||
Set via `manager.*` namespace (e.g., `"manager": { "flags": { "discuss": "--auto" } }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `manager.flags.discuss` | string | `""` | Any CLI flags string | Flags passed to `/gsd:discuss-phase` from manager (e.g., `"--auto --analyze"`) |
|
||||
| `manager.flags.plan` | string | `""` | Any CLI flags string | Flags passed to plan workflow from manager |
|
||||
| `manager.flags.execute` | string | `""` | Any CLI flags string | Flags passed to execute workflow from manager |
|
||||
|
||||
### Advanced Fields
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `parallelization` | boolean\|object | `true` | `true`, `false`, `{ "enabled": true }` | Enable parallel wave execution; object form allows additional sub-keys |
|
||||
| `model_overrides` | object\|null | `null` | `{ "<agent-type>": "<model-id>" }` | Override model selection per agent type |
|
||||
| `agent_skills` | object | `{}` | `{ "<agent-type>": "<skill-set>" }` | Assign skill sets to specific agent types |
|
||||
| `sub_repos` | array | `[]` | Array of relative path strings | Child directories with independent `.git` repos (auto-detected) |
|
||||
|
||||
### Planning Fields
|
||||
|
||||
These can be set at top level or nested under `planning.*` (e.g., `"planning": { "commit_docs": false }`). Both forms are equivalent; top-level takes precedence if both exist.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `planning.commit_docs` | boolean | `true` | `true`, `false` | Alias for top-level `commit_docs` |
|
||||
| `planning.search_gitignored` | boolean | `false` | `true`, `false` | Alias for top-level `search_gitignored` |
|
||||
|
||||
---
|
||||
|
||||
## Field Interactions
|
||||
|
||||
Several config fields affect each other or trigger special behavior:
|
||||
|
||||
1. **`commit_docs` auto-detection** -- When no explicit value is set in config.json and `.planning/` is in `.gitignore`, `commit_docs` automatically resolves to `false`. An explicit `true` or `false` in config always overrides auto-detection.
|
||||
|
||||
2. **`branching_strategy` controls branch templates** -- The `phase_branch_template` and `milestone_branch_template` fields are only used when `branching_strategy` is set to `"phase"` or `"milestone"` respectively. When `branching_strategy` is `"none"`, all template fields are ignored.
|
||||
|
||||
3. **`context_window` threshold triggers** -- When `context_window >= 500000`, workflows enable adaptive context enrichment: full-body reads of prior phase SUMMARYs, cross-phase context injection in plan-phase, and deeper read depth for anti-pattern references. Below 500000, only frontmatter and summaries are read.
|
||||
|
||||
4. **`parallelization` polymorphism** -- Accepts both a simple boolean and an object with an `enabled` field. `loadConfig()` normalizes either form to a boolean. `{ "enabled": true }` is equivalent to `true`.
|
||||
|
||||
5. **Search API keys and flags** -- `brave_search`, `firecrawl`, and `exa_search` are auto-set to `true` during project creation if the corresponding API key is detected (environment variable or `~/.gsd/<name>_api_key` file). Setting them to `true` without the API key has no effect.
|
||||
|
||||
6. **`planning.*` and top-level equivalence** -- `planning.commit_docs` and `commit_docs` are equivalent; `planning.search_gitignored` and `search_gitignored` are equivalent. If both are set, the top-level value takes precedence.
|
||||
|
||||
7. **`depth` to `granularity` migration** -- The deprecated `depth` key (`quick`/`standard`/`comprehensive`) is automatically migrated to `granularity` (`coarse`/`standard`/`fine`) on config load and persisted back to disk.
|
||||
|
||||
8. **`sub_repos` auto-sync** -- On every config load, GSD scans for child directories with `.git` and updates the `sub_repos` array if the filesystem has changed. Legacy `multiRepo: true` is automatically migrated to a detected `sub_repos` array.
|
||||
|
||||
---
|
||||
|
||||
## Example Configurations
|
||||
|
||||
### Minimal -- Solo Developer
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "balanced",
|
||||
"commit_docs": true,
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"use_worktrees": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Team Project with Branching
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "quality",
|
||||
"commit_docs": true,
|
||||
"project_code": "APP",
|
||||
"git": {
|
||||
"branching_strategy": "phase",
|
||||
"base_branch": "develop",
|
||||
"phase_branch_template": "gsd/phase-{phase}-{slug}"
|
||||
},
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"nyquist_validation": true,
|
||||
"use_worktrees": true,
|
||||
"discuss_mode": "discuss"
|
||||
},
|
||||
"manager": {
|
||||
"flags": {
|
||||
"discuss": "",
|
||||
"plan": "",
|
||||
"execute": ""
|
||||
}
|
||||
},
|
||||
"response_language": "English"
|
||||
}
|
||||
```
|
||||
|
||||
### Large Codebase -- 1M Context with Extended Timeouts
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "quality",
|
||||
"context_window": 1000000,
|
||||
"commit_docs": true,
|
||||
"project_code": "MEGA",
|
||||
"phase_naming": "sequential",
|
||||
"git": {
|
||||
"branching_strategy": "milestone",
|
||||
"milestone_branch_template": "gsd/{milestone}-{slug}"
|
||||
},
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"nyquist_validation": true,
|
||||
"subagent_timeout": 600000,
|
||||
"use_worktrees": true,
|
||||
"node_repair": true,
|
||||
"node_repair_budget": 3,
|
||||
"auto_advance": true
|
||||
},
|
||||
"brave_search": true,
|
||||
"hooks": {
|
||||
"context_warnings": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</complete_field_reference>
|
||||
|
||||
</planning_config>
|
||||
19
gsd-core/references/project-skills-discovery.md
Normal file
19
gsd-core/references/project-skills-discovery.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Project Skills Discovery
|
||||
|
||||
Before execution, check for project-defined skills and apply their rules.
|
||||
|
||||
**Discovery steps (shared across all GSD agents):**
|
||||
1. Check `.claude/skills/` or `.agents/skills/` directory — if neither exists, skip.
|
||||
2. List available skills (subdirectories).
|
||||
3. Read `SKILL.md` for each skill (lightweight index, typically ~130 lines).
|
||||
4. Load specific `rules/*.md` files only as needed during the current task.
|
||||
5. Do NOT load full `AGENTS.md` files — they are large (100KB+) and cost significant context.
|
||||
|
||||
**Application** — how to apply the loaded rules depends on the calling agent:
|
||||
- Planners account for project skill patterns and conventions in the plan.
|
||||
- Executors follow skill rules relevant to the task being implemented.
|
||||
- Researchers ensure research output accounts for project skill patterns.
|
||||
- Verifiers apply skill rules when scanning for anti-patterns and verifying quality.
|
||||
- Debuggers follow skill rules relevant to the bug being investigated and the fix being applied.
|
||||
|
||||
The caller's agent file should specify which application applies.
|
||||
162
gsd-core/references/questioning.md
Normal file
162
gsd-core/references/questioning.md
Normal file
@@ -0,0 +1,162 @@
|
||||
<questioning_guide>
|
||||
|
||||
Project initialization is dream extraction, not requirements gathering. You're helping the user discover and articulate what they want to build. This isn't a contract negotiation — it's collaborative thinking.
|
||||
|
||||
<philosophy>
|
||||
|
||||
**You are a thinking partner, not an interviewer.**
|
||||
|
||||
The user often has a fuzzy idea. Your job is to help them sharpen it. Ask questions that make them think "oh, I hadn't considered that" or "yes, that's exactly what I mean."
|
||||
|
||||
Don't interrogate. Collaborate. Don't follow a script. Follow the thread.
|
||||
|
||||
</philosophy>
|
||||
|
||||
<the_goal>
|
||||
|
||||
By the end of questioning, you need enough clarity to write a PROJECT.md that downstream phases can act on:
|
||||
|
||||
- **Research** needs: what domain to research, what the user already knows, what unknowns exist
|
||||
- **Requirements** needs: clear enough vision to scope v1 features
|
||||
- **Roadmap** needs: clear enough vision to decompose into phases, what "done" looks like
|
||||
- **plan-phase** needs: specific requirements to break into tasks, context for implementation choices
|
||||
- **execute-phase** needs: success criteria to verify against, the "why" behind requirements
|
||||
|
||||
A vague PROJECT.md forces every downstream phase to guess. The cost compounds.
|
||||
|
||||
</the_goal>
|
||||
|
||||
<how_to_question>
|
||||
|
||||
**Start open.** Let them dump their mental model. Don't interrupt with structure.
|
||||
|
||||
**Follow energy.** Whatever they emphasized, dig into that. What excited them? What problem sparked this?
|
||||
|
||||
**Challenge vagueness.** Never accept fuzzy answers. "Good" means what? "Users" means who? "Simple" means how?
|
||||
|
||||
**Make the abstract concrete.** "Walk me through using this." "What does that actually look like?"
|
||||
|
||||
**Clarify ambiguity.** "When you say Z, do you mean A or B?" "You mentioned X — tell me more."
|
||||
|
||||
**Know when to stop.** When you understand what they want, why they want it, who it's for, and what done looks like — offer to proceed.
|
||||
|
||||
</how_to_question>
|
||||
|
||||
<question_types>
|
||||
|
||||
Use these as inspiration, not a checklist. Pick what's relevant to the thread.
|
||||
|
||||
**Motivation — why this exists:**
|
||||
- "What prompted this?"
|
||||
- "What are you doing today that this replaces?"
|
||||
- "What would you do if this existed?"
|
||||
|
||||
**Concreteness — what it actually is:**
|
||||
- "Walk me through using this"
|
||||
- "You said X — what does that actually look like?"
|
||||
- "Give me an example"
|
||||
|
||||
**Clarification — what they mean:**
|
||||
- "When you say Z, do you mean A or B?"
|
||||
- "You mentioned X — tell me more about that"
|
||||
|
||||
**Success — how you'll know it's working:**
|
||||
- "How will you know this is working?"
|
||||
- "What does done look like?"
|
||||
|
||||
</question_types>
|
||||
|
||||
<using_askuserquestion>
|
||||
|
||||
Use AskUserQuestion to help users think by presenting concrete options to react to.
|
||||
|
||||
**Good options:**
|
||||
- Interpretations of what they might mean
|
||||
- Specific examples to confirm or deny
|
||||
- Concrete choices that reveal priorities
|
||||
|
||||
**Bad options:**
|
||||
- Generic categories ("Technical", "Business", "Other")
|
||||
- Leading options that presume an answer
|
||||
- Too many options (2-4 is ideal)
|
||||
- Headers longer than 12 characters (hard limit — validation will reject them)
|
||||
|
||||
**Example — vague answer:**
|
||||
User says "it should be fast"
|
||||
|
||||
- header: "Fast"
|
||||
- question: "Fast how?"
|
||||
- options: ["Sub-second response", "Handles large datasets", "Quick to build", "Let me explain"]
|
||||
|
||||
**Example — following a thread:**
|
||||
User mentions "frustrated with current tools"
|
||||
|
||||
- header: "Frustration"
|
||||
- question: "What specifically frustrates you?"
|
||||
- options: ["Too many clicks", "Missing features", "Unreliable", "Let me explain"]
|
||||
|
||||
**Tip for users — modifying an option:**
|
||||
Users who want a slightly modified version of an option can select "Other" and reference the option by number: `#1 but for finger joints only` or `#2 with pagination disabled`. This avoids retyping the full option text.
|
||||
|
||||
</using_askuserquestion>
|
||||
|
||||
<freeform_rule>
|
||||
|
||||
**When the user wants to explain freely, STOP using AskUserQuestion.**
|
||||
|
||||
If a user selects "Other" and their response signals they want to describe something in their own words (e.g., "let me describe it", "I'll explain", "something else", or any open-ended reply that isn't choosing/modifying an existing option), you MUST:
|
||||
|
||||
1. **Ask your follow-up as plain text** — NOT via AskUserQuestion
|
||||
2. **Wait for them to type at the normal prompt**
|
||||
3. **Resume AskUserQuestion** only after processing their freeform response
|
||||
|
||||
The same applies if YOU include a freeform-indicating option (like "Let me explain" or "Describe in detail") and the user selects it.
|
||||
|
||||
**Wrong:** User says "let me describe it" → AskUserQuestion("What feature?", ["Feature A", "Feature B", "Describe in detail"])
|
||||
**Right:** User says "let me describe it" → "Go ahead — what are you thinking?"
|
||||
|
||||
</freeform_rule>
|
||||
|
||||
<context_checklist>
|
||||
|
||||
Use this as a **background checklist**, not a conversation structure. Check these mentally as you go. If gaps remain, weave questions naturally.
|
||||
|
||||
- [ ] What they're building (concrete enough to explain to a stranger)
|
||||
- [ ] Why it needs to exist (the problem or desire driving it)
|
||||
- [ ] Who it's for (even if just themselves)
|
||||
- [ ] What "done" looks like (observable outcomes)
|
||||
|
||||
Four things. If they volunteer more, capture it.
|
||||
|
||||
</context_checklist>
|
||||
|
||||
<decision_gate>
|
||||
|
||||
When you could write a clear PROJECT.md, offer to proceed:
|
||||
|
||||
- header: "Ready?"
|
||||
- question: "I think I understand what you're after. Ready to create PROJECT.md?"
|
||||
- options:
|
||||
- "Create PROJECT.md" — Let's move forward
|
||||
- "Keep exploring" — I want to share more / ask me more
|
||||
|
||||
If "Keep exploring" — ask what they want to add or identify gaps and probe naturally.
|
||||
|
||||
Loop until "Create PROJECT.md" selected.
|
||||
|
||||
</decision_gate>
|
||||
|
||||
<anti_patterns>
|
||||
|
||||
- **Checklist walking** — Going through domains regardless of what they said
|
||||
- **Canned questions** — "What's your core value?" "What's out of scope?" regardless of context
|
||||
- **Corporate speak** — "What are your success criteria?" "Who are your stakeholders?"
|
||||
- **Interrogation** — Firing questions without building on answers
|
||||
- **Rushing** — Minimizing questions to get to "the work"
|
||||
- **Shallow acceptance** — Taking vague answers without probing
|
||||
- **Premature constraints** — Asking about tech stack before understanding the idea
|
||||
- **User skills** — NEVER ask about user's technical experience. Claude builds.
|
||||
|
||||
</anti_patterns>
|
||||
|
||||
</questioning_guide>
|
||||
97
gsd-core/references/revision-loop.md
Normal file
97
gsd-core/references/revision-loop.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Revision Loop Pattern
|
||||
|
||||
Standard pattern for iterative agent revision with feedback. Used when a checker/validator finds issues and the producing agent needs to revise its output.
|
||||
|
||||
---
|
||||
|
||||
## Pattern: Check-Revise-Escalate (max 3 iterations)
|
||||
|
||||
This pattern applies whenever:
|
||||
1. An agent produces output (plans, imports, gap-closure plans)
|
||||
2. A checker/validator evaluates that output
|
||||
3. Issues are found that need revision
|
||||
|
||||
### Flow
|
||||
|
||||
```
|
||||
prev_issue_count = Infinity
|
||||
iteration = 0
|
||||
|
||||
LOOP:
|
||||
1. Run checker/validator on current output
|
||||
2. Read checker results
|
||||
3. If PASSED or only INFO-level issues:
|
||||
-> Accept output, exit loop
|
||||
4. If BLOCKER or WARNING issues found:
|
||||
a. iteration += 1
|
||||
b. If iteration > 3:
|
||||
-> Escalate to user (see "After 3 Iterations" below)
|
||||
c. Parse issue count from checker output
|
||||
d. If issue_count >= prev_issue_count:
|
||||
-> Escalate to user: "Revision loop stalled (issue count not decreasing)"
|
||||
e. prev_issue_count = issue_count
|
||||
f. Re-spawn the producing agent with checker feedback appended
|
||||
g. After revision completes, go to LOOP
|
||||
```
|
||||
|
||||
### Issue Count Tracking
|
||||
|
||||
Track the number of BLOCKER + WARNING issues returned by the checker on each iteration. If the count does not decrease between consecutive iterations, the producing agent is stuck and further iterations will not help. Break early and escalate to the user.
|
||||
|
||||
Display iteration progress before each revision spawn:
|
||||
`Revision iteration {N}/3 -- {blocker_count} blockers, {warning_count} warnings`
|
||||
|
||||
### Re-spawn Prompt Structure
|
||||
|
||||
When re-spawning the producing agent for revision, pass the checker's YAML-formatted issues. The checker's output contains a `## Issues` heading followed by a YAML block. Parse this block and pass it verbatim to the revision agent.
|
||||
|
||||
```
|
||||
<checker_issues>
|
||||
The issues below are in YAML format. Each has: dimension, severity, finding,
|
||||
affected_field, suggested_fix. Address ALL BLOCKER issues. Address WARNING
|
||||
issues where feasible.
|
||||
|
||||
{YAML issues block from checker output -- passed verbatim}
|
||||
</checker_issues>
|
||||
|
||||
<revision_instructions>
|
||||
Address ALL BLOCKER and WARNING issues identified above.
|
||||
- For each BLOCKER: make the required change
|
||||
- For each WARNING: address or explain why it's acceptable
|
||||
- Do NOT introduce new issues while fixing existing ones
|
||||
- Preserve all content not flagged by the checker
|
||||
This is revision iteration {N} of max 3. Previous iteration had {prev_count}
|
||||
issues. You must reduce the count or the loop will terminate.
|
||||
</revision_instructions>
|
||||
```
|
||||
|
||||
### After 3 Iterations
|
||||
|
||||
If issues persist after 3 revision cycles:
|
||||
|
||||
1. Present remaining issues to the user
|
||||
2. Use gate prompt (pattern: yes-no from `references/gate-prompts.md`):
|
||||
question: "Issues remain after 3 revision attempts. Proceed with current output?"
|
||||
header: "Proceed?"
|
||||
options:
|
||||
- label: "Proceed anyway" description: "Accept output with remaining issues"
|
||||
- label: "Adjust approach" description: "Discuss a different approach"
|
||||
3. If "Proceed anyway": accept current output and continue
|
||||
4. If "Adjust approach" or "Other": discuss with user, then re-enter the producing step with updated context
|
||||
|
||||
### Workflow-Specific Variations
|
||||
|
||||
| Workflow | Producer Agent | Checker Agent | Notes |
|
||||
|----------|---------------|---------------|-------|
|
||||
| plan-phase | gsd-planner | gsd-plan-checker | Revision prompt via planner-revision.md |
|
||||
| execute-phase | gsd-executor | gsd-verifier | Post-execution verification |
|
||||
| discuss-phase | orchestrator | gsd-plan-checker | Inline revision by orchestrator |
|
||||
|
||||
---
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **INFO-level issues are always acceptable** -- they don't trigger revision
|
||||
- **Each iteration gets a fresh agent spawn** -- don't try to continue in the same context
|
||||
- **Checker feedback must be inlined** -- the revision agent needs to see exactly what failed
|
||||
- **Don't silently swallow issues** -- always present the final state to the user after exiting the loop
|
||||
51
gsd-core/references/scout-codebase.md
Normal file
51
gsd-core/references/scout-codebase.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Codebase scout — map selection table
|
||||
|
||||
> Lazy-loaded reference for the `scout_codebase` step in
|
||||
> `workflows/discuss-phase.md` (extracted via #2551 progressive-disclosure
|
||||
> refactor). Read this only when prior `.planning/codebase/*.md` maps exist
|
||||
> and the workflow needs to pick which 2–3 to load.
|
||||
|
||||
## Phase-type → recommended maps
|
||||
|
||||
Read 2–3 maps based on inferred phase type. Do NOT read all seven —
|
||||
that inflates context without improving discussion quality.
|
||||
|
||||
| Phase type (infer from title + ROADMAP entry) | Read these maps |
|
||||
|---|---|
|
||||
| UI / frontend / styling / design | CONVENTIONS.md, STRUCTURE.md, STACK.md |
|
||||
| Backend / API / service / data model | STACK.md, ARCHITECTURE.md, INTEGRATIONS.md |
|
||||
| Integration / third-party / provider | STACK.md, INTEGRATIONS.md, ARCHITECTURE.md |
|
||||
| Infrastructure / DevOps / CI / deploy | STACK.md, ARCHITECTURE.md, INTEGRATIONS.md |
|
||||
| Testing / QA / coverage | TESTING.md, CONVENTIONS.md, STRUCTURE.md |
|
||||
| Documentation / content | CONVENTIONS.md, STRUCTURE.md |
|
||||
| Mixed / unclear | STACK.md, ARCHITECTURE.md, CONVENTIONS.md |
|
||||
|
||||
Read CONCERNS.md only if the phase explicitly addresses known concerns or
|
||||
security issues.
|
||||
|
||||
## Single-read rule
|
||||
|
||||
Read each map file in a **single** Read call. Do not read the same file at
|
||||
two different offsets — split reads break prompt-cache reuse and cost more
|
||||
than a single full read.
|
||||
|
||||
## No-maps fallback
|
||||
|
||||
If `.planning/codebase/*.md` does not exist:
|
||||
1. Extract key terms from the phase goal (e.g., "feed" → "post", "card",
|
||||
"list"; "auth" → "login", "session", "token")
|
||||
2. `grep -rlE "{term1}|{term2}" src/ app/ --include="*.ts" ...` (use `-E`
|
||||
for extended regex so the `|` alternation works on both GNU grep and BSD
|
||||
grep / macOS), and `ls` the conventional component/hook/util dirs
|
||||
3. Read the 3–5 most relevant files
|
||||
|
||||
## Output (internal `<codebase_context>`)
|
||||
|
||||
From the scan, identify:
|
||||
- **Reusable assets** — components, hooks, utilities usable in this phase
|
||||
- **Established patterns** — state management, styling, data fetching
|
||||
- **Integration points** — routes, nav, providers where new code connects
|
||||
- **Creative options** — approaches the architecture enables or constrains
|
||||
|
||||
Used in `analyze_phase` and `present_gray_areas`. NOT written to a file —
|
||||
session-only.
|
||||
48
gsd-core/references/skeleton-template.md
Normal file
48
gsd-core/references/skeleton-template.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# SKELETON.md Template
|
||||
|
||||
> Emitted by `gsd-planner` when `WALKING_SKELETON=true` (Phase 1 + `--mvp` + new project). Records the architectural decisions the rest of the project will build on.
|
||||
|
||||
```markdown
|
||||
# Walking Skeleton — [Project Name]
|
||||
|
||||
**Phase:** 1
|
||||
**Generated:** {ISO date}
|
||||
|
||||
## Capability Proven End-to-End
|
||||
|
||||
> One sentence: the smallest user-visible capability that exercises the full stack.
|
||||
|
||||
Example: "A signed-in user can view their email on a dashboard page served by the deployed app."
|
||||
|
||||
## Architectural Decisions
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|---|---|---|
|
||||
| Framework | (e.g., Next.js 15 App Router) | Why this fits the project |
|
||||
| Data layer | (e.g., Postgres + Drizzle) | Why |
|
||||
| Auth | (e.g., session cookies + bcrypt) | Why |
|
||||
| Deployment target | (e.g., Vercel preview) | Why |
|
||||
| Directory layout | (e.g., feature-folders under src/features/*) | Why |
|
||||
|
||||
## Stack Touched in Phase 1
|
||||
|
||||
- [ ] Project scaffold (framework, build, lint, test runner)
|
||||
- [ ] Routing — at least one real route
|
||||
- [ ] Database — at least one real read AND one real write
|
||||
- [ ] UI — at least one interactive element wired to the API
|
||||
- [ ] Deployment — running on dev environment OR documented local full-stack run command
|
||||
|
||||
## Out of Scope (Deferred to Later Slices)
|
||||
|
||||
> Anything that is *not* in the skeleton. Be explicit — this list prevents future phases from re-litigating Phase 1's minimalism.
|
||||
|
||||
- (e.g., password reset, email verification, multi-tenancy)
|
||||
|
||||
## Subsequent Slice Plan
|
||||
|
||||
Each later phase adds one vertical slice on top of this skeleton without altering its architectural decisions:
|
||||
|
||||
- Phase 2: [next user capability]
|
||||
- Phase 3: [next user capability]
|
||||
- ...
|
||||
```
|
||||
41
gsd-core/references/sketch-interactivity.md
Normal file
41
gsd-core/references/sketch-interactivity.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Making Sketches Feel Alive
|
||||
|
||||
Static mockups are barely better than screenshots. Every interactive element in a sketch must respond to interaction.
|
||||
|
||||
## Required Interactivity
|
||||
|
||||
| Element | Must Have |
|
||||
|---------|-----------|
|
||||
| Buttons | Click handler with visible feedback (state change, animation, toast) |
|
||||
| Forms | Input validation on blur, submit handler that shows success state |
|
||||
| Lists | Add/remove items, empty state, populated state |
|
||||
| Toggles/switches | Working toggle with visible state change |
|
||||
| Tabs/nav | Click to switch content |
|
||||
| Modals/drawers | Open/close with transition |
|
||||
| Hover states | Every clickable element needs a hover effect |
|
||||
| Dropdowns | Open/close, item selection |
|
||||
|
||||
## Transitions
|
||||
|
||||
Add `transition: all 0.15s ease` as a baseline to interactive elements. Subtle motion makes the sketch feel real and helps judge whether the interaction pattern works.
|
||||
|
||||
## Fake the Backend
|
||||
|
||||
If the sketch shows a "Save" button, clicking it should show a brief loading state then a success message. If it shows a search bar, typing should filter hardcoded results. The goal is to feel the full interaction loop, not just see the resting state.
|
||||
|
||||
## State Cycling
|
||||
|
||||
If the sketch has multiple states (empty, loading, populated, error), include buttons to cycle through them. Label each state clearly. This lets the user experience how the design handles different data conditions.
|
||||
|
||||
## Implementation
|
||||
|
||||
Use vanilla JS in inline `<script>` tags. No frameworks, no build step. Keep it simple:
|
||||
|
||||
```html
|
||||
<script>
|
||||
// Toggle a panel
|
||||
document.querySelector('.panel-toggle').addEventListener('click', (e) => {
|
||||
e.target.closest('.panel').classList.toggle('collapsed');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
94
gsd-core/references/sketch-theme-system.md
Normal file
94
gsd-core/references/sketch-theme-system.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Shared Theme System
|
||||
|
||||
All sketches share a CSS variable theme so design decisions compound across sketches.
|
||||
|
||||
## Setup
|
||||
|
||||
On the first sketch, create `.planning/sketches/themes/` with a default theme:
|
||||
|
||||
```
|
||||
.planning/sketches/
|
||||
themes/
|
||||
default.css <- all sketches link to this
|
||||
001-dashboard-layout/
|
||||
index.html <- links to ../themes/default.css
|
||||
```
|
||||
|
||||
## Theme File Structure
|
||||
|
||||
Each theme defines CSS custom properties only — no component styles, no layout rules. Just the visual vocabulary:
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Colors */
|
||||
--color-bg: #fafafa;
|
||||
--color-surface: #ffffff;
|
||||
--color-border: #e5e5e5;
|
||||
--color-text: #1a1a1a;
|
||||
--color-text-muted: #6b6b6b;
|
||||
--color-primary: #2563eb;
|
||||
--color-primary-hover: #1d4ed8;
|
||||
--color-accent: #f59e0b;
|
||||
--color-danger: #ef4444;
|
||||
--color-success: #22c55e;
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Inter', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', monospace;
|
||||
--text-xs: 0.75rem;
|
||||
--text-sm: 0.875rem;
|
||||
--text-base: 1rem;
|
||||
--text-lg: 1.125rem;
|
||||
--text-xl: 1.25rem;
|
||||
--text-2xl: 1.5rem;
|
||||
--text-3xl: 1.875rem;
|
||||
|
||||
/* Spacing */
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-6: 24px;
|
||||
--space-8: 32px;
|
||||
--space-12: 48px;
|
||||
|
||||
/* Shapes */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
|
||||
--shadow-md: 0 4px 6px rgba(0,0,0,0.07);
|
||||
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
```
|
||||
|
||||
Adapt the default theme to match the mood/direction established during intake. The values above are a starting point — change colors, fonts, spacing, and shapes to match the agreed aesthetic.
|
||||
|
||||
## Linking
|
||||
|
||||
Every sketch links to the theme:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="../themes/default.css">
|
||||
```
|
||||
|
||||
## Creating New Themes
|
||||
|
||||
When a sketch reveals an aesthetic fork ("should this feel clinical or warm?"), create both as theme files rather than arguing about it. The user can switch and feel the difference.
|
||||
|
||||
Name themes descriptively: `midnight.css`, `warm-minimal.css`, `brutalist.css`.
|
||||
|
||||
## Theme Switcher
|
||||
|
||||
Include in every sketch (part of the sketch toolbar):
|
||||
|
||||
```html
|
||||
<select id="theme-switcher" onchange="document.querySelector('link[href*=themes]').href='../themes/'+this.value+'.css'">
|
||||
<option value="default">Default</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
Dynamically populate options by listing available theme files, or hardcode the known themes.
|
||||
45
gsd-core/references/sketch-tooling.md
Normal file
45
gsd-core/references/sketch-tooling.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Sketch Toolbar
|
||||
|
||||
Include a small floating toolbar in every sketch. It provides utilities without competing with the actual design.
|
||||
|
||||
## Implementation
|
||||
|
||||
A small `<div>` fixed to the bottom-right, semi-transparent, expands on hover:
|
||||
|
||||
```html
|
||||
<div id="sketch-tools" style="position:fixed;bottom:12px;right:12px;z-index:9999;font-family:system-ui;font-size:12px;background:rgba(0,0,0,0.7);color:white;padding:8px 12px;border-radius:8px;opacity:0.4;transition:opacity 0.2s;" onmouseenter="this.style.opacity='1'" onmouseleave="this.style.opacity='0.4'">
|
||||
<!-- Theme switcher -->
|
||||
<!-- Viewport buttons -->
|
||||
<!-- Annotation toggle -->
|
||||
</div>
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### Theme Switcher
|
||||
|
||||
A dropdown that swaps the theme CSS file at runtime:
|
||||
|
||||
```html
|
||||
<select onchange="document.querySelector('link[href*=themes]').href='../themes/'+this.value+'.css'">
|
||||
<option value="default">Default</option>
|
||||
</select>
|
||||
```
|
||||
|
||||
### Viewport Preview
|
||||
|
||||
Three buttons that constrain the sketch content area to standard widths:
|
||||
|
||||
- Phone: 375px
|
||||
- Tablet: 768px
|
||||
- Desktop: 1280px (or full width)
|
||||
|
||||
Implemented by wrapping sketch content in a container and adjusting its `max-width`.
|
||||
|
||||
### Annotation Mode
|
||||
|
||||
A toggle that overlays spacing values, color hex codes, and font sizes on hover. Implemented as a JS snippet that reads computed styles and shows them in a tooltip. Helps understand visual decisions without opening dev tools.
|
||||
|
||||
## Styling
|
||||
|
||||
The toolbar should be unobtrusive — small, dark, semi-transparent. It should never compete with the sketch visually. Style it independently of the theme (hardcoded dark background, white text).
|
||||
81
gsd-core/references/sketch-variant-patterns.md
Normal file
81
gsd-core/references/sketch-variant-patterns.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Multi-Variant HTML Patterns
|
||||
|
||||
Every sketch produces 2-3 variants in the same HTML file. The user switches between them to compare.
|
||||
|
||||
## Tab-Based Variants
|
||||
|
||||
The standard approach: a tab bar at the top of the page, each tab shows a different variant.
|
||||
|
||||
```html
|
||||
<div id="variant-nav" style="position:fixed;top:0;left:0;right:0;z-index:9998;background:var(--color-surface, #fff);border-bottom:1px solid var(--color-border, #e5e5e5);padding:8px 16px;display:flex;gap:8px;font-family:system-ui;">
|
||||
<button class="variant-tab active" onclick="showVariant('a')">A: Sidebar Layout</button>
|
||||
<button class="variant-tab" onclick="showVariant('b')">B: Top Nav</button>
|
||||
<button class="variant-tab" onclick="showVariant('c')">C: Floating Panels</button>
|
||||
</div>
|
||||
|
||||
<div id="variant-a" class="variant active">
|
||||
<!-- Variant A content -->
|
||||
</div>
|
||||
<div id="variant-b" class="variant" style="display:none">
|
||||
<!-- Variant B content -->
|
||||
</div>
|
||||
<div id="variant-c" class="variant" style="display:none">
|
||||
<!-- Variant C content -->
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showVariant(id) {
|
||||
document.querySelectorAll('.variant').forEach(v => v.style.display = 'none');
|
||||
document.querySelectorAll('.variant-tab').forEach(t => t.classList.remove('active'));
|
||||
document.getElementById('variant-' + id).style.display = 'block';
|
||||
event.target.classList.add('active');
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
Add `padding-top` to the body to account for the fixed tab bar.
|
||||
|
||||
## Marking the Winner
|
||||
|
||||
After the user picks a direction, add a visual indicator to the winning tab:
|
||||
|
||||
```html
|
||||
<button class="variant-tab active">A: Sidebar Layout ★ Selected</button>
|
||||
```
|
||||
|
||||
Keep all variants visible and navigable — the winner is highlighted, not the only option.
|
||||
|
||||
## Side-by-Side (for small variants)
|
||||
|
||||
When comparing small elements (button styles, card layouts, icon treatments), render them next to each other with labels rather than using tabs:
|
||||
|
||||
```html
|
||||
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:24px;padding:24px;">
|
||||
<div>
|
||||
<h3>A: Rounded</h3>
|
||||
<!-- variant content -->
|
||||
</div>
|
||||
<div>
|
||||
<h3>B: Sharp</h3>
|
||||
<!-- variant content -->
|
||||
</div>
|
||||
<div>
|
||||
<h3>C: Pill</h3>
|
||||
<!-- variant content -->
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Variant Count
|
||||
|
||||
- **First round (dramatic):** 2-3 meaningfully different approaches
|
||||
- **Refinement rounds:** 2-3 subtle variations within the chosen direction
|
||||
- **Never more than 4** — more than that overwhelms. If there are 5+ options, narrow before showing.
|
||||
|
||||
## Synthesis Variants
|
||||
|
||||
When the user cherry-picks elements across variants, create a new variant tab labeled descriptively:
|
||||
|
||||
```html
|
||||
<button class="variant-tab" onclick="showVariant('synth1')">Synthesis: A's layout + C's palette</button>
|
||||
```
|
||||
69
gsd-core/references/spidr-splitting.md
Normal file
69
gsd-core/references/spidr-splitting.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# SPIDR Story Splitting Rules
|
||||
|
||||
> Used by `mvp-phase` workflow when the user-supplied story is too large for a single phase. Per PRD decision Q3, SPIDR runs as a **full interactive flow** — not a lightweight check.
|
||||
|
||||
## When SPIDR triggers
|
||||
|
||||
Trigger SPIDR splitting if **any** of these size signals fire on the user story:
|
||||
|
||||
1. **Compound capabilities.** The story names two or more independent user actions joined by "and" (e.g., "register **and** log in **and** reset their password"). Each "and" is a candidate split point.
|
||||
2. **Multi-actor.** The story names more than one `[user role]` (e.g., "As a user or admin..."). Each role is a candidate split.
|
||||
3. **Length.** The assembled story exceeds ~120 chars on a single line.
|
||||
4. **Vague capability.** The capability is a noun phrase, not a verb-noun pair (e.g., "I want to use the dashboard" — needs to specify *which interaction* with the dashboard).
|
||||
|
||||
If none of these fire, skip SPIDR entirely and proceed to ROADMAP write.
|
||||
|
||||
## The five SPIDR axes
|
||||
|
||||
For each axis, ask one targeted question. The user picks the axis that best fits their story; only one axis is applied per split.
|
||||
|
||||
### Spike
|
||||
|
||||
> "Is there an unknown that needs research before this can be implemented? If so, the spike is its own phase."
|
||||
|
||||
If yes: split out a research phase (no acceptance criteria except "we know enough to plan the rest"). The remaining story becomes a follow-up phase.
|
||||
|
||||
### Paths
|
||||
|
||||
> "Does this feature have a happy path and one or more error/edge paths?"
|
||||
|
||||
If yes: split happy path into the first phase, edge paths into follow-ups. Order: happy path first (it proves the slice works), then progressively edge cases.
|
||||
|
||||
### Interfaces
|
||||
|
||||
> "Does this feature need to work on more than one interface (web, mobile, API, CLI)?"
|
||||
|
||||
If yes: split by interface. Web first if user-facing; API first if integration-driven; mobile last unless it's the primary platform.
|
||||
|
||||
### Data
|
||||
|
||||
> "Does this feature touch multiple data scopes (one user vs. many, single team vs. multi-tenant, small CSV vs. large dataset)?"
|
||||
|
||||
If yes: split by scope. Smallest scope first (one user, single team, small data), then expand.
|
||||
|
||||
### Rules
|
||||
|
||||
> "Does this feature have multiple business rules that could be added incrementally (basic validation first, then complex policy)?"
|
||||
|
||||
If yes: split by rule complexity. Minimum viable rules first; complex policy in follow-ups.
|
||||
|
||||
## Workflow
|
||||
|
||||
When SPIDR triggers, the workflow:
|
||||
|
||||
1. Restates the user-supplied story.
|
||||
2. Asks "Which SPIDR axis fits best?" with the five options above.
|
||||
3. Walks through the chosen axis interactively (one focused question), produces a split proposal: "Phase N (this one): X. Phase N+1: Y. Phase N+2: Z."
|
||||
4. Confirms the split with the user.
|
||||
5. On accept: writes the FIRST phase's story to the current ROADMAP entry; defers creating new phases for the splits to a follow-up step (the workflow surfaces a list of `/gsd add-phase` invocations the user can run after `mvp-phase` completes — but does not run them automatically, to preserve user control over phase numbering).
|
||||
6. On reject: proceeds with the original story unchanged.
|
||||
|
||||
## Anti-patterns to reject
|
||||
|
||||
- **Splitting by technical layer.** "Phase 1: schema. Phase 2: API. Phase 3: UI." That's horizontal planning. Reject.
|
||||
- **Pre-splitting before the user even sees the original.** Always show the user-supplied story first; only offer split if it triggers a size signal.
|
||||
- **Splitting more than one axis at once.** SPIDR is one axis per split. If a story needs splitting on two axes (e.g., paths AND data), do paths first, then re-evaluate the resulting smaller stories.
|
||||
|
||||
## Reference
|
||||
|
||||
See [Mike Cohn — Five Simple But Powerful Ways to Split User Stories](https://www.mountaingoatsoftware.com/blog/five-simple-but-powerful-ways-to-split-user-stories).
|
||||
330
gsd-core/references/tdd.md
Normal file
330
gsd-core/references/tdd.md
Normal file
@@ -0,0 +1,330 @@
|
||||
<overview>
|
||||
TDD is about design quality, not coverage metrics. The red-green-refactor cycle forces you to think about behavior before implementation, producing cleaner interfaces and more testable code.
|
||||
|
||||
**Principle:** If you can describe the behavior as `expect(fn(input)).toBe(output)` before writing `fn`, TDD improves the result.
|
||||
|
||||
**Key insight:** TDD work is fundamentally heavier than standard tasks—it requires 2-3 execution cycles (RED → GREEN → REFACTOR), each with file reads, test runs, and potential debugging. TDD features get dedicated plans to ensure full context is available throughout the cycle.
|
||||
</overview>
|
||||
|
||||
<when_to_use_tdd>
|
||||
## When TDD Improves Quality
|
||||
|
||||
**TDD candidates (create a TDD plan):**
|
||||
- Business logic with defined inputs/outputs
|
||||
- API endpoints with request/response contracts
|
||||
- Data transformations, parsing, formatting
|
||||
- Validation rules and constraints
|
||||
- Algorithms with testable behavior
|
||||
- State machines and workflows
|
||||
- Utility functions with clear specifications
|
||||
|
||||
**Skip TDD (use standard plan with `type="auto"` tasks):**
|
||||
- UI layout, styling, visual components
|
||||
- Configuration changes
|
||||
- Glue code connecting existing components
|
||||
- One-off scripts and migrations
|
||||
- Simple CRUD with no business logic
|
||||
- Exploratory prototyping
|
||||
|
||||
**Heuristic:** Can you write `expect(fn(input)).toBe(output)` before writing `fn`?
|
||||
→ Yes: Create a TDD plan
|
||||
→ No: Use standard plan, add tests after if needed
|
||||
</when_to_use_tdd>
|
||||
|
||||
<tdd_plan_structure>
|
||||
## TDD Plan Structure
|
||||
|
||||
Each TDD plan implements **one feature** through the full RED-GREEN-REFACTOR cycle.
|
||||
|
||||
```markdown
|
||||
---
|
||||
phase: XX-name
|
||||
plan: NN
|
||||
type: tdd
|
||||
---
|
||||
|
||||
<objective>
|
||||
[What feature and why]
|
||||
Purpose: [Design benefit of TDD for this feature]
|
||||
Output: [Working, tested feature]
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@relevant/source/files.ts
|
||||
</context>
|
||||
|
||||
<feature>
|
||||
<name>[Feature name]</name>
|
||||
<files>[source file, test file]</files>
|
||||
<behavior>
|
||||
[Expected behavior in testable terms]
|
||||
Cases: input → expected output
|
||||
</behavior>
|
||||
<implementation>[How to implement once tests pass]</implementation>
|
||||
</feature>
|
||||
|
||||
<verification>
|
||||
[Test command that proves feature works]
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Failing test written and committed
|
||||
- Implementation passes test
|
||||
- Refactor complete (if needed)
|
||||
- All 2-3 commits present
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create SUMMARY.md with:
|
||||
- RED: What test was written, why it failed
|
||||
- GREEN: What implementation made it pass
|
||||
- REFACTOR: What cleanup was done (if any)
|
||||
- Commits: List of commits produced
|
||||
</output>
|
||||
```
|
||||
|
||||
**One feature per TDD plan.** If features are trivial enough to batch, they're trivial enough to skip TDD—use a standard plan and add tests after.
|
||||
</tdd_plan_structure>
|
||||
|
||||
<execution_flow>
|
||||
## Red-Green-Refactor Cycle
|
||||
|
||||
**RED - Write failing test:**
|
||||
1. Create test file following project conventions
|
||||
2. Write test describing expected behavior (from `<behavior>` element)
|
||||
3. Run test - it MUST fail
|
||||
4. If test passes: feature exists or test is wrong. Investigate.
|
||||
5. Commit: `test({phase}-{plan}): add failing test for [feature]`
|
||||
|
||||
**GREEN - Implement to pass:**
|
||||
1. Write minimal code to make test pass
|
||||
2. No cleverness, no optimization - just make it work
|
||||
3. Run test - it MUST pass
|
||||
4. Commit: `feat({phase}-{plan}): implement [feature]`
|
||||
|
||||
**REFACTOR (if needed):**
|
||||
1. Clean up implementation if obvious improvements exist
|
||||
2. Run tests - MUST still pass
|
||||
3. Only commit if changes made: `refactor({phase}-{plan}): clean up [feature]`
|
||||
|
||||
**Result:** Each TDD plan produces 2-3 atomic commits.
|
||||
</execution_flow>
|
||||
|
||||
<test_quality>
|
||||
## Good Tests vs Bad Tests
|
||||
|
||||
**Test behavior, not implementation:**
|
||||
- Good: "returns formatted date string"
|
||||
- Bad: "calls formatDate helper with correct params"
|
||||
- Tests should survive refactors
|
||||
|
||||
**One concept per test:**
|
||||
- Good: Separate tests for valid input, empty input, malformed input
|
||||
- Bad: Single test checking all edge cases with multiple assertions
|
||||
|
||||
**Descriptive names:**
|
||||
- Good: "should reject empty email", "returns null for invalid ID"
|
||||
- Bad: "test1", "handles error", "works correctly"
|
||||
|
||||
**No implementation details:**
|
||||
- Good: Test public API, observable behavior
|
||||
- Bad: Mock internals, test private methods, assert on internal state
|
||||
</test_quality>
|
||||
|
||||
<framework_setup>
|
||||
## Test Framework Setup (If None Exists)
|
||||
|
||||
When executing a TDD plan but no test framework is configured, set it up as part of the RED phase:
|
||||
|
||||
**1. Detect project type:**
|
||||
```bash
|
||||
# JavaScript/TypeScript
|
||||
if [ -f package.json ]; then echo "node"; fi
|
||||
|
||||
# Python
|
||||
if [ -f requirements.txt ] || [ -f pyproject.toml ]; then echo "python"; fi
|
||||
|
||||
# Go
|
||||
if [ -f go.mod ]; then echo "go"; fi
|
||||
|
||||
# Rust
|
||||
if [ -f Cargo.toml ]; then echo "rust"; fi
|
||||
```
|
||||
|
||||
**2. Install minimal framework:**
|
||||
| Project | Framework | Install |
|
||||
|---------|-----------|---------|
|
||||
| Node.js | Jest | `npm install -D jest @types/jest ts-jest` |
|
||||
| Node.js (Vite) | Vitest | `npm install -D vitest` |
|
||||
| Python | pytest | `pip install pytest` |
|
||||
| Go | testing | Built-in |
|
||||
| Rust | cargo test | Built-in |
|
||||
|
||||
**3. Create config if needed:**
|
||||
- Jest: `jest.config.js` with ts-jest preset
|
||||
- Vitest: `vitest.config.ts` with test globals
|
||||
- pytest: `pytest.ini` or `pyproject.toml` section
|
||||
|
||||
**4. Verify setup:**
|
||||
```bash
|
||||
# Run empty test suite - should pass with 0 tests
|
||||
npm test # Node
|
||||
pytest # Python
|
||||
go test ./... # Go
|
||||
cargo test # Rust
|
||||
```
|
||||
|
||||
**5. Create first test file:**
|
||||
Follow project conventions for test location:
|
||||
- `*.test.ts` / `*.spec.ts` next to source
|
||||
- `__tests__/` directory
|
||||
- `tests/` directory at root
|
||||
|
||||
Framework setup is a one-time cost included in the first TDD plan's RED phase.
|
||||
</framework_setup>
|
||||
|
||||
<error_handling>
|
||||
## Error Handling
|
||||
|
||||
**Test doesn't fail in RED phase:**
|
||||
- Feature may already exist - investigate
|
||||
- Test may be wrong (not testing what you think)
|
||||
- Fix before proceeding
|
||||
|
||||
**Test doesn't pass in GREEN phase:**
|
||||
- Debug implementation
|
||||
- Don't skip to refactor
|
||||
- Keep iterating until green
|
||||
|
||||
**Tests fail in REFACTOR phase:**
|
||||
- Undo refactor
|
||||
- Commit was premature
|
||||
- Refactor in smaller steps
|
||||
|
||||
**Unrelated tests break:**
|
||||
- Stop and investigate
|
||||
- May indicate coupling issue
|
||||
- Fix before proceeding
|
||||
</error_handling>
|
||||
|
||||
<commit_pattern>
|
||||
## Commit Pattern for TDD Plans
|
||||
|
||||
TDD plans produce 2-3 atomic commits (one per phase):
|
||||
|
||||
```
|
||||
test(08-02): add failing test for email validation
|
||||
|
||||
- Tests valid email formats accepted
|
||||
- Tests invalid formats rejected
|
||||
- Tests empty input handling
|
||||
|
||||
feat(08-02): implement email validation
|
||||
|
||||
- Regex pattern matches RFC 5322
|
||||
- Returns boolean for validity
|
||||
- Handles edge cases (empty, null)
|
||||
|
||||
refactor(08-02): extract regex to constant (optional)
|
||||
|
||||
- Moved pattern to EMAIL_REGEX constant
|
||||
- No behavior changes
|
||||
- Tests still pass
|
||||
```
|
||||
|
||||
**Comparison with standard plans:**
|
||||
- Standard plans: 1 commit per task, 2-4 commits per plan
|
||||
- TDD plans: 2-3 commits for single feature
|
||||
|
||||
Both follow same format: `{type}({phase}-{plan}): {description}`
|
||||
|
||||
**Benefits:**
|
||||
- Each commit independently revertable
|
||||
- Git bisect works at commit level
|
||||
- Clear history showing TDD discipline
|
||||
- Consistent with overall commit strategy
|
||||
</commit_pattern>
|
||||
|
||||
<gate_enforcement>
|
||||
## Gate Enforcement Rules
|
||||
|
||||
When `workflow.tdd_mode` is enabled in config, the RED/GREEN/REFACTOR gate sequence is enforced for all `type: tdd` plans.
|
||||
|
||||
### Gate Definitions
|
||||
|
||||
| Gate | Required | Commit Pattern | Validation |
|
||||
|------|----------|---------------|------------|
|
||||
| RED | Yes | `test({phase}-{plan}): ...` | Test exists AND fails before implementation |
|
||||
| GREEN | Yes | `feat({phase}-{plan}): ...` | Test passes after implementation |
|
||||
| REFACTOR | No | `refactor({phase}-{plan}): ...` | Tests still pass after cleanup |
|
||||
|
||||
### Fail-Fast Rules
|
||||
|
||||
1. **Unexpected GREEN in RED phase:** If the test passes before any implementation code is written, STOP. The feature may already exist or the test is wrong. Investigate before proceeding.
|
||||
2. **Missing RED commit:** If no `test(...)` commit precedes the `feat(...)` commit, the TDD discipline was violated. Flag in SUMMARY.md.
|
||||
3. **REFACTOR breaks tests:** Undo the refactor immediately. Commit was premature — refactor in smaller steps.
|
||||
|
||||
### Executor Gate Validation
|
||||
|
||||
After completing a `type: tdd` plan, the executor validates the git log:
|
||||
```bash
|
||||
# Check for RED gate commit
|
||||
git log --oneline --grep="^test(${PHASE}-${PLAN})" | head -1
|
||||
# Check for GREEN gate commit
|
||||
git log --oneline --grep="^feat(${PHASE}-${PLAN})" | head -1
|
||||
# Check for optional REFACTOR gate commit
|
||||
git log --oneline --grep="^refactor(${PHASE}-${PLAN})" | head -1
|
||||
```
|
||||
|
||||
If RED or GREEN gate commits are missing, add a `## TDD Gate Compliance` section to SUMMARY.md with the violation details.
|
||||
</gate_enforcement>
|
||||
|
||||
<end_of_phase_review>
|
||||
## End-of-Phase TDD Review Checkpoint
|
||||
|
||||
When `workflow.tdd_mode` is enabled, the execute-phase orchestrator inserts a collaborative review checkpoint after all waves complete but before phase verification.
|
||||
|
||||
### Review Checkpoint Format
|
||||
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
TDD REVIEW — Phase {X}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
TDD Plans: {count} | Gate violations: {count}
|
||||
|
||||
| Plan | RED | GREEN | REFACTOR | Status |
|
||||
|------|-----|-------|----------|--------|
|
||||
| {id} | ✓ | ✓ | ✓ | Pass |
|
||||
| {id} | ✓ | ✗ | — | FAIL |
|
||||
|
||||
{If violations exist:}
|
||||
⚠ Gate violations are advisory — review before advancing.
|
||||
```
|
||||
|
||||
### What the Review Checks
|
||||
|
||||
1. **Gate sequence:** Each TDD plan has RED → GREEN commits in order
|
||||
2. **Test quality:** RED phase tests fail for the right reason (not import errors or syntax)
|
||||
3. **Minimal GREEN:** Implementation is minimal — no premature optimization in GREEN phase
|
||||
4. **Refactor discipline:** If REFACTOR commit exists, tests still pass
|
||||
|
||||
This checkpoint is advisory — it does not block phase completion but surfaces TDD discipline issues for human review.
|
||||
</end_of_phase_review>
|
||||
|
||||
<context_budget>
|
||||
## Context Budget
|
||||
|
||||
TDD plans target **~40% context usage** (lower than standard plans' ~50%).
|
||||
|
||||
Why lower:
|
||||
- RED phase: write test, run test, potentially debug why it didn't fail
|
||||
- GREEN phase: implement, run test, potentially iterate on failures
|
||||
- REFACTOR phase: modify code, run tests, verify no regressions
|
||||
|
||||
Each phase involves reading files, running commands, analyzing output. The back-and-forth is inherently heavier than linear task execution.
|
||||
|
||||
Single feature focus ensures full quality throughout the cycle.
|
||||
</context_budget>
|
||||
44
gsd-core/references/thinking-models-debug.md
Normal file
44
gsd-core/references/thinking-models-debug.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Thinking Models: Debug Cluster
|
||||
|
||||
Structured reasoning models for the **debugger** agent. Apply these at decision points during investigation, not continuously. Each model counters a specific documented failure mode.
|
||||
|
||||
Source: Curated from [thinking-partner](https://github.com/mattnowdev/thinking-partner) model catalog (150+ models). Selected for direct applicability to GSD debugging workflow.
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
**Fault Tree and Hypothesis-Driven are sequential:** Fault Tree FIRST (generate the tree of possible causes), Hypothesis-Driven SECOND (test each branch systematically). Fault Tree provides the map; Hypothesis-Driven provides the discipline to traverse it.
|
||||
|
||||
## 1. Fault Tree Analysis
|
||||
|
||||
**Counters:** Jumping to conclusions without systematically mapping failure paths.
|
||||
|
||||
Before testing any hypothesis, build a fault tree: start with the observed symptom as the root node, then branch into all possible causes at each level (hardware, software, configuration, data, environment). Use AND/OR gates -- some failures require multiple conditions (AND), others have independent triggers (OR). This tree becomes your investigation roadmap. Prioritize branches by likelihood and testability, but do NOT prune branches just because they seem unlikely -- unlikely causes that are easy to test should be tested early.
|
||||
|
||||
## 2. Hypothesis-Driven Investigation
|
||||
|
||||
**Counters:** Making random changes and hoping something works -- the "shotgun debugging" anti-pattern.
|
||||
|
||||
For each hypothesis from the fault tree, follow the strict protocol: PREDICT ("If hypothesis H is correct, then test T should produce result R"), TEST (execute exactly one test), OBSERVE (record the actual result), CONCLUDE (matched = SUPPORTED, failed = ELIMINATED, unexpected = new evidence). Never skip the PREDICT step -- without a prediction, you cannot distinguish a meaningful result from noise. Never change more than one variable per test -- if you change two things and the bug disappears, you don't know which change fixed it.
|
||||
|
||||
## 3. Occam's Razor
|
||||
|
||||
**Counters:** Pursuing elaborate explanations when simple ones have not been ruled out.
|
||||
|
||||
Before investigating complex multi-component interaction bugs, race conditions, or framework-level issues, verify the simple explanations first: typo in variable name, wrong file path, missing import, incorrect config value, stale cache, wrong environment variable. These "boring" causes account for the majority of bugs. Only escalate to complex hypotheses AFTER the simple ones are eliminated. If your current hypothesis requires 3+ things to go wrong simultaneously, step back and look for a single-point failure.
|
||||
|
||||
## 4. Counterfactual Thinking
|
||||
|
||||
**Counters:** Failing to isolate causation by not asking "what if we changed just this one thing?"
|
||||
|
||||
When you have a hypothesis about the root cause, construct a counterfactual: "If I change ONLY this one variable/config/line, the bug should disappear (or appear)." Execute the counterfactual test. If the bug persists after your targeted change, your hypothesis is wrong -- the cause is elsewhere. If the bug disappears, you have strong causal evidence. This is more powerful than correlation ("the bug appeared after deploy X") because it tests the mechanism, not just the timeline.
|
||||
|
||||
---
|
||||
|
||||
## When NOT to Think
|
||||
|
||||
Skip structured reasoning models when the situation does not benefit from them:
|
||||
|
||||
- **Obvious single-cause bugs** -- If the error message names the exact file, line, and cause (e.g., `TypeError: Cannot read property 'x' of undefined at foo.js:42`), fix it directly. Do not build a fault tree for a null reference with a stack trace.
|
||||
- **Reproducing a known fix** -- If you already know the root cause from a previous investigation or the user told you exactly what is wrong, skip hypothesis-driven investigation and go straight to the fix.
|
||||
- **Typos, missing imports, wrong paths** -- If Occam's Razor would immediately resolve it, apply the fix without invoking the full model. The model exists for when simple checks fail, not to gate simple checks.
|
||||
- **Reading error logs** -- Reading and understanding error output is normal debugging, not a "decision point." Only invoke models when you have multiple plausible hypotheses and need to choose which to test first.
|
||||
50
gsd-core/references/thinking-models-execution.md
Normal file
50
gsd-core/references/thinking-models-execution.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Thinking Models: Execution Cluster
|
||||
|
||||
Structured reasoning models for the **executor** agent. Apply these at decision points during task execution, not continuously. Each model counters a specific documented failure mode.
|
||||
|
||||
Source: Curated from [thinking-partner](https://github.com/mattnowdev/thinking-partner) model catalog (150+ models). Selected for direct applicability to GSD execution workflow.
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
**Forcing Function and First Principles both push toward "do it now".** Run First Principles FIRST (understand the constraint), Forcing Function SECOND (create the mechanism). Sequential, not competing.
|
||||
|
||||
## 1. Circle of Concern vs Circle of Control
|
||||
|
||||
**Counters:** Executor trying to fix things outside its scope -- upstream bugs, unrelated tech debt, infrastructure issues.
|
||||
|
||||
Before modifying any code not explicitly listed in the plan's `<files>` section, ask: Is this in my Circle of Control (plan scope) or my Circle of Concern (things I notice but shouldn't fix)? If Circle of Concern: document it as a deviation note or deferred item, do NOT fix it. The executor's job is to build what the plan says, not to improve the codebase. Scope creep from "while I'm here" fixes is the #1 cause of executor overruns.
|
||||
|
||||
## 2. Forcing Function
|
||||
|
||||
**Counters:** Deferring hard decisions to runtime instead of resolving them at build time.
|
||||
|
||||
When you encounter an ambiguous requirement or unclear integration point, create a forcing function that makes the decision explicit NOW rather than hiding it behind a TODO or runtime check. Examples: use a TypeScript `never` type to force exhaustive switches, add a build-time assertion for required config values, create an interface that forces callers to handle error cases. If a decision truly cannot be made at build time, document it as a `checkpoint:decision` deviation -- do not silently defer.
|
||||
|
||||
## 3. First Principles Thinking
|
||||
|
||||
**Counters:** Copying patterns from existing code without understanding whether they fit the current task.
|
||||
|
||||
Before copying a pattern from another file or phase, decompose WHY that pattern exists: What constraint does it satisfy? Does your current task have the same constraint? If not, the pattern may be cargo cult. Build your implementation from the task's actual requirements, not from the nearest existing example. When in doubt, the plan's `<action>` steps define what to build -- derive the implementation from those, not from adjacent code.
|
||||
|
||||
## 4. Occam's Razor
|
||||
|
||||
**Counters:** Over-engineering simple tasks with unnecessary abstractions, generics, or future-proofing.
|
||||
|
||||
Before adding an abstraction layer, generic type parameter, factory pattern, or configuration option, ask: Does the plan REQUIRE this flexibility? If the plan says "create a function that does X", create a function that does X -- not a configurable, extensible, pluggable framework that could theoretically do X through Y through Z. The simplest implementation that satisfies the plan's `<done>` condition is the correct one. Add complexity only when the plan explicitly calls for it.
|
||||
|
||||
## 5. Chesterton's Fence
|
||||
|
||||
**Counters:** Removing or modifying existing code without understanding why it was written that way.
|
||||
|
||||
Before removing, replacing, or significantly modifying existing code that the plan touches, determine WHY it exists. Check: git blame for the commit that introduced it, comments explaining the rationale, test cases that exercise it, the PLAN.md or SUMMARY.md that created it. If the purpose is unclear, keep it and add a comment noting the uncertainty -- do NOT remove code whose purpose you don't understand. If the plan explicitly says to remove it, still document what it did in the deviation notes.
|
||||
|
||||
---
|
||||
|
||||
## When NOT to Think
|
||||
|
||||
Skip structured reasoning models when the situation does not benefit from them:
|
||||
|
||||
- **Straightforward task actions** -- If the plan says "create file X with content Y" and the action is unambiguous, execute it directly. Do not invoke First Principles to analyze why you are creating a file the plan told you to create.
|
||||
- **Following established project patterns** -- If the codebase has a clear, consistent pattern (e.g., every route handler follows the same structure) and the plan says to add another one, follow the pattern. Chesterton's Fence applies to removing patterns, not to following them.
|
||||
- **Trivial file edits** -- Adding an import, fixing a typo, updating a version number. These are mechanical changes that do not involve design decisions.
|
||||
- **Running verify commands** -- Executing the plan's `<verify>` steps is procedural. Only invoke models if a verify step fails and you need to decide how to respond.
|
||||
62
gsd-core/references/thinking-models-planning.md
Normal file
62
gsd-core/references/thinking-models-planning.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Thinking Models: Planning Cluster
|
||||
|
||||
Structured reasoning models for the **planner** and **roadmapper** agents. Apply these at decision points during plan creation, not continuously. Each model counters a specific documented failure mode.
|
||||
|
||||
Source: Curated from [thinking-partner](https://github.com/mattnowdev/thinking-partner) model catalog (150+ models). Selected for direct applicability to GSD planning workflow.
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
Pre-Mortem and Constraint Analysis both analyze risk at different granularities. Run Constraint Analysis FIRST (identify the hardest constraint), then Pre-Mortem (enumerate failure modes around that constraint and the rest of the plan).
|
||||
|
||||
## 1. Pre-Mortem Analysis
|
||||
|
||||
**Counters:** Optimistic plan decomposition that ignores failure modes.
|
||||
|
||||
Before finalizing this plan, assume it has already failed. List the 3 most likely reasons for failure -- missing dependency, wrong decomposition, underestimated complexity -- and add mitigation steps or acceptance criteria that would catch each failure early.
|
||||
|
||||
## 2. MECE Decomposition
|
||||
|
||||
**Counters:** Overlapping tasks (merge conflicts) or gapped tasks (missing requirements).
|
||||
|
||||
Verify this task breakdown is MECE at the REQUIREMENT level: (1) list every requirement from the phase goal, (2) confirm each maps to exactly one task's `<done>`, (3) if two tasks modify the same file, confirm they modify DIFFERENT sections or serve DIFFERENT requirements, (4) flag any requirement not covered by any task.
|
||||
|
||||
## 3. Constraint Analysis
|
||||
|
||||
**Counters:** Deferring the hardest constraint to the last task, causing late-stage failures.
|
||||
|
||||
Identify the single hardest constraint in this phase -- the one thing that, if it doesn't work, makes everything else irrelevant. Schedule that constraint as Task 1 or 2, not last. If the constraint involves an external API or unfamiliar library, add a spike/proof-of-concept task before the main implementation.
|
||||
|
||||
## 4. Reversibility Test
|
||||
|
||||
**Counters:** Over-analyzing cheap decisions, under-analyzing costly ones.
|
||||
|
||||
For each significant decision in this plan, classify as REVERSIBLE (can change later with low cost) or IRREVERSIBLE (changing later requires migration, breaking changes, or significant rework). Spend analysis time proportional to irreversibility. For irreversible decisions, document the rationale in the plan.
|
||||
|
||||
## 5. Curse of Knowledge Counter
|
||||
|
||||
**Counters:** Plan-to-executor ambiguity from compressed instructions.
|
||||
|
||||
For each `<action>` step, re-read it as if you have NEVER seen this codebase. Is every noun unambiguous (which file? which function? which endpoint?)? Is every verb specific (add WHERE? modify HOW?)? If a step could be interpreted two ways, rewrite it. Include file paths, function names, and expected behavior in every action step.
|
||||
|
||||
## 6. Base Rate Neglect Counter
|
||||
|
||||
**Counters:** Planners ignoring low-confidence research caveats.
|
||||
|
||||
Before finalizing the plan, read ALL `[NEEDS DECISION]` items and LOW-confidence recommendations from SUMMARY.md. For each: either (a) create a `checkpoint:decision` task to resolve it, or (b) document why the risk is acceptable in the plan's deviation notes. LOW-confidence items that are silently accepted become undocumented technical debt.
|
||||
|
||||
## Gap Closure Mode: Root-Cause Check
|
||||
|
||||
**Applies only when:** Planner enters gap closure mode (triggered by `gaps_found` in VERIFICATION.md).
|
||||
|
||||
Before writing the fix plan, apply a single "why" round: Why did this gap occur? Was it a plan deficiency (wrong task), an execution miss (correct task, wrong implementation), or a changed assumption (environment/dependency shift)? The fix plan must target the root cause category, not just the symptom.
|
||||
|
||||
---
|
||||
|
||||
## When NOT to Think
|
||||
|
||||
Skip structured reasoning models when the situation does not benefit from them:
|
||||
|
||||
- **Single-task plans** -- If the phase has one clear requirement and one obvious task, do not run Pre-Mortem or MECE analysis. Write the task directly.
|
||||
- **Well-researched phases** -- If RESEARCH.md has HIGH-confidence recommendations for every decision and no `[NEEDS DECISION]` items, skip Base Rate Neglect Counter. The research already resolved uncertainty.
|
||||
- **Revision iterations** -- When revising a plan based on checker feedback, focus on fixing the flagged issues. Do not re-run the full model suite on every revision pass -- apply only the model relevant to the specific issue (e.g., MECE if the checker found a coverage gap).
|
||||
- **Boilerplate plans** -- Configuration changes, version bumps, documentation updates. These do not have failure modes worth pre-mortem analysis.
|
||||
50
gsd-core/references/thinking-models-research.md
Normal file
50
gsd-core/references/thinking-models-research.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Thinking Models: Research Cluster
|
||||
|
||||
Structured reasoning models for the **researcher** and **synthesizer** agents. Apply these at decision points during research and synthesis, not continuously. Each model counters a specific documented failure mode.
|
||||
|
||||
Source: Curated from [thinking-partner](https://github.com/mattnowdev/thinking-partner) model catalog (150+ models). Selected for direct applicability to GSD research workflow.
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
**First Principles and Steel Man both expand scope** -- run First Principles FIRST (decompose the problem), then Steel Man (strengthen alternatives). Don't run simultaneously.
|
||||
|
||||
## 1. First Principles Thinking
|
||||
|
||||
**Counters:** Accepting surface-level explanations without decomposing into fundamental components.
|
||||
|
||||
Before accepting any technology recommendation or architectural pattern, decompose it to its fundamental constraints: What problem does this solve? What are the non-negotiable requirements? What are the physical/logical limits? Build your recommendation UP from these constraints rather than DOWN from conventional wisdom. If you cannot explain WHY a recommendation is correct from first principles, flag it as `[LOW]` regardless of source count.
|
||||
|
||||
## 2. Simpson's Paradox Awareness
|
||||
|
||||
**Counters:** Synthesizer aggregating conflicting research without checking for confounding splits.
|
||||
|
||||
When combining findings from multiple research documents that show contradictory results, check whether the contradiction disappears when you split by a hidden variable: framework version, deployment target, project scale, or use case category. A library that benchmarks faster overall may be slower for YOUR specific workload. Before resolving contradictions by majority vote, ask: "Is there a subgroup split that explains why both findings are correct in their own context?"
|
||||
|
||||
## 3. Survivorship Bias
|
||||
|
||||
**Counters:** Only finding successful examples while missing failures and abandoned approaches.
|
||||
|
||||
After gathering evidence FOR a recommended approach, actively search for projects that ABANDONED it. Check GitHub issues for "migrated away from", "replaced X with", or "problems with X at scale". A technology with 10 success stories and 100 quiet failures looks great until you check the graveyard. Weight negative evidence (migration-away stories, deprecation notices, unresolved issues) MORE heavily than positive evidence -- failures are underreported.
|
||||
|
||||
## 4. Confirmation Bias Counter
|
||||
|
||||
**Counters:** Searching for evidence that confirms initial hypothesis while ignoring disconfirming evidence.
|
||||
|
||||
After forming your initial recommendation, spend one full research cycle searching AGAINST it. Use search terms like "{technology} problems", "{technology} alternatives", "why not {technology}", "{technology} vs {competitor}". For each piece of disconfirming evidence found, either (a) refute it with higher-confidence sources, or (b) add it as a caveat to your recommendation. If you cannot find ANY criticism of your recommendation, your search was too narrow -- widen it.
|
||||
|
||||
## 5. Steel Man
|
||||
|
||||
**Counters:** Dismissing alternative approaches without giving them their strongest possible form.
|
||||
|
||||
Before recommending against an alternative technology or approach, construct its STRONGEST possible case. What would a passionate advocate say? What use cases does it serve better than your recommendation? What trade-offs favor it? Present the steel-manned alternative alongside your recommendation with an honest comparison. If the steel-manned alternative is competitive, flag the decision as `[NEEDS DECISION]` rather than making a unilateral recommendation.
|
||||
|
||||
---
|
||||
|
||||
## When NOT to Think
|
||||
|
||||
Skip structured reasoning models when the situation does not benefit from them:
|
||||
|
||||
- **Locked decisions from CONTEXT.md** -- If the user already decided "use library X", do not run Steel Man analysis on alternatives or First Principles decomposition of the choice. Research how to use X well, not whether X is the right choice.
|
||||
- **Standard stack lookups** -- If you are simply checking the latest version of a well-known library or reading its API docs, do not invoke Survivorship Bias or Confirmation Bias Counter. These models are for evaluating contested recommendations, not for factual lookups.
|
||||
- **Single-technology phases** -- If the phase involves one technology with no alternatives to evaluate (e.g., "add ESLint rule X"), skip comparative models (Steel Man, Confirmation Bias Counter). Just research the implementation.
|
||||
- **Codebase-only research** -- If the research is purely internal (understanding existing code patterns, finding where a function is called), structured reasoning models add no value. Use grep and read the code.
|
||||
55
gsd-core/references/thinking-models-verification.md
Normal file
55
gsd-core/references/thinking-models-verification.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Thinking Models: Verification Cluster
|
||||
|
||||
Structured reasoning models for the **verifier** and **plan-checker** agents. Apply these during verification passes, not continuously. Each model counters a specific documented failure mode.
|
||||
|
||||
Source: Curated from [thinking-partner](https://github.com/mattnowdev/thinking-partner) model catalog (150+ models). Selected for direct applicability to GSD verification workflow.
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
**Inversion** and **Confirmation Bias Counter** both look for failures but serve different purposes. Run them in sequence:
|
||||
|
||||
1. **Inversion FIRST** (brainstorm): generate 3 ways this could be wrong
|
||||
2. **Confirmation Bias Counter SECOND** (structured check): find one partial requirement, one misleading test, one uncovered error path
|
||||
|
||||
Inversion generates the list; Confirmation Bias Counter is the discipline to verify items on it.
|
||||
|
||||
## 1. Inversion
|
||||
|
||||
**Counters:** Verifiers confirming success rather than finding failures.
|
||||
|
||||
Instead of checking what IS correct, list 3 specific ways this implementation could be WRONG despite passing tests: missing edge cases, silent data loss, race conditions, unhandled error paths. For each, write a concrete check (grep for pattern, test with specific input, verify error handling exists). Additionally, check whether any documented DEVIATION in SUMMARY.md changes the meaning or applicability of a must-have. If a must-have was written assuming approach A but the executor used approach B, the must-have may need reinterpretation, not literal checking.
|
||||
|
||||
## 2. Chesterton's Fence
|
||||
|
||||
**Counters:** Flagging purposeful code as dead or unnecessary.
|
||||
|
||||
Before flagging any existing code as dead, redundant, or overcomplicated, determine WHY it was written that way. Check git blame, comments, test cases, and the PLAN.md that created it. If the reason is unclear, flag as "purpose unknown -- recommend keeping with WARNING, not removing" and include the git blame hash for the commit that introduced it.
|
||||
|
||||
## 3. Confirmation Bias Counter
|
||||
|
||||
**Counters:** Verifiers primed by SUMMARY.md claims to see success.
|
||||
|
||||
After your initial verification pass, do a DISCONFIRMATION pass: (1) find one requirement that is only partially met, (2) find one test that passes but does not actually test the stated behavior, (3) find one error path that has no test coverage. Report these even if overall verification passes.
|
||||
|
||||
## 4. Planning Fallacy Calibration
|
||||
|
||||
**Counters:** Accepting over-scoped plans as reasonable (plan-checker).
|
||||
|
||||
For each task estimated as "simple" or "small", check: does it touch more than 2 files? Does it require understanding an unfamiliar API? Does it modify shared infrastructure? If yes to any, flag as likely underestimated. Plans with >5 tasks or tasks touching >4 files per task are over-scoped.
|
||||
|
||||
## 5. Counterfactual Thinking
|
||||
|
||||
**Counters:** Plans that assume success at every step with no error recovery (plan-checker).
|
||||
|
||||
For each plan, ask: "What would happen if the executor followed this plan EXACTLY as written but encountered a common failure: dependency version mismatch, API returning unexpected format, file already modified by prior plan?" If the plan has no contingency path and the `<action>` steps assume success at every point, flag as WARNING: "No error recovery path for task T{n}."
|
||||
|
||||
---
|
||||
|
||||
## When NOT to Think
|
||||
|
||||
Skip structured reasoning models when the situation does not benefit from them:
|
||||
|
||||
- **Re-verification of previously passed items** -- When in re-verification mode, items that passed the initial check only need a quick regression check (existence + basic sanity), not the full Inversion + Confirmation Bias Counter treatment.
|
||||
- **Binary existence checks** -- If a must-have is "file X exists with >N lines" and the file clearly exists with substantive content, do not run Counterfactual Thinking on it. Reserve models for ambiguous or wiring-dependent must-haves.
|
||||
- **Straightforward test results** -- If `<verify>` commands produce clear pass/fail output (e.g., test suite exits 0 with all tests passing), accept the result. Only invoke models when test results are ambiguous or when you suspect the tests do not actually test what they claim.
|
||||
- **INFO-level issues** -- Do not apply structured reasoning to decide whether an INFO-level observation is actually a BLOCKER. INFO items are informational by definition and never trigger gates.
|
||||
96
gsd-core/references/thinking-partner.md
Normal file
96
gsd-core/references/thinking-partner.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Thinking Partner Integration
|
||||
|
||||
Conditional extended thinking at workflow decision points. Activates when `features.thinking_partner: true` in `.planning/config.json` (default: false).
|
||||
|
||||
---
|
||||
|
||||
## Tradeoff Detection Signals
|
||||
|
||||
The thinking partner activates when developer responses contain specific signals indicating competing priorities:
|
||||
|
||||
**Keyword signals:**
|
||||
- "or" / "versus" / "vs" connecting two approaches
|
||||
- "tradeoff" / "trade-off" / "tradeoffs"
|
||||
- "on one hand" / "on the other hand"
|
||||
- "pros and cons"
|
||||
- "not sure between" / "torn between"
|
||||
|
||||
**Structural signals:**
|
||||
- Developer lists 2+ competing options
|
||||
- Developer asks "which is better" or "what would you recommend"
|
||||
- Developer reverses a previous decision ("actually, maybe we should...")
|
||||
|
||||
**When NOT to activate:**
|
||||
- Developer has already made a clear choice
|
||||
- The "or" is rhetorical or trivial (e.g., "tabs or spaces" — use project convention)
|
||||
- Simple yes/no questions
|
||||
- Developer explicitly asks to move on
|
||||
|
||||
---
|
||||
|
||||
## Integration Points
|
||||
|
||||
### 1. Discuss Phase — Tradeoff Deep-Dive
|
||||
|
||||
**When:** During `discuss_areas` step, after a developer answer reveals competing priorities.
|
||||
|
||||
**What:** Pause the normal question flow and offer a brief structured analysis:
|
||||
```
|
||||
I notice competing priorities here — {X} optimizes for {A} while {Y} optimizes for {B}.
|
||||
|
||||
Want me to think through the tradeoffs before we decide?
|
||||
[Yes, analyze tradeoffs] / [No, I've decided]
|
||||
```
|
||||
|
||||
If yes, provide a brief (3-5 bullet) analysis covering:
|
||||
- What each approach optimizes for
|
||||
- What each approach sacrifices
|
||||
- Which aligns better with the project's stated goals (from PROJECT.md)
|
||||
- A recommendation with reasoning
|
||||
|
||||
Then return to the normal discussion flow.
|
||||
|
||||
### 2. Plan Phase — Architectural Decision Analysis
|
||||
|
||||
**When:** During step 11 (Handle Checker Return), when the plan-checker flags issues containing architectural tradeoff keywords.
|
||||
|
||||
**What:** Before sending to the revision loop, analyze the architectural decision:
|
||||
```
|
||||
The plan-checker flagged an architectural tradeoff: {issue description}
|
||||
|
||||
Brief analysis:
|
||||
- Option A: {approach} — {pros/cons}
|
||||
- Option B: {approach} — {pros/cons}
|
||||
- Recommendation: {choice} because {reasoning aligned with phase goals}
|
||||
|
||||
Apply this recommendation to the revision? [Yes] / [No, let me decide]
|
||||
```
|
||||
|
||||
### 3. Explore — Approach Comparison (requires #1729)
|
||||
|
||||
**When:** During Socratic conversation, when multiple viable approaches emerge.
|
||||
**Note:** This integration point will be added when /gsd:explore (#1729) lands.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"features": {
|
||||
"thinking_partner": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Default: `false`. The thinking partner is opt-in because it adds latency to interactive workflows.
|
||||
|
||||
---
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Lightweight** — inline analysis, not a separate interactive session
|
||||
2. **Opt-in** — must be explicitly enabled, never activates by default
|
||||
3. **Skippable** — always offer "No, I've decided" to bypass
|
||||
4. **Brief** — 3-5 bullets max, not a full research report
|
||||
5. **Aligned** — recommendations reference PROJECT.md goals when available
|
||||
162
gsd-core/references/ui-brand.md
Normal file
162
gsd-core/references/ui-brand.md
Normal file
@@ -0,0 +1,162 @@
|
||||
<ui_patterns>
|
||||
|
||||
Visual patterns for user-facing GSD output. Orchestrators @-reference this file.
|
||||
|
||||
## Stage Banners
|
||||
|
||||
Use for major workflow transitions.
|
||||
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► {STAGE NAME}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
```
|
||||
|
||||
**Stage names (uppercase):**
|
||||
- `QUESTIONING`
|
||||
- `RESEARCHING`
|
||||
- `DEFINING REQUIREMENTS`
|
||||
- `CREATING ROADMAP`
|
||||
- `PLANNING PHASE {N}`
|
||||
- `EXECUTING WAVE {N}`
|
||||
- `VERIFYING`
|
||||
- `PHASE {N} COMPLETE ✓`
|
||||
- `MILESTONE COMPLETE 🎉`
|
||||
|
||||
---
|
||||
|
||||
## Checkpoint Boxes
|
||||
|
||||
User action required. 62-character width.
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ CHECKPOINT: {Type} ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
{Content}
|
||||
|
||||
──────────────────────────────────────────────────────────────
|
||||
→ {ACTION PROMPT}
|
||||
──────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
**Types:**
|
||||
- `CHECKPOINT: Verification Required` → `→ Type "approved" or describe issues`
|
||||
- `CHECKPOINT: Decision Required` → `→ Select: option-a / option-b`
|
||||
- `CHECKPOINT: Action Required` → `→ Type "done" when complete`
|
||||
|
||||
---
|
||||
|
||||
## Status Symbols
|
||||
|
||||
```
|
||||
✓ Complete / Passed / Verified
|
||||
✗ Failed / Missing / Blocked
|
||||
◆ In Progress
|
||||
○ Pending
|
||||
⚡ Auto-approved
|
||||
⚠ Warning
|
||||
🎉 Milestone complete (only in banner)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Progress Display
|
||||
|
||||
**Phase/milestone level:**
|
||||
```
|
||||
Progress: ████████░░ 80%
|
||||
```
|
||||
|
||||
**Task level:**
|
||||
```
|
||||
Tasks: 2/4 complete
|
||||
```
|
||||
|
||||
**Plan level:**
|
||||
```
|
||||
Plans: 3/5 complete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spawning Indicators
|
||||
|
||||
**Liveness convention:** Every spawn announcement must carry the canonical phrase `runs in a subagent` inline so users know that silence during a subagent run is expected. Without this, a healthy 1–5 minute agent looks identical to a frozen session. Single spawns use the singular form; parallel spawns use the plural form.
|
||||
|
||||
```
|
||||
◆ Spawning researcher... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
|
||||
|
||||
◆ Spawning 4 researchers in parallel... (each runs in a subagent — no output until they return, ~1–5 min; expected, not a freeze)
|
||||
→ Stack research
|
||||
→ Features research
|
||||
→ Architecture research
|
||||
→ Pitfalls research
|
||||
|
||||
✓ Researcher complete: STACK.md written
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Up Block
|
||||
|
||||
Always at end of major completions.
|
||||
|
||||
```
|
||||
───────────────────────────────────────────────────────────────
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**{Identifier}: {Name}** — {one-line description}
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`{copy-paste command}`
|
||||
|
||||
───────────────────────────────────────────────────────────────
|
||||
|
||||
**Also available:**
|
||||
- `/gsd-alternative-1` — description
|
||||
- `/gsd-alternative-2` — description
|
||||
|
||||
───────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Box
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════╗
|
||||
║ ERROR ║
|
||||
╚══════════════════════════════════════════════════════════════╝
|
||||
|
||||
{Error description}
|
||||
|
||||
**To fix:** {Resolution steps}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tables
|
||||
|
||||
```
|
||||
| Phase | Status | Plans | Progress |
|
||||
|-------|--------|-------|----------|
|
||||
| 1 | ✓ | 3/3 | 100% |
|
||||
| 2 | ◆ | 1/4 | 25% |
|
||||
| 3 | ○ | 0/2 | 0% |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Varying box/banner widths
|
||||
- Mixing banner styles (`===`, `---`, `***`)
|
||||
- Skipping `GSD ►` prefix in banners
|
||||
- Random emoji (`🚀`, `✨`, `💫`)
|
||||
- Missing Next Up block after completions
|
||||
|
||||
</ui_patterns>
|
||||
63
gsd-core/references/universal-anti-patterns.md
Normal file
63
gsd-core/references/universal-anti-patterns.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Universal Anti-Patterns
|
||||
|
||||
Rules that apply to ALL workflows and agents. Individual workflows may have additional specific anti-patterns.
|
||||
|
||||
---
|
||||
|
||||
## Context Budget Rules
|
||||
|
||||
1. **Never** read agent definition files (`agents/*.md`) -- `subagent_type` auto-loads them. Reading agent definitions into the orchestrator wastes context for content automatically injected into subagent sessions.
|
||||
2. **Never** inline large files into subagent prompts -- tell agents to read files from disk instead. Agents have their own context windows.
|
||||
3. **Read depth scales with context window** -- check `context_window` in `.planning/config.json`. At < 500000: read only frontmatter, status fields, or summaries. At >= 500000 (1M model): full body reads permitted when content is needed for inline decisions. See `references/context-budget.md` for the complete table.
|
||||
4. **Delegate** heavy work to subagents -- the orchestrator routes, it does not build, analyze, research, investigate, or verify.
|
||||
5. **Proactive pause warning**: If you have already consumed significant context (large file reads, multiple subagent results), warn the user: "Context budget is getting heavy. Consider checkpointing progress."
|
||||
|
||||
## File Reading Rules
|
||||
|
||||
6. **SUMMARY.md read depth scales with context window** -- at context_window < 500000: read frontmatter only from prior phase SUMMARYs. At >= 500000: full body reads permitted for direct-dependency phases. Transitive dependencies (2+ phases back) remain frontmatter-only regardless.
|
||||
7. **Never** read full PLAN.md files from other phases -- only current phase plans.
|
||||
8. **Never** read `.planning/logs/` files -- only the health workflow reads these.
|
||||
9. **Do not** re-read full file contents when frontmatter is sufficient -- frontmatter contains status, key_files, commits, and provides fields. Exception: at >= 500000, re-reading full body is acceptable when semantic content is needed.
|
||||
|
||||
## Subagent Rules
|
||||
|
||||
10. **NEVER** use non-GSD agent types (`general-purpose`, `Explore`, `Plan`, `Bash`, `feature-dev`, etc.) -- ALWAYS use `subagent_type: "gsd-{agent}"` (e.g., `gsd-phase-researcher`, `gsd-executor`, `gsd-planner`). GSD agents have project-aware prompts, audit logging, and workflow context. Generic agents bypass all of this.
|
||||
11. **Do not** re-litigate decisions that are already locked in CONTEXT.md (or PROJECT.md ## Context section) -- respect locked decisions unconditionally.
|
||||
|
||||
## Questioning Anti-Patterns
|
||||
|
||||
Reference: `references/questioning.md` for the full anti-pattern list.
|
||||
|
||||
12. **Do not** walk through checklists -- checklist walking (asking items one by one from a list) is the #1 anti-pattern. Instead, use progressive depth: start broad, dig where interesting.
|
||||
13. **Do not** use corporate speak -- avoid jargon like "stakeholder alignment", "synergize", "deliverables". Use plain language.
|
||||
14. **Do not** apply premature constraints -- don't narrow the solution space before understanding the problem. Ask about the problem first, then constrain.
|
||||
|
||||
## State Management Anti-Patterns
|
||||
|
||||
15. **No direct Write/Edit to STATE.md or ROADMAP.md for mutations.** Always use `gsd-tools query` for registered state/roadmap handlers (e.g. `state.update`, `state.advance-plan`, `roadmap.update-plan-progress`), or legacy `node …/gsd-tools.cjs` for CLI-only commands. Direct Write tool usage bypasses safe update logic and is unsafe in multi-session environments. Exception: first-time creation of STATE.md from template is allowed.
|
||||
|
||||
## Behavioral Rules
|
||||
|
||||
16. **Do not** create artifacts the user did not approve -- always confirm before writing new planning documents.
|
||||
17. **Do not** modify files outside the workflow's stated scope -- check the plan's files_modified list.
|
||||
18. **Do not** suggest multiple next actions without clear priority -- one primary suggestion, alternatives listed secondary.
|
||||
19. **Do not** use `git add .` or `git add -A` -- stage specific files only.
|
||||
20. **Do not** include sensitive information (API keys, passwords, tokens) in planning documents or commits.
|
||||
|
||||
## Error Recovery Rules
|
||||
|
||||
21. **Git lock detection**: Before any git operation, if it fails with "Unable to create lock file", check for stale `.git/index.lock` and advise the user to remove it (do not remove automatically).
|
||||
22. **Config fallback awareness**: Config loading returns `null` silently on invalid JSON. If your workflow depends on config values, check for null and warn the user: "config.json is invalid or missing -- running with defaults."
|
||||
23. **Partial state recovery**: If STATE.md references a phase directory that doesn't exist, do not proceed silently. Warn the user and suggest diagnosing the mismatch.
|
||||
|
||||
## GSD-Specific Rules
|
||||
|
||||
24. **Do not** check for `mode === 'auto'` or `mode === 'autonomous'` -- GSD uses `yolo` config flag. Check `yolo: true` for autonomous mode, absence or `false` for interactive mode.
|
||||
25. **Prefer `gsd-tools query`** for orchestration when a handler exists; when shelling out to the legacy CLI, use **`gsd-tools.cjs`** (not `gsd-tools.js` or any other filename) — GSD ships the programmatic API as CommonJS for Node.js CLI compatibility.
|
||||
26. **Plan files MUST follow `{padded_phase}-{NN}-PLAN.md` pattern** (e.g., `01-01-PLAN.md`). Never use `PLAN-01.md`, `plan-01.md`, or any other variation -- gsd-tools detection depends on this exact pattern.
|
||||
27. **Do not start executing the next plan before writing the SUMMARY.md for the current plan** -- downstream plans may reference it via `@` includes.
|
||||
|
||||
## iOS / Apple Platform Rules
|
||||
|
||||
28. **NEVER use `Package.swift` + `.executableTarget` (or `.target`) as the primary build system for iOS apps.** SPM executable targets produce macOS CLI binaries, not iOS `.app` bundles. They cannot be installed on iOS devices or submitted to the App Store. Use XcodeGen (`project.yml` + `xcodegen generate`) to create a proper `.xcodeproj`. See `references/ios-scaffold.md` for the full pattern.
|
||||
29. **Verify SwiftUI API availability before use.** Many SwiftUI APIs require a specific minimum iOS version (e.g., `NavigationSplitView` is iOS 16+, `List(selection:)` with multi-select and `@Observable` require iOS 17). If a plan uses an API that exceeds the declared `IPHONEOS_DEPLOYMENT_TARGET`, raise the deployment target or add `#available` guards.
|
||||
681
gsd-core/references/user-profiling.md
Normal file
681
gsd-core/references/user-profiling.md
Normal file
@@ -0,0 +1,681 @@
|
||||
# User Profiling: Detection Heuristics Reference
|
||||
|
||||
This reference document defines detection heuristics for behavioral profiling across 8 dimensions. The gsd-user-profiler agent applies these rules when analyzing extracted session messages. Do not invent dimensions or scoring rules beyond what is defined here.
|
||||
|
||||
## How to Use This Document
|
||||
|
||||
1. The gsd-user-profiler agent reads this document before analyzing any messages
|
||||
2. For each dimension, the agent scans messages for the signal patterns defined below
|
||||
3. The agent applies the detection heuristics to classify the developer's pattern
|
||||
4. Confidence is scored using the thresholds defined per dimension
|
||||
5. Evidence quotes are curated using the rules in the Evidence Curation section
|
||||
6. Output must conform to the JSON schema in the Output Schema section
|
||||
|
||||
---
|
||||
|
||||
## Dimensions
|
||||
|
||||
### 1. Communication Style
|
||||
|
||||
`dimension_id: communication_style`
|
||||
|
||||
**What we're measuring:** How the developer phrases requests, instructions, and feedback -- the structural pattern of their messages to Claude.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `terse-direct` | Short, imperative messages with minimal context. Gets to the point immediately. |
|
||||
| `conversational` | Medium-length messages mixing instructions with questions and thinking-aloud. Natural, informal tone. |
|
||||
| `detailed-structured` | Long messages with explicit structure -- headers, numbered lists, problem statements, pre-analysis. |
|
||||
| `mixed` | No dominant pattern; style shifts based on task type or project context. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Message length distribution** -- Average word count across messages. Terse < 50 words, conversational 50-200 words, detailed > 200 words.
|
||||
2. **Imperative-to-interrogative ratio** -- Ratio of commands ("fix this", "add X") to questions ("what do you think?", "should we?"). High imperative ratio suggests terse-direct.
|
||||
3. **Structural formatting** -- Presence of markdown headers, numbered lists, code blocks, or bullet points within messages. Frequent formatting suggests detailed-structured.
|
||||
4. **Context preambles** -- Whether the developer provides background/context before making a request. Preambles suggest conversational or detailed-structured.
|
||||
5. **Sentence completeness** -- Whether messages use full sentences or fragments/shorthand. Fragments suggest terse-direct.
|
||||
6. **Follow-up pattern** -- Whether the developer provides additional context in subsequent messages (multi-message requests suggest conversational).
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If average message length < 50 words AND predominantly imperative mood AND minimal formatting --> `terse-direct`
|
||||
2. If average message length 50-200 words AND mix of imperative and interrogative AND occasional formatting --> `conversational`
|
||||
3. If average message length > 200 words AND frequent structural formatting AND context preambles present --> `detailed-structured`
|
||||
4. If message length variance is high (std dev > 60% of mean) AND no single pattern dominates (< 60% of messages match one style) --> `mixed`
|
||||
5. If pattern varies systematically by project type (e.g., terse in CLI projects, detailed in frontend) --> `mixed` with context-dependent note
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ messages showing consistent pattern (> 70% match), same pattern observed across 2+ projects
|
||||
- **MEDIUM:** 5-9 messages showing pattern, OR pattern consistent within 1 project only
|
||||
- **LOW:** < 5 messages with relevant signals, OR mixed signals (contradictory patterns observed in similar contexts)
|
||||
- **UNSCORED:** 0 messages with relevant signals for this dimension
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **terse-direct:** "fix the auth bug" / "add pagination to the list endpoint" / "this test is failing, make it pass"
|
||||
- **conversational:** "I'm thinking we should probably handle the error case here. What do you think about returning a 422 instead of a 500? The client needs to know it was a validation issue."
|
||||
- **detailed-structured:** "## Context\nThe auth flow currently uses session cookies but we need to migrate to JWT.\n\n## Requirements\n1. Access tokens (15min expiry)\n2. Refresh tokens (7-day)\n3. httpOnly cookies\n\n## What I've tried\nI looked at jose and jsonwebtoken..."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
When communication style varies systematically by project or task type, report the split rather than forcing a single rating. Example: "context-dependent: terse-direct for bug fixes and CLI tooling, detailed-structured for architecture and frontend work." Phase 3 orchestration resolves context-dependent splits by presenting the split to the user.
|
||||
|
||||
---
|
||||
|
||||
### 2. Decision Speed
|
||||
|
||||
`dimension_id: decision_speed`
|
||||
|
||||
**What we're measuring:** How quickly the developer makes choices when Claude presents options, alternatives, or trade-offs.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `fast-intuitive` | Decides immediately based on experience or gut feeling. Minimal deliberation. |
|
||||
| `deliberate-informed` | Requests comparison or summary before deciding. Wants to understand trade-offs. |
|
||||
| `research-first` | Delays decision to research independently. May leave and return with findings. |
|
||||
| `delegator` | Defers to Claude's recommendation. Trusts the suggestion. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Response latency to options** -- How many messages between Claude presenting options and developer choosing. Immediate (same message or next) suggests fast-intuitive.
|
||||
2. **Comparison requests** -- Presence of "compare these", "what are the trade-offs?", "pros and cons?" suggests deliberate-informed.
|
||||
3. **External research indicators** -- Messages like "I looked into X and...", "according to the docs...", "I read that..." suggest research-first.
|
||||
4. **Delegation language** -- "just pick one", "whatever you recommend", "your call", "go with the best option" suggests delegator.
|
||||
5. **Decision reversal frequency** -- How often the developer changes a decision after making it. Frequent reversals may indicate fast-intuitive with low confidence.
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer selects options within 1-2 messages of presentation AND uses decisive language ("use X", "go with A") AND rarely asks for comparisons --> `fast-intuitive`
|
||||
2. If developer requests trade-off analysis or comparison tables AND decides after receiving comparison AND asks clarifying questions --> `deliberate-informed`
|
||||
3. If developer defers decisions with "let me look into this" AND returns with external information AND cites documentation or articles --> `research-first`
|
||||
4. If developer uses delegation language (> 3 instances) AND rarely overrides Claude's choices AND says "sounds good" or "your call" --> `delegator`
|
||||
5. If no clear pattern OR evidence is split across multiple styles --> classify as the dominant style with a context-dependent note
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ decision points observed showing consistent pattern, same pattern across 2+ projects
|
||||
- **MEDIUM:** 5-9 decision points, OR consistent within 1 project only
|
||||
- **LOW:** < 5 decision points observed, OR mixed decision-making styles
|
||||
- **UNSCORED:** 0 messages containing decision-relevant signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **fast-intuitive:** "Use Tailwind. Next question." / "Option B, let's move on"
|
||||
- **deliberate-informed:** "Can you compare Prisma vs Drizzle for this use case? I want to understand the migration story and type safety differences before I pick."
|
||||
- **research-first:** "Hold off on the DB choice -- I want to read the Drizzle docs and check their GitHub issues first. I'll come back with a decision."
|
||||
- **delegator:** "You know more about this than me. Whatever you recommend, go with it."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Decision speed often varies by stakes. A developer may be fast-intuitive for styling choices but research-first for database or auth decisions. When this pattern is clear, report the split: "context-dependent: fast-intuitive for low-stakes (styling, naming), deliberate-informed for high-stakes (architecture, security)."
|
||||
|
||||
---
|
||||
|
||||
### 3. Explanation Depth
|
||||
|
||||
`dimension_id: explanation_depth`
|
||||
|
||||
**What we're measuring:** How much explanation the developer wants alongside code -- their preference for understanding vs. speed.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `code-only` | Wants working code with minimal or no explanation. Reads and understands code directly. |
|
||||
| `concise` | Wants brief explanation of approach with code. Key decisions noted, not exhaustive. |
|
||||
| `detailed` | Wants thorough walkthrough of the approach, reasoning, and code. Appreciates structure. |
|
||||
| `educational` | Wants deep conceptual explanation. Treats interactions as learning opportunities. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Explicit depth requests** -- "just show me the code", "explain why", "teach me about X", "skip the explanation"
|
||||
2. **Reaction to explanations** -- Does the developer skip past explanations? Ask for more detail? Say "too much"?
|
||||
3. **Follow-up question depth** -- Surface-level follow-ups ("does it work?") vs. conceptual ("why this pattern over X?")
|
||||
4. **Code comprehension signals** -- Does the developer reference implementation details in their messages? This suggests they read and understand code directly.
|
||||
5. **"I know this" signals** -- Messages like "I'm familiar with X", "skip the basics", "I know how hooks work" indicate lower explanation preference.
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer says "just the code" or "skip the explanation" AND rarely asks follow-up conceptual questions AND references code details directly --> `code-only`
|
||||
2. If developer accepts brief explanations without asking for more AND asks focused follow-ups about specific decisions --> `concise`
|
||||
3. If developer asks "why" questions AND requests walkthroughs AND appreciates structured explanations --> `detailed`
|
||||
4. If developer asks conceptual questions beyond the immediate task AND uses learning language ("I want to understand", "teach me") --> `educational`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ messages showing consistent preference, same preference across 2+ projects
|
||||
- **MEDIUM:** 5-9 messages, OR consistent within 1 project only
|
||||
- **LOW:** < 5 relevant messages, OR preferences shift between interactions
|
||||
- **UNSCORED:** 0 messages with relevant signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **code-only:** "Just give me the implementation. I'll read through it." / "Skip the explanation, show the code."
|
||||
- **concise:** "Quick summary of the approach, then the code please." / "Why did you use a Map here instead of an object?"
|
||||
- **detailed:** "Walk me through this step by step. I want to understand the auth flow before we implement it."
|
||||
- **educational:** "Can you explain how JWT refresh token rotation works conceptually? I want to understand the security model, not just implement it."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Explanation depth often correlates with domain familiarity. A developer may want code-only for well-known tech but educational for new domains. Report splits when observed: "context-dependent: code-only for React/TypeScript, detailed for database optimization."
|
||||
|
||||
---
|
||||
|
||||
### 4. Debugging Approach
|
||||
|
||||
`dimension_id: debugging_approach`
|
||||
|
||||
**What we're measuring:** How the developer approaches problems, errors, and unexpected behavior when working with Claude.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `fix-first` | Pastes error, wants it fixed. Minimal diagnosis interest. Results-oriented. |
|
||||
| `diagnostic` | Shares error with context, wants to understand the cause before fixing. |
|
||||
| `hypothesis-driven` | Investigates independently first, brings specific theories to Claude for validation. |
|
||||
| `collaborative` | Wants to work through the problem step-by-step with Claude as a partner. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Error presentation style** -- Raw error paste only (fix-first) vs. error + "I think it might be..." (hypothesis-driven) vs. "Can you help me understand why..." (diagnostic)
|
||||
2. **Pre-investigation indicators** -- Does the developer share what they already tried? Do they mention reading logs, checking state, or isolating the issue?
|
||||
3. **Root cause interest** -- After a fix, does the developer ask "why did that happen?" or just move on?
|
||||
4. **Step-by-step language** -- "Let's check X first", "what should we look at next?", "walk me through the debugging"
|
||||
5. **Fix acceptance pattern** -- Does the developer immediately apply fixes or question them first?
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer pastes errors without context AND accepts fixes without root cause questions AND moves on immediately --> `fix-first`
|
||||
2. If developer provides error context AND asks "why is this happening?" AND wants explanation with the fix --> `diagnostic`
|
||||
3. If developer shares their own analysis AND proposes theories ("I think the issue is X because...") AND asks Claude to confirm or refute --> `hypothesis-driven`
|
||||
4. If developer uses collaborative language ("let's", "what should we check?") AND prefers incremental diagnosis AND walks through problems together --> `collaborative`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ debugging interactions showing consistent approach, same approach across 2+ projects
|
||||
- **MEDIUM:** 5-9 debugging interactions, OR consistent within 1 project only
|
||||
- **LOW:** < 5 debugging interactions, OR approach varies significantly
|
||||
- **UNSCORED:** 0 messages with debugging-relevant signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **fix-first:** "Getting this error: TypeError: Cannot read properties of undefined. Fix it."
|
||||
- **diagnostic:** "The API returns 500 when I send a POST to /users. Here's the request body and the server log. What's causing this?"
|
||||
- **hypothesis-driven:** "I think the race condition is in the useEffect cleanup. I checked and the subscription isn't being cancelled on unmount. Can you confirm?"
|
||||
- **collaborative:** "Let's debug this together. The test passes locally but fails in CI. What should we check first?"
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Debugging approach may vary by urgency. A developer might be fix-first under deadline pressure but hypothesis-driven during regular development. Note temporal patterns if detected.
|
||||
|
||||
---
|
||||
|
||||
### 5. UX Philosophy
|
||||
|
||||
`dimension_id: ux_philosophy`
|
||||
|
||||
**What we're measuring:** How the developer prioritizes user experience, design, and visual quality relative to functionality.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `function-first` | Get it working, polish later. Minimal UX concern during implementation. |
|
||||
| `pragmatic` | Basic usability from the start. Nothing ugly or broken, but no design obsession. |
|
||||
| `design-conscious` | Design and UX are treated as important as functionality. Attention to visual detail. |
|
||||
| `backend-focused` | Primarily builds backend/CLI. Minimal frontend exposure or interest. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Design-related requests** -- Mentions of styling, layout, responsiveness, animations, color schemes, spacing
|
||||
2. **Polish timing** -- Does the developer ask for visual polish during implementation or defer it?
|
||||
3. **UI feedback specificity** -- Vague ("make it look better") vs. specific ("increase the padding to 16px, change the font weight to 600")
|
||||
4. **Frontend vs. backend distribution** -- Ratio of frontend-focused requests to backend-focused requests
|
||||
5. **Accessibility mentions** -- References to a11y, screen readers, keyboard navigation, ARIA labels
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer rarely mentions UI/UX AND focuses on logic, APIs, data AND defers styling ("we'll make it pretty later") --> `function-first`
|
||||
2. If developer includes basic UX requirements AND mentions usability but not pixel-perfection AND balances form with function --> `pragmatic`
|
||||
3. If developer provides specific design requirements AND mentions polish, animations, spacing AND treats UI bugs as seriously as logic bugs --> `design-conscious`
|
||||
4. If developer works primarily on CLI tools, APIs, or backend systems AND rarely or never works on frontend AND messages focus on data, performance, infrastructure --> `backend-focused`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ messages with UX-relevant signals, same pattern across 2+ projects
|
||||
- **MEDIUM:** 5-9 messages, OR consistent within 1 project only
|
||||
- **LOW:** < 5 relevant messages, OR philosophy varies by project type
|
||||
- **UNSCORED:** 0 messages with UX-relevant signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **function-first:** "Just get the form working. We'll style it later." / "I don't care how it looks, I need the data flowing."
|
||||
- **pragmatic:** "Make sure the loading state is visible and the error messages are clear. Standard styling is fine."
|
||||
- **design-conscious:** "The button needs more breathing room -- add 12px vertical padding and make the hover state transition 200ms. Also check the contrast ratio."
|
||||
- **backend-focused:** "I'm building a CLI tool. No UI needed." / "Add the REST endpoint, I'll handle the frontend separately."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
UX philosophy is inherently project-dependent. A developer building a CLI tool is necessarily backend-focused for that project. When possible, distinguish between project-driven and preference-driven patterns. If the developer only has backend projects, note that the rating reflects available data: "backend-focused (note: all analyzed projects are backend/CLI -- may not reflect frontend preferences)."
|
||||
|
||||
---
|
||||
|
||||
### 6. Vendor Philosophy
|
||||
|
||||
`dimension_id: vendor_philosophy`
|
||||
|
||||
**What we're measuring:** How the developer approaches choosing and evaluating libraries, frameworks, and external services.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `pragmatic-fast` | Uses what works, what Claude suggests, or what's fastest. Minimal evaluation. |
|
||||
| `conservative` | Prefers well-known, battle-tested, widely-adopted options. Risk-averse. |
|
||||
| `thorough-evaluator` | Researches alternatives, reads docs, compares features and trade-offs before committing. |
|
||||
| `opinionated` | Has strong, pre-existing preferences for specific tools. Knows what they like. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Library selection language** -- "just use whatever", "is X the standard?", "I want to compare A vs B", "we're using X, period"
|
||||
2. **Evaluation depth** -- Does the developer accept the first suggestion or ask for alternatives?
|
||||
3. **Stated preferences** -- Explicit mentions of preferred tools, past experience, or tool philosophy
|
||||
4. **Rejection patterns** -- Does the developer reject Claude's suggestions? On what basis (popularity, personal experience, docs quality)?
|
||||
5. **Dependency attitude** -- "minimize dependencies", "no external deps", "add whatever we need" -- reveals philosophy about external code
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer accepts library suggestions without pushback AND uses phrases like "sounds good" or "go with that" AND rarely asks about alternatives --> `pragmatic-fast`
|
||||
2. If developer asks about popularity, maintenance, community AND prefers "industry standard" or "battle-tested" AND avoids new/experimental --> `conservative`
|
||||
3. If developer requests comparisons AND reads docs before deciding AND asks about edge cases, license, bundle size --> `thorough-evaluator`
|
||||
4. If developer names specific libraries unprompted AND overrides Claude's suggestions AND expresses strong preferences --> `opinionated`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ vendor/library decisions observed, same pattern across 2+ projects
|
||||
- **MEDIUM:** 5-9 decisions, OR consistent within 1 project only
|
||||
- **LOW:** < 5 vendor decisions observed, OR pattern varies
|
||||
- **UNSCORED:** 0 messages with vendor-selection signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **pragmatic-fast:** "Use whatever ORM you recommend. I just need it working." / "Sure, Tailwind is fine."
|
||||
- **conservative:** "Is Prisma the most widely used ORM for this? I want something with a large community." / "Let's stick with what most teams use."
|
||||
- **thorough-evaluator:** "Before we pick a state management library, can you compare Zustand vs Jotai vs Redux Toolkit? I want to understand bundle size, API surface, and TypeScript support."
|
||||
- **opinionated:** "We're using Drizzle, not Prisma. I've used both and Drizzle's SQL-like API is better for complex queries."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Vendor philosophy may shift based on project importance or domain. Personal projects may use pragmatic-fast while professional projects use thorough-evaluator. Report the split if detected.
|
||||
|
||||
---
|
||||
|
||||
### 7. Frustration Triggers
|
||||
|
||||
`dimension_id: frustration_triggers`
|
||||
|
||||
**What we're measuring:** What causes visible frustration, correction, or negative emotional signals in the developer's messages to Claude.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `scope-creep` | Frustrated when Claude does things that were not asked for. Wants bounded execution. |
|
||||
| `instruction-adherence` | Frustrated when Claude doesn't follow instructions precisely. Values exactness. |
|
||||
| `verbosity` | Frustrated when Claude over-explains or is too wordy. Wants conciseness. |
|
||||
| `regression` | Frustrated when Claude breaks working code while fixing something else. Values stability. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Correction language** -- "I didn't ask for that", "don't do X", "I said Y not Z", "why did you change this?"
|
||||
2. **Repetition patterns** -- Repeating the same instruction with emphasis suggests instruction-adherence frustration
|
||||
3. **Emotional tone shifts** -- Shift from neutral to terse, use of capitals, exclamation marks, explicit frustration words
|
||||
4. **"Don't" statements** -- "don't add extra features", "don't explain so much", "don't touch that file" -- what they prohibit reveals what frustrates them
|
||||
5. **Frustration recovery** -- How quickly the developer returns to neutral tone after a frustration event
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer corrects Claude for doing unrequested work AND uses language like "I only asked for X", "stop adding things", "stick to what I asked" --> `scope-creep`
|
||||
2. If developer repeats instructions AND corrects specific deviations from stated requirements AND emphasizes precision ("I specifically said...") --> `instruction-adherence`
|
||||
3. If developer asks Claude to be shorter AND skips explanations AND expresses annoyance at length ("too much", "just the answer") --> `verbosity`
|
||||
4. If developer expresses frustration at broken functionality AND checks for regressions AND says "you broke X while fixing Y" --> `regression`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ frustration events showing consistent trigger pattern, same trigger across 2+ projects
|
||||
- **MEDIUM:** 5-9 frustration events, OR consistent within 1 project only
|
||||
- **LOW:** < 5 frustration events observed (note: low frustration count is POSITIVE -- it means the developer is generally satisfied, not that data is insufficient)
|
||||
- **UNSCORED:** 0 messages with frustration signals (note: "no frustration detected" is a valid finding)
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **scope-creep:** "I asked you to fix the login bug, not refactor the entire auth module. Revert everything except the bug fix."
|
||||
- **instruction-adherence:** "I said to use a Map, not an object. I was specific about this. Please redo it with a Map."
|
||||
- **verbosity:** "Way too much explanation. Just show me the code change, nothing else."
|
||||
- **regression:** "The search was working fine before. Now after your 'fix' to the filter, search results are empty. Don't touch things I didn't ask you to change."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Frustration triggers tend to be consistent across projects (personality-driven, not project-driven). However, their intensity may vary with project stakes. If multiple frustration triggers are observed, report the primary (most frequent) and note secondaries.
|
||||
|
||||
---
|
||||
|
||||
### 8. Learning Style
|
||||
|
||||
`dimension_id: learning_style`
|
||||
|
||||
**What we're measuring:** How the developer prefers to understand new concepts, tools, or patterns they encounter.
|
||||
|
||||
**Rating spectrum:**
|
||||
|
||||
| Rating | Description |
|
||||
|--------|-------------|
|
||||
| `self-directed` | Reads code directly, figures things out independently. Asks Claude specific questions. |
|
||||
| `guided` | Asks Claude to explain relevant parts. Prefers guided understanding. |
|
||||
| `documentation-first` | Reads official docs and tutorials before diving in. References documentation. |
|
||||
| `example-driven` | Wants working examples to modify and learn from. Pattern-matching learner. |
|
||||
|
||||
**Signal patterns:**
|
||||
|
||||
1. **Learning initiation** -- Does the developer start by reading code, asking for explanation, requesting docs, or asking for examples?
|
||||
2. **Reference to external sources** -- Mentions of documentation, tutorials, Stack Overflow, blog posts suggest documentation-first
|
||||
3. **Example requests** -- "show me an example", "can you give me a sample?", "let me see how this looks in practice"
|
||||
4. **Code-reading indicators** -- "I looked at the implementation", "I see that X calls Y", "from reading the code..."
|
||||
5. **Explanation requests vs. code requests** -- Ratio of "explain X" to "show me X" messages
|
||||
|
||||
**Detection heuristics:**
|
||||
|
||||
1. If developer references reading code directly AND asks specific targeted questions AND demonstrates independent investigation --> `self-directed`
|
||||
2. If developer asks Claude to explain concepts AND requests walkthroughs AND prefers Claude-mediated understanding --> `guided`
|
||||
3. If developer cites documentation AND asks for doc links AND mentions reading tutorials or official guides --> `documentation-first`
|
||||
4. If developer requests examples AND modifies provided examples AND learns by pattern matching --> `example-driven`
|
||||
|
||||
**Confidence scoring:**
|
||||
|
||||
- **HIGH:** 10+ learning interactions showing consistent preference, same preference across 2+ projects
|
||||
- **MEDIUM:** 5-9 learning interactions, OR consistent within 1 project only
|
||||
- **LOW:** < 5 learning interactions, OR preference varies by topic familiarity
|
||||
- **UNSCORED:** 0 messages with learning-relevant signals
|
||||
|
||||
**Example quotes:**
|
||||
|
||||
- **self-directed:** "I read through the middleware code. The issue is that the token check happens after the rate limiter. Should those be swapped?"
|
||||
- **guided:** "Can you walk me through how the auth flow works in this codebase? Start from the login request."
|
||||
- **documentation-first:** "I read the Prisma docs on relations. Can you help me apply the many-to-many pattern from their guide to our schema?"
|
||||
- **example-driven:** "Show me a working example of a protected API route with JWT validation. I'll adapt it for our endpoints."
|
||||
|
||||
**Context-dependent patterns:**
|
||||
|
||||
Learning style often varies with domain expertise. A developer may be self-directed in familiar domains but guided or example-driven in new ones. Report the split if detected: "context-dependent: self-directed for TypeScript/Node, example-driven for Rust/systems programming."
|
||||
|
||||
---
|
||||
|
||||
## Evidence Curation
|
||||
|
||||
### Evidence Format
|
||||
|
||||
Use the combined format for each evidence entry:
|
||||
|
||||
**Signal:** [pattern interpretation -- what the quote demonstrates] / **Example:** "[trimmed quote, ~100 characters]" -- project: [project name]
|
||||
|
||||
### Evidence Targets
|
||||
|
||||
- **3 evidence quotes per dimension** (24 total across all 8 dimensions)
|
||||
- Select quotes that best illustrate the rated pattern
|
||||
- Prefer quotes from different projects to demonstrate cross-project consistency
|
||||
- When fewer than 3 relevant quotes exist, include what is available and note the evidence count
|
||||
|
||||
### Quote Truncation
|
||||
|
||||
- Trim quotes to the behavioral signal -- the part that demonstrates the pattern
|
||||
- Target approximately 100 characters per quote
|
||||
- Preserve the meaningful fragment, not the full message
|
||||
- If the signal is in the middle of a long message, use "..." to indicate trimming
|
||||
- Never include the full 500-character message when 50 characters capture the signal
|
||||
|
||||
### Project Attribution
|
||||
|
||||
- Every evidence quote must include the project name
|
||||
- Project attribution enables verification and shows cross-project patterns
|
||||
- Format: `-- project: [name]`
|
||||
|
||||
### Sensitive Content Exclusion (Layer 1)
|
||||
|
||||
The profiler agent must never select quotes containing any of the following patterns:
|
||||
|
||||
- `sk-` (API key prefixes)
|
||||
- `Bearer ` (auth tokens)
|
||||
- `password` (credentials)
|
||||
- `secret` (secrets)
|
||||
- `token` (when used as a credential value, not a concept discussion)
|
||||
- `api_key` or `API_KEY` (API key references)
|
||||
- Full absolute file paths containing usernames (e.g., `/Users/john/...`, `/home/john/...`)
|
||||
|
||||
**When sensitive content is found and excluded**, report as metadata in the analysis output:
|
||||
|
||||
```json
|
||||
{
|
||||
"sensitive_excluded": [
|
||||
{ "type": "api_key_pattern", "count": 2 },
|
||||
{ "type": "file_path_with_username", "count": 1 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This metadata enables defense-in-depth auditing. Layer 2 (regex filter in the write-profile step) provides a second pass, but the profiler should still avoid selecting sensitive quotes.
|
||||
|
||||
### Natural Language Priority
|
||||
|
||||
Weight natural language messages higher than:
|
||||
- Pasted log output (detected by timestamps, repeated format strings, `[DEBUG]`, `[INFO]`, `[ERROR]`)
|
||||
- Session context dumps (messages starting with "This session is being continued from a previous conversation")
|
||||
- Large code pastes (messages where > 80% of content is inside code fences)
|
||||
|
||||
These message types are genuine but carry less behavioral signal. Deprioritize them when selecting evidence quotes.
|
||||
|
||||
---
|
||||
|
||||
## Recency Weighting
|
||||
|
||||
### Guideline
|
||||
|
||||
Recent sessions (last 30 days) should be weighted approximately 3x compared to older sessions when analyzing patterns.
|
||||
|
||||
### Rationale
|
||||
|
||||
Developer styles evolve. A developer who was terse six months ago may now provide detailed structured context. Recent behavior is a more accurate reflection of current working style.
|
||||
|
||||
### Application
|
||||
|
||||
1. When counting signals for confidence scoring, recent signals count 3x (e.g., 4 recent signals = 12 weighted signals)
|
||||
2. When selecting evidence quotes, prefer recent quotes over older ones when both demonstrate the same pattern
|
||||
3. When patterns conflict between recent and older sessions, the recent pattern takes precedence for the rating, but note the evolution: "recently shifted from terse-direct to conversational"
|
||||
4. The 30-day window is relative to the analysis date, not a fixed date
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- If ALL sessions are older than 30 days, apply no weighting (all sessions are equally stale)
|
||||
- If ALL sessions are within the last 30 days, apply no weighting (all sessions are equally recent)
|
||||
- The 3x weight is a guideline, not a hard multiplier -- use judgment when the weighted count changes a confidence threshold
|
||||
|
||||
---
|
||||
|
||||
## Thin Data Handling
|
||||
|
||||
### Message Thresholds
|
||||
|
||||
| Total Genuine Messages | Mode | Behavior |
|
||||
|------------------------|------|----------|
|
||||
| > 50 | `full` | Full analysis across all 8 dimensions. Questionnaire optional (user can choose to supplement). |
|
||||
| 20-50 | `hybrid` | Analyze available messages. Score each dimension with confidence. Supplement with questionnaire for LOW/UNSCORED dimensions. |
|
||||
| < 20 | `insufficient` | All dimensions scored LOW or UNSCORED. Recommend questionnaire fallback as primary profile source. Note: "insufficient session data for behavioral analysis." |
|
||||
|
||||
### Handling Insufficient Dimensions
|
||||
|
||||
When a specific dimension has insufficient data (even if total messages exceed thresholds):
|
||||
|
||||
- Set confidence to `UNSCORED`
|
||||
- Set summary to: "Insufficient data -- no clear signals detected for this dimension."
|
||||
- Set claude_instruction to a neutral fallback: "No strong preference detected. Ask the developer when this dimension is relevant."
|
||||
- Set evidence_quotes to empty array `[]`
|
||||
- Set evidence_count to `0`
|
||||
|
||||
### Questionnaire Supplement
|
||||
|
||||
When operating in `hybrid` mode, the questionnaire fills gaps for dimensions where session analysis produced LOW or UNSCORED confidence. The questionnaire-derived ratings use:
|
||||
- **MEDIUM** confidence for strong, definitive picks
|
||||
- **LOW** confidence for "it varies" or ambiguous selections
|
||||
|
||||
If session analysis and questionnaire agree on a dimension, confidence can be elevated (e.g., session LOW + questionnaire MEDIUM agreement = MEDIUM).
|
||||
|
||||
---
|
||||
|
||||
## Output Schema
|
||||
|
||||
The profiler agent must return JSON matching this exact schema, wrapped in `<analysis>` tags.
|
||||
|
||||
```json
|
||||
{
|
||||
"profile_version": "1.0",
|
||||
"analyzed_at": "ISO-8601 timestamp",
|
||||
"data_source": "session_analysis",
|
||||
"projects_analyzed": ["project-name-1", "project-name-2"],
|
||||
"messages_analyzed": 0,
|
||||
"message_threshold": "full|hybrid|insufficient",
|
||||
"sensitive_excluded": [
|
||||
{ "type": "string", "count": 0 }
|
||||
],
|
||||
"dimensions": {
|
||||
"communication_style": {
|
||||
"rating": "terse-direct|conversational|detailed-structured|mixed",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [
|
||||
{
|
||||
"signal": "Pattern interpretation describing what the quote demonstrates",
|
||||
"quote": "Trimmed quote, approximately 100 characters",
|
||||
"project": "project-name"
|
||||
}
|
||||
],
|
||||
"summary": "One to two sentence description of the observed pattern",
|
||||
"claude_instruction": "Imperative directive for Claude: 'Match structured communication style' not 'You tend to provide structured context'"
|
||||
},
|
||||
"decision_speed": {
|
||||
"rating": "fast-intuitive|deliberate-informed|research-first|delegator",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"explanation_depth": {
|
||||
"rating": "code-only|concise|detailed|educational",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"debugging_approach": {
|
||||
"rating": "fix-first|diagnostic|hypothesis-driven|collaborative",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"ux_philosophy": {
|
||||
"rating": "function-first|pragmatic|design-conscious|backend-focused",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"vendor_philosophy": {
|
||||
"rating": "pragmatic-fast|conservative|thorough-evaluator|opinionated",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"frustration_triggers": {
|
||||
"rating": "scope-creep|instruction-adherence|verbosity|regression",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
},
|
||||
"learning_style": {
|
||||
"rating": "self-directed|guided|documentation-first|example-driven",
|
||||
"confidence": "HIGH|MEDIUM|LOW|UNSCORED",
|
||||
"evidence_count": 0,
|
||||
"cross_project_consistent": true,
|
||||
"evidence_quotes": [],
|
||||
"summary": "string",
|
||||
"claude_instruction": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Schema Notes
|
||||
|
||||
- **`profile_version`**: Always `"1.0"` for this schema version
|
||||
- **`analyzed_at`**: ISO-8601 timestamp of when the analysis was performed
|
||||
- **`data_source`**: `"session_analysis"` for session-based profiling, `"questionnaire"` for questionnaire-only, `"hybrid"` for combined
|
||||
- **`projects_analyzed`**: List of project names that contributed messages
|
||||
- **`messages_analyzed`**: Total number of genuine user messages processed
|
||||
- **`message_threshold`**: Which threshold mode was triggered (`full`, `hybrid`, `insufficient`)
|
||||
- **`sensitive_excluded`**: Array of excluded sensitive content types with counts (empty array if none found)
|
||||
- **`claude_instruction`**: Must be written in imperative form directed at Claude. This field is how the profile becomes actionable.
|
||||
- Good: "Provide structured responses with headers and numbered lists to match this developer's communication style."
|
||||
- Bad: "You tend to like structured responses."
|
||||
- Good: "Ask before making changes beyond the stated request -- this developer values bounded execution."
|
||||
- Bad: "The developer gets frustrated when you do extra work."
|
||||
|
||||
---
|
||||
|
||||
## Cross-Project Consistency
|
||||
|
||||
### Assessment
|
||||
|
||||
For each dimension, assess whether the observed pattern is consistent across the projects analyzed:
|
||||
|
||||
- **`cross_project_consistent: true`** -- Same rating would apply regardless of which project is analyzed. Evidence from 2+ projects shows the same pattern.
|
||||
- **`cross_project_consistent: false`** -- Pattern varies by project. Include a context-dependent note in the summary.
|
||||
|
||||
### Reporting Splits
|
||||
|
||||
When `cross_project_consistent` is false, the summary must describe the split:
|
||||
|
||||
- "Context-dependent: terse-direct for CLI/backend projects (gsd-tools, api-server), detailed-structured for frontend projects (dashboard, landing-page)."
|
||||
- "Context-dependent: fast-intuitive for familiar tech (React, Node), research-first for new domains (Rust, ML)."
|
||||
|
||||
The rating field should reflect the **dominant** pattern (most evidence). The summary describes the nuance.
|
||||
|
||||
### Phase 3 Resolution
|
||||
|
||||
Context-dependent splits are resolved during Phase 3 orchestration. The orchestrator presents the split to the developer and asks which pattern represents their general preference. Until resolved, Claude uses the dominant pattern with awareness of the context-dependent variation.
|
||||
|
||||
---
|
||||
|
||||
*Reference document version: 1.0*
|
||||
*Dimensions: 8*
|
||||
*Schema: profile_version 1.0*
|
||||
58
gsd-core/references/user-story-template.md
Normal file
58
gsd-core/references/user-story-template.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# User Story Template (MVP Mode)
|
||||
|
||||
> Used by `mvp-phase` workflow and `gsd-planner` agent when `MVP_MODE=true`. Defines the canonical "As a / I want to / So that" format and the rules for converting it into the `**Goal:**` line in ROADMAP.md.
|
||||
|
||||
## Canonical format
|
||||
|
||||
```
|
||||
As a [user role], I want to [capability], so that [outcome].
|
||||
```
|
||||
|
||||
Three required components:
|
||||
|
||||
| Slot | Question | Examples |
|
||||
|---|---|---|
|
||||
| `[user role]` | Who is the actor? | "new user", "admin", "signed-in customer", "API consumer" |
|
||||
| `[capability]` | What can they do? | "register and log in", "upload a CSV", "see my dashboard" |
|
||||
| `[outcome]` | Why does it matter? | "I can access my account", "I can bulk-import contacts", "I can see at a glance what needs attention" |
|
||||
|
||||
All three must be present. Refuse to assemble a partial story.
|
||||
|
||||
## How it lands in ROADMAP.md
|
||||
|
||||
The full user story replaces the existing `**Goal:**` line in the phase section:
|
||||
|
||||
**Before:**
|
||||
```
|
||||
### Phase 1: User Auth MVP
|
||||
**Goal:** Users can register and log in
|
||||
```
|
||||
|
||||
**After:**
|
||||
```
|
||||
### Phase 1: User Auth MVP
|
||||
**Goal:** As a new user, I want to register and log in, so that I can access my dashboard.
|
||||
**Mode:** mvp
|
||||
```
|
||||
|
||||
Two structural rules:
|
||||
1. The `**Goal:**` line stays on a single line (no line breaks inside the story). If the story is longer than ~120 chars, it should be split into multiple phases via SPIDR (see `spidr-splitting.md`).
|
||||
2. The `**Mode:** mvp` line is added immediately below `**Goal:**`. If `**Mode:**` already exists, it is replaced (not duplicated).
|
||||
|
||||
## How it lands in PLAN.md
|
||||
|
||||
The `gsd-planner` agent (with MVP_MODE=true) emits the user story as the first content under the phase header in `PLAN.md`:
|
||||
|
||||
```markdown
|
||||
## Phase Goal
|
||||
|
||||
**As a** new user, **I want to** register and log in, **so that** I can access my dashboard.
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] ...
|
||||
|
||||
## MVP Slice Tasks
|
||||
...
|
||||
```
|
||||
|
||||
Note the bold-keyword formatting (`**As a**`, `**I want to**`, `**so that**`) is for the PLAN.md emit only. The ROADMAP.md `**Goal:**` line uses prose form (the keywords are not bolded inside the goal line, since the goal is itself a single bolded label).
|
||||
227
gsd-core/references/verification-overrides.md
Normal file
227
gsd-core/references/verification-overrides.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Verification Overrides
|
||||
|
||||
Mechanism for intentionally accepting must-have failures when the deviation is known and acceptable. Prevents verification loops on items that will never pass as originally specified.
|
||||
|
||||
<override_format>
|
||||
|
||||
## Override Format
|
||||
|
||||
Overrides are declared in the VERIFICATION.md frontmatter under an `overrides:` key:
|
||||
|
||||
```yaml
|
||||
---
|
||||
phase: 03-authentication
|
||||
verified: 2026-04-05T12:00:00Z
|
||||
status: passed
|
||||
score: 5/5
|
||||
overrides_applied: 2
|
||||
overrides:
|
||||
- must_have: "OAuth2 PKCE flow implemented"
|
||||
reason: "Using session-based auth instead — PKCE unnecessary for server-rendered app"
|
||||
accepted_by: "dave"
|
||||
accepted_at: "2026-04-04T15:30:00Z"
|
||||
- must_have: "Rate limiting on login endpoint"
|
||||
reason: "Deferred to Phase 5 (infrastructure) — tracked in ROADMAP.md"
|
||||
accepted_by: "dave"
|
||||
accepted_at: "2026-04-04T15:30:00Z"
|
||||
---
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `must_have` | string | The must-have truth, artifact description, or key link being overridden. Does not need to be an exact match — fuzzy matching applies. |
|
||||
| `reason` | string | Why this deviation is acceptable. Must be specific — not just "not needed". |
|
||||
| `accepted_by` | string | Who accepted the override (username or role). Required. |
|
||||
| `accepted_at` | string | ISO timestamp of when the override was accepted. Required. |
|
||||
|
||||
</override_format>
|
||||
|
||||
## When to Use
|
||||
|
||||
Overrides apply when a phase intentionally deviated from the original plan during execution — for example, a requirement was descoped, an alternative approach was chosen, or a dependency changed.
|
||||
|
||||
Without overrides, the verifier reports these as FAIL even though the deviation was intentional. Overrides let the developer mark specific items as `PASSED (override)` with a documented reason.
|
||||
|
||||
Overrides are appropriate when:
|
||||
- A requirement changed after planning but ROADMAP.md hasn't been updated yet
|
||||
- An alternative implementation satisfies the intent but not the literal wording
|
||||
- A must-have is deferred to a later phase with explicit tracking
|
||||
- External constraints make the original must-have impossible or unnecessary
|
||||
|
||||
## When NOT to Use
|
||||
|
||||
Overrides are NOT appropriate when:
|
||||
- The implementation is simply incomplete — fix it instead
|
||||
- The must-have is unclear — clarify it instead
|
||||
- The developer wants to skip verification — that undermines the process
|
||||
- Multiple must-haves are failing for the same phase — if more than 2-3 items need overrides, revisit the plan instead of overriding in bulk
|
||||
|
||||
<matching_rules>
|
||||
|
||||
## Matching Rules
|
||||
|
||||
Override matching uses **fuzzy matching**, not exact string comparison. This accommodates minor wording differences between how must-haves are phrased in ROADMAP.md, PLAN.md frontmatter, and the override entry.
|
||||
|
||||
### Matching Algorithm
|
||||
|
||||
1. **Normalize both strings:** case-insensitive comparison — lowercase both strings, strip punctuation, collapse whitespace
|
||||
2. **Token overlap:** split into words, compute intersection
|
||||
3. **Match threshold:** 80% token overlap in EITHER direction (override tokens found in must-have, OR must-have tokens found in override)
|
||||
4. **Key noun priority:** nouns and technical terms (file paths, component names, API endpoints) are weighted higher than common words
|
||||
|
||||
### Examples
|
||||
|
||||
| Must-Have | Override `must_have` | Match? | Reason |
|
||||
|-----------|---------------------|--------|--------|
|
||||
| "User can authenticate via OAuth2 PKCE" | "OAuth2 PKCE flow implemented" | Yes | Key terms `OAuth2` and `PKCE` overlap, 80% threshold met |
|
||||
| "Rate limiting on /api/auth/login" | "Rate limiting on login endpoint" | Yes | `rate limiting` + `login` overlap |
|
||||
| "Chat component renders messages" | "OAuth2 PKCE flow implemented" | No | No meaningful token overlap |
|
||||
| "src/components/Chat.tsx provides message list" | "Chat.tsx message list rendering" | Yes | `Chat.tsx` + `message` + `list` overlap |
|
||||
|
||||
### Ambiguity Resolution
|
||||
|
||||
If an override matches multiple must-haves, apply it to the **most specific match** (highest token overlap percentage). If still ambiguous, apply to the first match and log a warning.
|
||||
|
||||
</matching_rules>
|
||||
|
||||
<verifier_behavior>
|
||||
|
||||
## Verifier Behavior with Overrides
|
||||
|
||||
### Check Order
|
||||
|
||||
The override check happens **before marking a must-have as FAIL**. The flow is:
|
||||
|
||||
1. Evaluate must-have against codebase (Steps 3-5 of verification process)
|
||||
2. If evaluation result is FAIL or UNCERTAIN:
|
||||
a. Check `overrides:` array in VERIFICATION.md frontmatter for a fuzzy match
|
||||
b. If override found: mark as `PASSED (override)` instead of FAIL
|
||||
c. If no override found: mark as FAIL as normal
|
||||
3. If evaluation result is PASS: mark as VERIFIED (overrides are irrelevant)
|
||||
|
||||
### Output Format
|
||||
|
||||
Overridden items appear with distinct status in all verification tables:
|
||||
|
||||
```markdown
|
||||
| # | Truth | Status | Evidence |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | User can authenticate | VERIFIED | OAuth session flow working |
|
||||
| 2 | OAuth2 PKCE flow | PASSED (override) | Override: Using session-based auth — accepted by dave on 2026-04-04 |
|
||||
| 3 | Chat renders messages | FAILED | Component returns placeholder |
|
||||
```
|
||||
|
||||
The `PASSED (override)` status must be visually distinct from both `VERIFIED` and `FAILED`. In the evidence column, include the override reason and who accepted it.
|
||||
|
||||
### Impact on Overall Status
|
||||
|
||||
- `PASSED (override)` items count toward the passing score, not the failing score
|
||||
- A phase with all items either VERIFIED or PASSED (override) can have status `passed`
|
||||
- Overrides do NOT suppress `human_needed` items — those still require human testing
|
||||
|
||||
### Frontmatter Score
|
||||
|
||||
The score and override count in frontmatter reflect applied overrides:
|
||||
|
||||
```yaml
|
||||
score: 5/5 # includes 2 overrides
|
||||
overrides_applied: 2
|
||||
```
|
||||
|
||||
</verifier_behavior>
|
||||
|
||||
<creating_overrides>
|
||||
|
||||
## Creating Overrides
|
||||
|
||||
### Interactive Override Suggestion
|
||||
|
||||
When the verifier marks a must-have as FAIL and the failure looks intentional (e.g., alternative implementation exists, or the code explicitly handles the case differently), the verifier should suggest creating an override:
|
||||
|
||||
```markdown
|
||||
### F-002: OAuth2 PKCE flow
|
||||
|
||||
**Status:** FAILED
|
||||
**Evidence:** No PKCE implementation found. Session-based auth used instead.
|
||||
|
||||
**This looks intentional.** The codebase uses session-based authentication which achieves the same goal differently. To accept this deviation, add an override to VERIFICATION.md frontmatter:
|
||||
|
||||
```yaml
|
||||
overrides:
|
||||
- must_have: "OAuth2 PKCE flow implemented"
|
||||
reason: "Using session-based auth instead — PKCE unnecessary for server-rendered app"
|
||||
accepted_by: "{your name}"
|
||||
accepted_at: "{current ISO timestamp}"
|
||||
```
|
||||
|
||||
Then re-run verification to apply.
|
||||
```
|
||||
|
||||
### Override via gsd-tools
|
||||
|
||||
Overrides can also be managed through the verification workflow:
|
||||
|
||||
1. Run `/gsd:verify-work` — verification finds gaps
|
||||
2. Review gaps — determine which are intentional deviations
|
||||
3. Add override entries to VERIFICATION.md frontmatter
|
||||
4. Re-run `/gsd:verify-work` — overrides are applied, remaining gaps shown
|
||||
|
||||
</creating_overrides>
|
||||
|
||||
<override_lifecycle>
|
||||
|
||||
## Override Lifecycle
|
||||
|
||||
### During Re-verification
|
||||
|
||||
When a phase is re-verified (e.g., after gap closure):
|
||||
- Existing overrides carry forward automatically
|
||||
- If the underlying code now satisfies the must-have, the override becomes unnecessary — mark as VERIFIED instead
|
||||
- Overrides are never removed automatically; they persist as documentation
|
||||
|
||||
### At Milestone Completion
|
||||
|
||||
During `/gsd:audit-milestone`, overrides are surfaced in the audit report:
|
||||
|
||||
```
|
||||
### Verification Overrides ({count} across {phase_count} phases)
|
||||
|
||||
| Phase | Must-Have | Reason | Accepted By |
|
||||
|-------|----------|--------|-------------|
|
||||
| 03 | OAuth2 PKCE | Session-based auth used instead | dave |
|
||||
```
|
||||
|
||||
This gives the team visibility into all accepted deviations before closing the milestone.
|
||||
|
||||
### Cleanup
|
||||
|
||||
Stale overrides (where the must-have was later implemented or removed from ROADMAP.md) can be cleaned up during milestone completion. They are informational — leaving them causes no harm.
|
||||
|
||||
</override_lifecycle>
|
||||
|
||||
## Example VERIFICATION.md
|
||||
|
||||
```markdown
|
||||
---
|
||||
phase: 03-api-layer
|
||||
verified: 2026-04-05T12:00:00Z
|
||||
status: passed
|
||||
score: 3/3
|
||||
overrides_applied: 1
|
||||
overrides:
|
||||
- must_have: "paginated API responses"
|
||||
reason: "Descoped — dataset under 100 items, pagination adds complexity without value"
|
||||
accepted_by: "dave"
|
||||
accepted_at: "2026-04-04T15:30:00Z"
|
||||
---
|
||||
|
||||
## Phase 3: API Layer — Verification
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | REST endpoints return JSON | VERIFIED | curl tests confirm |
|
||||
| 2 | Paginated API responses | PASSED (override) | Descoped — see override: dataset under 100 items |
|
||||
| 3 | Authentication middleware | VERIFIED | JWT validation working |
|
||||
```
|
||||
612
gsd-core/references/verification-patterns.md
Normal file
612
gsd-core/references/verification-patterns.md
Normal file
@@ -0,0 +1,612 @@
|
||||
# Verification Patterns
|
||||
|
||||
How to verify different types of artifacts are real implementations, not stubs or placeholders.
|
||||
|
||||
<core_principle>
|
||||
**Existence ≠ Implementation**
|
||||
|
||||
A file existing does not mean the feature works. Verification must check:
|
||||
1. **Exists** - File is present at expected path
|
||||
2. **Substantive** - Content is real implementation, not placeholder
|
||||
3. **Wired** - Connected to the rest of the system
|
||||
4. **Functional** - Actually works when invoked
|
||||
|
||||
Levels 1-3 can be checked programmatically. Level 4 often requires human verification.
|
||||
</core_principle>
|
||||
|
||||
<stub_detection>
|
||||
|
||||
## Universal Stub Patterns
|
||||
|
||||
These patterns indicate placeholder code regardless of file type:
|
||||
|
||||
**Comment-based stubs:**
|
||||
```bash
|
||||
# Grep patterns for stub comments
|
||||
grep -E "(TODO|FIXME|XXX|HACK|PLACEHOLDER)" "$file"
|
||||
grep -E "implement|add later|coming soon|will be" "$file" -i
|
||||
grep -E "// \.\.\.|/\* \.\.\. \*/|# \.\.\." "$file"
|
||||
```
|
||||
|
||||
**Placeholder text in output:**
|
||||
```bash
|
||||
# UI placeholder patterns
|
||||
grep -E "placeholder|lorem ipsum|coming soon|under construction" "$file" -i
|
||||
grep -E "sample|example|test data|dummy" "$file" -i
|
||||
grep -E "\[.*\]|<.*>|\{.*\}" "$file" # Template brackets left in
|
||||
```
|
||||
|
||||
**Empty or trivial implementations:**
|
||||
```bash
|
||||
# Functions that do nothing
|
||||
grep -E "return null|return undefined|return \{\}|return \[\]" "$file"
|
||||
grep -E "pass$|\.\.\.|\bnothing\b" "$file"
|
||||
grep -E "console\.(log|warn|error).*only" "$file" # Log-only functions
|
||||
```
|
||||
|
||||
**Hardcoded values where dynamic expected:**
|
||||
```bash
|
||||
# Hardcoded IDs, counts, or content
|
||||
grep -E "id.*=.*['\"].*['\"]" "$file" # Hardcoded string IDs
|
||||
grep -E "count.*=.*\d+|length.*=.*\d+" "$file" # Hardcoded counts
|
||||
grep -E "\\\$\d+\.\d{2}|\d+ items" "$file" # Hardcoded display values
|
||||
```
|
||||
|
||||
</stub_detection>
|
||||
|
||||
<react_components>
|
||||
|
||||
## React/Next.js Components
|
||||
|
||||
**Existence check:**
|
||||
```bash
|
||||
# File exists and exports component
|
||||
[ -f "$component_path" ] && grep -E "export (default |)function|export const.*=.*\(" "$component_path"
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Returns actual JSX, not placeholder
|
||||
grep -E "return.*<" "$component_path" | grep -v "return.*null" | grep -v "placeholder" -i
|
||||
|
||||
# Has meaningful content (not just wrapper div)
|
||||
grep -E "<[A-Z][a-zA-Z]+|className=|onClick=|onChange=" "$component_path"
|
||||
|
||||
# Uses props or state (not static)
|
||||
grep -E "props\.|useState|useEffect|useContext|\{.*\}" "$component_path"
|
||||
```
|
||||
|
||||
**Stub patterns specific to React:**
|
||||
```javascript
|
||||
// RED FLAGS - These are stubs:
|
||||
return <div>Component</div>
|
||||
return <div>Placeholder</div>
|
||||
return <div>{/* TODO */}</div>
|
||||
return <p>Coming soon</p>
|
||||
return null
|
||||
return <></>
|
||||
|
||||
// Also stubs - empty handlers:
|
||||
onClick={() => {}}
|
||||
onChange={() => console.log('clicked')}
|
||||
onSubmit={(e) => e.preventDefault()} // Only prevents default, does nothing
|
||||
```
|
||||
|
||||
**Wiring check:**
|
||||
```bash
|
||||
# Component imports what it needs
|
||||
grep -E "^import.*from" "$component_path"
|
||||
|
||||
# Props are actually used (not just received)
|
||||
# Look for destructuring or props.X usage
|
||||
grep -E "\{ .* \}.*props|\bprops\.[a-zA-Z]+" "$component_path"
|
||||
|
||||
# API calls exist (for data-fetching components)
|
||||
grep -E "fetch\(|axios\.|useSWR|useQuery|getServerSideProps|getStaticProps" "$component_path"
|
||||
```
|
||||
|
||||
**Functional verification (human required):**
|
||||
- Does the component render visible content?
|
||||
- Do interactive elements respond to clicks?
|
||||
- Does data load and display?
|
||||
- Do error states show appropriately?
|
||||
|
||||
</react_components>
|
||||
|
||||
<api_routes>
|
||||
|
||||
## API Routes (Next.js App Router / Express / etc.)
|
||||
|
||||
**Existence check:**
|
||||
```bash
|
||||
# Route file exists
|
||||
[ -f "$route_path" ]
|
||||
|
||||
# Exports HTTP method handlers (Next.js App Router)
|
||||
grep -E "export (async )?(function|const) (GET|POST|PUT|PATCH|DELETE)" "$route_path"
|
||||
|
||||
# Or Express-style handlers
|
||||
grep -E "\.(get|post|put|patch|delete)\(" "$route_path"
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Has actual logic, not just return statement
|
||||
wc -l "$route_path" # More than 10-15 lines suggests real implementation
|
||||
|
||||
# Interacts with data source
|
||||
grep -E "prisma\.|db\.|mongoose\.|sql|query|find|create|update|delete" "$route_path" -i
|
||||
|
||||
# Has error handling
|
||||
grep -E "try|catch|throw|error|Error" "$route_path"
|
||||
|
||||
# Returns meaningful response
|
||||
grep -E "Response\.json|res\.json|res\.send|return.*\{" "$route_path" | grep -v "message.*not implemented" -i
|
||||
```
|
||||
|
||||
**Stub patterns specific to API routes:**
|
||||
```typescript
|
||||
// RED FLAGS - These are stubs:
|
||||
export async function POST() {
|
||||
return Response.json({ message: "Not implemented" })
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
return Response.json([]) // Empty array with no DB query
|
||||
}
|
||||
|
||||
export async function PUT() {
|
||||
return new Response() // Empty response
|
||||
}
|
||||
|
||||
// Console log only:
|
||||
export async function POST(req) {
|
||||
console.log(await req.json())
|
||||
return Response.json({ ok: true })
|
||||
}
|
||||
```
|
||||
|
||||
**Wiring check:**
|
||||
```bash
|
||||
# Imports database/service clients
|
||||
grep -E "^import.*prisma|^import.*db|^import.*client" "$route_path"
|
||||
|
||||
# Actually uses request body (for POST/PUT)
|
||||
grep -E "req\.json\(\)|req\.body|request\.json\(\)" "$route_path"
|
||||
|
||||
# Validates input (not just trusting request)
|
||||
grep -E "schema\.parse|validate|zod|yup|joi" "$route_path"
|
||||
```
|
||||
|
||||
**Functional verification (human or automated):**
|
||||
- Does GET return real data from database?
|
||||
- Does POST actually create a record?
|
||||
- Does error response have correct status code?
|
||||
- Are auth checks actually enforced?
|
||||
|
||||
</api_routes>
|
||||
|
||||
<database_schema>
|
||||
|
||||
## Database Schema (Prisma / Drizzle / SQL)
|
||||
|
||||
**Existence check:**
|
||||
```bash
|
||||
# Schema file exists
|
||||
[ -f "prisma/schema.prisma" ] || [ -f "drizzle/schema.ts" ] || [ -f "src/db/schema.sql" ]
|
||||
|
||||
# Model/table is defined
|
||||
grep -E "^model $model_name|CREATE TABLE $table_name|export const $table_name" "$schema_path"
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Has expected fields (not just id)
|
||||
grep -A 20 "model $model_name" "$schema_path" | grep -E "^\s+\w+\s+\w+"
|
||||
|
||||
# Has relationships if expected
|
||||
grep -E "@relation|REFERENCES|FOREIGN KEY" "$schema_path"
|
||||
|
||||
# Has appropriate field types (not all String)
|
||||
grep -A 20 "model $model_name" "$schema_path" | grep -E "Int|DateTime|Boolean|Float|Decimal|Json"
|
||||
```
|
||||
|
||||
**Stub patterns specific to schemas:**
|
||||
```prisma
|
||||
// RED FLAGS - These are stubs:
|
||||
model User {
|
||||
id String @id
|
||||
// TODO: add fields
|
||||
}
|
||||
|
||||
model Message {
|
||||
id String @id
|
||||
content String // Only one real field
|
||||
}
|
||||
|
||||
// Missing critical fields:
|
||||
model Order {
|
||||
id String @id
|
||||
// No: userId, items, total, status, createdAt
|
||||
}
|
||||
```
|
||||
|
||||
**Wiring check:**
|
||||
```bash
|
||||
# Migrations exist and are applied
|
||||
ls prisma/migrations/ 2>/dev/null | wc -l # Should be > 0
|
||||
npx prisma migrate status 2>/dev/null | grep -v "pending"
|
||||
|
||||
# Client is generated
|
||||
[ -d "node_modules/.prisma/client" ]
|
||||
```
|
||||
|
||||
**Functional verification:**
|
||||
```bash
|
||||
# Can query the table (automated)
|
||||
npx prisma db execute --stdin <<< "SELECT COUNT(*) FROM $table_name"
|
||||
```
|
||||
|
||||
</database_schema>
|
||||
|
||||
<hooks_utilities>
|
||||
|
||||
## Custom Hooks and Utilities
|
||||
|
||||
**Existence check:**
|
||||
```bash
|
||||
# File exists and exports function
|
||||
[ -f "$hook_path" ] && grep -E "export (default )?(function|const)" "$hook_path"
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Hook uses React hooks (for custom hooks)
|
||||
grep -E "useState|useEffect|useCallback|useMemo|useRef|useContext" "$hook_path"
|
||||
|
||||
# Has meaningful return value
|
||||
grep -E "return \{|return \[" "$hook_path"
|
||||
|
||||
# More than trivial length
|
||||
[ $(wc -l < "$hook_path") -gt 10 ]
|
||||
```
|
||||
|
||||
**Stub patterns specific to hooks:**
|
||||
```typescript
|
||||
// RED FLAGS - These are stubs:
|
||||
export function useAuth() {
|
||||
return { user: null, login: () => {}, logout: () => {} }
|
||||
}
|
||||
|
||||
export function useCart() {
|
||||
const [items, setItems] = useState([])
|
||||
return { items, addItem: () => console.log('add'), removeItem: () => {} }
|
||||
}
|
||||
|
||||
// Hardcoded return:
|
||||
export function useUser() {
|
||||
return { name: "Test User", email: "test@example.com" }
|
||||
}
|
||||
```
|
||||
|
||||
**Wiring check:**
|
||||
```bash
|
||||
# Hook is actually imported somewhere
|
||||
grep -r "import.*$hook_name" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_path"
|
||||
|
||||
# Hook is actually called
|
||||
grep -r "$hook_name()" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_path"
|
||||
```
|
||||
|
||||
</hooks_utilities>
|
||||
|
||||
<environment_config>
|
||||
|
||||
## Environment Variables and Configuration
|
||||
|
||||
**Existence check:**
|
||||
```bash
|
||||
# .env file exists
|
||||
[ -f ".env" ] || [ -f ".env.local" ]
|
||||
|
||||
# Required variable is defined
|
||||
grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Variable has actual value (not placeholder)
|
||||
grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
|
||||
|
||||
# Value looks valid for type:
|
||||
# - URLs should start with http
|
||||
# - Keys should be long enough
|
||||
# - Booleans should be true/false
|
||||
```
|
||||
|
||||
**Stub patterns specific to env:**
|
||||
```bash
|
||||
# RED FLAGS - These are stubs:
|
||||
DATABASE_URL=your-database-url-here
|
||||
STRIPE_SECRET_KEY=sk_test_xxx
|
||||
API_KEY=placeholder
|
||||
NEXT_PUBLIC_API_URL=http://localhost:3000 # Still pointing to localhost in prod
|
||||
```
|
||||
|
||||
**Wiring check:**
|
||||
```bash
|
||||
# Variable is actually used in code
|
||||
grep -r "process\.env\.$VAR_NAME|env\.$VAR_NAME" src/ --include="*.ts" --include="*.tsx"
|
||||
|
||||
# Variable is in validation schema (if using zod/etc for env)
|
||||
grep -E "$VAR_NAME" src/env.ts src/env.mjs 2>/dev/null
|
||||
```
|
||||
|
||||
</environment_config>
|
||||
|
||||
<wiring_verification>
|
||||
|
||||
## Wiring Verification Patterns
|
||||
|
||||
Wiring verification checks that components actually communicate. This is where most stubs hide.
|
||||
|
||||
### Pattern: Component → API
|
||||
|
||||
**Check:** Does the component actually call the API?
|
||||
|
||||
```bash
|
||||
# Find the fetch/axios call
|
||||
grep -E "fetch\(['\"].*$api_path|axios\.(get|post).*$api_path" "$component_path"
|
||||
|
||||
# Verify it's not commented out
|
||||
grep -E "fetch\(|axios\." "$component_path" | grep -v "^.*//.*fetch"
|
||||
|
||||
# Check the response is used
|
||||
grep -E "await.*fetch|\.then\(|setData|setState" "$component_path"
|
||||
```
|
||||
|
||||
**Red flags:**
|
||||
```typescript
|
||||
// Fetch exists but response ignored:
|
||||
fetch('/api/messages') // No await, no .then, no assignment
|
||||
|
||||
// Fetch in comment:
|
||||
// fetch('/api/messages').then(r => r.json()).then(setMessages)
|
||||
|
||||
// Fetch to wrong endpoint:
|
||||
fetch('/api/message') // Typo - should be /api/messages
|
||||
```
|
||||
|
||||
### Pattern: API → Database
|
||||
|
||||
**Check:** Does the API route actually query the database?
|
||||
|
||||
```bash
|
||||
# Find the database call
|
||||
grep -E "prisma\.$model|db\.query|Model\.find" "$route_path"
|
||||
|
||||
# Verify it's awaited
|
||||
grep -E "await.*prisma|await.*db\." "$route_path"
|
||||
|
||||
# Check result is returned
|
||||
grep -E "return.*json.*data|res\.json.*result" "$route_path"
|
||||
```
|
||||
|
||||
**Red flags:**
|
||||
```typescript
|
||||
// Query exists but result not returned:
|
||||
await prisma.message.findMany()
|
||||
return Response.json({ ok: true }) // Returns static, not query result
|
||||
|
||||
// Query not awaited:
|
||||
const messages = prisma.message.findMany() // Missing await
|
||||
return Response.json(messages) // Returns Promise, not data
|
||||
```
|
||||
|
||||
### Pattern: Form → Handler
|
||||
|
||||
**Check:** Does the form submission actually do something?
|
||||
|
||||
```bash
|
||||
# Find onSubmit handler
|
||||
grep -E "onSubmit=\{|handleSubmit" "$component_path"
|
||||
|
||||
# Check handler has content
|
||||
grep -A 10 "onSubmit.*=" "$component_path" | grep -E "fetch|axios|mutate|dispatch"
|
||||
|
||||
# Verify not just preventDefault
|
||||
grep -A 5 "onSubmit" "$component_path" | grep -v "only.*preventDefault" -i
|
||||
```
|
||||
|
||||
**Red flags:**
|
||||
```typescript
|
||||
// Handler only prevents default:
|
||||
onSubmit={(e) => e.preventDefault()}
|
||||
|
||||
// Handler only logs:
|
||||
const handleSubmit = (data) => {
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
// Handler is empty:
|
||||
onSubmit={() => {}}
|
||||
```
|
||||
|
||||
### Pattern: State → Render
|
||||
|
||||
**Check:** Does the component render state, not hardcoded content?
|
||||
|
||||
```bash
|
||||
# Find state usage in JSX
|
||||
grep -E "\{.*messages.*\}|\{.*data.*\}|\{.*items.*\}" "$component_path"
|
||||
|
||||
# Check map/render of state
|
||||
grep -E "\.map\(|\.filter\(|\.reduce\(" "$component_path"
|
||||
|
||||
# Verify dynamic content
|
||||
grep -E "\{[a-zA-Z_]+\." "$component_path" # Variable interpolation
|
||||
```
|
||||
|
||||
**Red flags:**
|
||||
```tsx
|
||||
// Hardcoded instead of state:
|
||||
return <div>
|
||||
<p>Message 1</p>
|
||||
<p>Message 2</p>
|
||||
</div>
|
||||
|
||||
// State exists but not rendered:
|
||||
const [messages, setMessages] = useState([])
|
||||
return <div>No messages</div> // Always shows "no messages"
|
||||
|
||||
// Wrong state rendered:
|
||||
const [messages, setMessages] = useState([])
|
||||
return <div>{otherData.map(...)}</div> // Uses different data
|
||||
```
|
||||
|
||||
</wiring_verification>
|
||||
|
||||
<verification_checklist>
|
||||
|
||||
## Quick Verification Checklist
|
||||
|
||||
For each artifact type, run through this checklist:
|
||||
|
||||
### Component Checklist
|
||||
- [ ] File exists at expected path
|
||||
- [ ] Exports a function/const component
|
||||
- [ ] Returns JSX (not null/empty)
|
||||
- [ ] No placeholder text in render
|
||||
- [ ] Uses props or state (not static)
|
||||
- [ ] Event handlers have real implementations
|
||||
- [ ] Imports resolve correctly
|
||||
- [ ] Used somewhere in the app
|
||||
|
||||
### API Route Checklist
|
||||
- [ ] File exists at expected path
|
||||
- [ ] Exports HTTP method handlers
|
||||
- [ ] Handlers have more than 5 lines
|
||||
- [ ] Queries database or service
|
||||
- [ ] Returns meaningful response (not empty/placeholder)
|
||||
- [ ] Has error handling
|
||||
- [ ] Validates input
|
||||
- [ ] Called from frontend
|
||||
|
||||
### Schema Checklist
|
||||
- [ ] Model/table defined
|
||||
- [ ] Has all expected fields
|
||||
- [ ] Fields have appropriate types
|
||||
- [ ] Relationships defined if needed
|
||||
- [ ] Migrations exist and applied
|
||||
- [ ] Client generated
|
||||
|
||||
### Hook/Utility Checklist
|
||||
- [ ] File exists at expected path
|
||||
- [ ] Exports function
|
||||
- [ ] Has meaningful implementation (not empty returns)
|
||||
- [ ] Used somewhere in the app
|
||||
- [ ] Return values consumed
|
||||
|
||||
### Wiring Checklist
|
||||
- [ ] Component → API: fetch/axios call exists and uses response
|
||||
- [ ] API → Database: query exists and result returned
|
||||
- [ ] Form → Handler: onSubmit calls API/mutation
|
||||
- [ ] State → Render: state variables appear in JSX
|
||||
|
||||
</verification_checklist>
|
||||
|
||||
<automated_verification_script>
|
||||
|
||||
## Automated Verification Approach
|
||||
|
||||
For the verification subagent, use this pattern:
|
||||
|
||||
```bash
|
||||
# 1. Check existence
|
||||
check_exists() {
|
||||
[ -f "$1" ] && echo "EXISTS: $1" || echo "MISSING: $1"
|
||||
}
|
||||
|
||||
# 2. Check for stub patterns
|
||||
check_stubs() {
|
||||
local file="$1"
|
||||
local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented" "$file" 2>/dev/null || echo 0)
|
||||
[ "$stubs" -gt 0 ] && echo "STUB_PATTERNS: $stubs in $file"
|
||||
}
|
||||
|
||||
# 3. Check wiring (component calls API)
|
||||
check_wiring() {
|
||||
local component="$1"
|
||||
local api_path="$2"
|
||||
grep -q "$api_path" "$component" && echo "WIRED: $component → $api_path" || echo "NOT_WIRED: $component → $api_path"
|
||||
}
|
||||
|
||||
# 4. Check substantive (more than N lines, has expected patterns)
|
||||
check_substantive() {
|
||||
local file="$1"
|
||||
local min_lines="$2"
|
||||
local pattern="$3"
|
||||
local lines=$(wc -l < "$file" 2>/dev/null || echo 0)
|
||||
local has_pattern=$(grep -c -E "$pattern" "$file" 2>/dev/null || echo 0)
|
||||
[ "$lines" -ge "$min_lines" ] && [ "$has_pattern" -gt 0 ] && echo "SUBSTANTIVE: $file" || echo "THIN: $file ($lines lines, $has_pattern matches)"
|
||||
}
|
||||
```
|
||||
|
||||
Run these checks against each must-have artifact. Aggregate results into VERIFICATION.md.
|
||||
|
||||
</automated_verification_script>
|
||||
|
||||
<human_verification_triggers>
|
||||
|
||||
## When to Require Human Verification
|
||||
|
||||
Some things can't be verified programmatically. Flag these for human testing:
|
||||
|
||||
**Always human:**
|
||||
- Visual appearance (does it look right?)
|
||||
- User flow completion (can you actually do the thing?)
|
||||
- Real-time behavior (WebSocket, SSE)
|
||||
- External service integration (Stripe, email sending)
|
||||
- Error message clarity (is the message helpful?)
|
||||
- Performance feel (does it feel fast?)
|
||||
|
||||
**Human if uncertain:**
|
||||
- Complex wiring that grep can't trace
|
||||
- Dynamic behavior depending on state
|
||||
- Edge cases and error states
|
||||
- Mobile responsiveness
|
||||
- Accessibility
|
||||
|
||||
**Format for human verification request:**
|
||||
```markdown
|
||||
## Human Verification Required
|
||||
|
||||
### 1. Chat message sending
|
||||
**Test:** Type a message and click Send
|
||||
**Expected:** Message appears in list, input clears
|
||||
**Check:** Does message persist after refresh?
|
||||
|
||||
### 2. Error handling
|
||||
**Test:** Disconnect network, try to send
|
||||
**Expected:** Error message appears, message not lost
|
||||
**Check:** Can retry after reconnect?
|
||||
```
|
||||
|
||||
</human_verification_triggers>
|
||||
|
||||
<checkpoint_automation_reference>
|
||||
|
||||
## Pre-Checkpoint Automation
|
||||
|
||||
For automation-first checkpoint patterns, server lifecycle management, CLI installation handling, and error recovery protocols, see:
|
||||
|
||||
**@~/.claude/gsd-core/references/checkpoints.md** → `<automation_reference>` section
|
||||
|
||||
Key principles:
|
||||
- Claude sets up verification environment BEFORE presenting checkpoints
|
||||
- Users never run CLI commands (visit URLs only)
|
||||
- Server lifecycle: start before checkpoint, handle port conflicts, keep running for duration
|
||||
- CLI installation: auto-install where safe, checkpoint for user choice otherwise
|
||||
- Error handling: fix broken environment before checkpoint, never present checkpoint with failed setup
|
||||
|
||||
</checkpoint_automation_reference>
|
||||
85
gsd-core/references/verify-mvp-mode.md
Normal file
85
gsd-core/references/verify-mvp-mode.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Verify-Work — MVP Mode UAT Framing
|
||||
|
||||
> Loaded by `verify-work` workflow and `gsd-verifier` agent only when the phase under verification has `mode: mvp` in ROADMAP.md. Reframes UAT generation from technical checks to user-flow walk-throughs.
|
||||
|
||||
## Core rule
|
||||
|
||||
**Show expected, ask if reality matches** — same philosophy as standard verify-work (from `workflows/verify-work.md`). The MVP-mode change is WHAT gets shown:
|
||||
|
||||
- **Standard verify-work:** "The API endpoint at /users/register returns 201 with the new user's ID." → user confirms.
|
||||
- **MVP verify-work:** "Open the registration page. Fill in 'name', 'email', 'password'. Click Submit. You should see your dashboard with your name in the header." → user confirms.
|
||||
|
||||
The user-flow form mirrors what a real user does: open, fill, click, see. No HTTP verbs, no JSON shapes, no error codes.
|
||||
|
||||
## When this framing applies
|
||||
|
||||
The framing fires when:
|
||||
- The phase under verification has `**Mode:** mvp` in ROADMAP.md (parsed via `gsd-tools query roadmap.get-phase --pick mode`).
|
||||
- AND the phase has a user-story-formatted goal (set by `/gsd mvp-phase` per Phase 2): "As a [user role], I want to [capability], so that [outcome]."
|
||||
|
||||
If the phase has `mode: mvp` but the goal is NOT in user-story format, the verifier surfaces this as a discrepancy and asks the user to run `/gsd mvp-phase` to reformat the goal — same pattern as the planner agent under MVP_MODE (per `references/planner-mvp-mode.md`).
|
||||
|
||||
## Generated UAT script structure under MVP mode
|
||||
|
||||
The UAT script generated by `verify-work` under MVP mode has THREE sections, in this exact order:
|
||||
|
||||
### 1. User-flow walk-through (always first, always required)
|
||||
|
||||
Derive ordered steps from the phase's user-story goal:
|
||||
|
||||
1. The first step opens the entry point ("Open the app", "Navigate to /register", "Run `gsd mvp-phase 1`").
|
||||
2. Each subsequent step is one user action: fill, click, type, observe.
|
||||
3. The final step asserts the user-visible outcome from the `[outcome]` clause of the user story.
|
||||
|
||||
Format each step as: "**Step N: [action]** — Expected: [what the user should see]". The user responds with one of:
|
||||
- `yes` / `y` / `next` / empty → step passes
|
||||
- Anything else → step is logged as an issue, and the script halts (do not proceed to step N+1 with a broken N).
|
||||
|
||||
If ALL user-flow steps pass, advance to section 2. If any step fails, the verdict is FAIL — do not run technical checks.
|
||||
|
||||
### 2. Technical checks (only if section 1 passes)
|
||||
|
||||
After the user flow passes, run the technical checks that would normally run in non-MVP mode:
|
||||
- API endpoint schema verification (if the phase shipped APIs)
|
||||
- Error state behavior (4xx, 5xx codes; invalid input handling)
|
||||
- Edge cases (empty data, large data, concurrent requests if applicable)
|
||||
- Cross-browser / cross-runtime checks (if applicable)
|
||||
|
||||
These are the same checks `verify-work` would run without MVP mode — just deferred until the user flow proves the slice actually works for a user.
|
||||
|
||||
### 3. Coverage check (always last, always required)
|
||||
|
||||
Verify that the user-story `[outcome]` clause is observably true in the codebase:
|
||||
- If the outcome is "I can access my dashboard", verify a dashboard route exists and renders for an authenticated user.
|
||||
- If the outcome is "I can bulk-import contacts", verify the import path produces persisted records.
|
||||
|
||||
Coverage is a goal-backward check: "did this phase deliver what its user story promised?" — sourced from the existing `gsd-verifier` agent's goal-backward methodology, narrowed to the user story.
|
||||
|
||||
## Anti-patterns to reject under MVP mode
|
||||
|
||||
- **Lead with technical checks.** "Step 1: GET /api/users/me returns 200." Reject. The user does not see API endpoints. Reorder so a user action comes first.
|
||||
- **Schema-as-feature.** "User has a `name` field on the User model." Reject. The user does not see database fields. Express the same check as a user-visible outcome ("the user's name appears in the dashboard header").
|
||||
- **Skip user flow because the test passed.** The unit test passing in CI is not evidence that the user flow works. The user-flow walk-through is mandatory under MVP mode even when all unit tests are green.
|
||||
|
||||
## Compatibility with existing verify-work philosophy
|
||||
|
||||
The "show expected, ask if reality matches" model is preserved. The user still types `yes` / `next` / empty to advance. The UAT.md state file format is unchanged. Only the WHAT changes — under MVP mode, the "expected" is a user-visible outcome rather than a technical assertion.
|
||||
|
||||
## Output: VERIFICATION.md changes under MVP mode
|
||||
|
||||
The `gsd-verifier` agent produces `VERIFICATION.md`. Under MVP mode, the report adds a top-level "User Flow Coverage" section that maps each step of the user story to evidence in the codebase:
|
||||
|
||||
```markdown
|
||||
## User Flow Coverage
|
||||
|
||||
User story: «As a new user, I want to register and log in, so that I can access my dashboard.»
|
||||
|
||||
| Step | Expected | Evidence | Status |
|
||||
|------|----------|----------|--------|
|
||||
| Register | Form at /register accepts name/email/password | src/app/register/page.tsx:12 (form component) | ✓ |
|
||||
| Submit | Persists user, redirects to /dashboard | src/api/register/route.ts:34 (db.insert + redirect) | ✓ |
|
||||
| See dashboard | Dashboard page renders, shows user's name | src/app/dashboard/page.tsx:8 (greeting line) | ✓ |
|
||||
| Outcome | "Access my dashboard" — user lands on a populated page | dashboard route + greeting both verified above | ✓ |
|
||||
```
|
||||
|
||||
Standard technical-check sections of VERIFICATION.md remain (API verification, error handling, etc.) but are appended below "User Flow Coverage", not above.
|
||||
111
gsd-core/references/workstream-flag.md
Normal file
111
gsd-core/references/workstream-flag.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Workstream Flag (`--ws`)
|
||||
|
||||
## Overview
|
||||
|
||||
The `--ws <name>` flag scopes GSD operations to a specific workstream, enabling
|
||||
parallel milestone work by multiple Claude Code instances on the same codebase.
|
||||
|
||||
## Resolution Priority
|
||||
|
||||
1. `--ws <name>` flag (explicit, highest priority)
|
||||
2. `GSD_WORKSTREAM` environment variable (per-instance)
|
||||
3. Session-scoped active workstream pointer in temp storage (per runtime session / terminal)
|
||||
4. `.planning/active-workstream` file (legacy shared fallback when no session key exists)
|
||||
5. `null` — flat mode (no workstreams)
|
||||
|
||||
## Why session-scoped pointers exist
|
||||
|
||||
The shared `.planning/active-workstream` file is fundamentally unsafe when multiple
|
||||
Claude/Codex instances are active on the same repo at the same time. One session can
|
||||
silently repoint another session's `STATE.md`, `ROADMAP.md`, and phase paths.
|
||||
|
||||
GSD now prefers a session-scoped pointer keyed by runtime/session identity
|
||||
(`GSD_SESSION_KEY`, `CODEX_THREAD_ID`, `CLAUDE_CODE_SSE_PORT`, terminal session IDs,
|
||||
or the controlling TTY). This keeps concurrent sessions isolated while preserving
|
||||
legacy compatibility for runtimes that do not expose a stable session key.
|
||||
|
||||
## Session Identity Resolution
|
||||
|
||||
When GSD resolves the session-scoped pointer in step 3 above, it uses this order:
|
||||
|
||||
1. Explicit runtime/session env vars such as `GSD_SESSION_KEY`, `CODEX_THREAD_ID`,
|
||||
`CLAUDE_SESSION_ID`, `CLAUDE_CODE_SSE_PORT`, `OPENCODE_SESSION_ID`,
|
||||
`GEMINI_SESSION_ID`, `CURSOR_SESSION_ID`, `WINDSURF_SESSION_ID`,
|
||||
`TERM_SESSION_ID`, `WT_SESSION`, `TMUX_PANE`, and `ZELLIJ_SESSION_NAME`
|
||||
2. `TTY` or `SSH_TTY` if the shell/runtime already exposes the terminal path
|
||||
3. A single best-effort `tty` probe, but only when stdin is interactive
|
||||
|
||||
If none of those produce a stable identity, GSD does not keep probing. It falls
|
||||
back directly to the legacy shared `.planning/active-workstream` file.
|
||||
|
||||
This matters in headless or stripped environments: when stdin is already
|
||||
non-interactive, GSD intentionally skips shelling out to `tty` because that path
|
||||
cannot discover a stable session identity and only adds avoidable failures on the
|
||||
routing hot path.
|
||||
|
||||
## Pointer Lifecycle
|
||||
|
||||
Session-scoped pointers are intentionally lightweight and best-effort:
|
||||
|
||||
- Clearing a workstream for one session removes only that session's pointer file
|
||||
- If that was the last pointer for the repo, GSD also removes the now-empty
|
||||
per-project temp directory
|
||||
- If sibling session pointers still exist, the temp directory is left in place
|
||||
- When a pointer refers to a workstream directory that no longer exists, GSD
|
||||
treats it as stale state: it removes that pointer file and resolves to `null`
|
||||
until the session explicitly sets a new active workstream again
|
||||
|
||||
GSD does not currently run a background garbage collector for historical temp
|
||||
directories. Cleanup is opportunistic at the pointer being cleared or self-healed,
|
||||
and broader temp hygiene is left to OS temp cleanup or future maintenance work.
|
||||
|
||||
## Routing Propagation
|
||||
|
||||
All workflow routing commands include `${GSD_WS}` which:
|
||||
- Expands to `--ws <name>` when a workstream is active
|
||||
- Expands to empty string in flat mode (backward compatible)
|
||||
|
||||
This ensures workstream scope chains automatically through the workflow:
|
||||
`new-milestone → discuss-phase → plan-phase → execute-phase → transition`
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
.planning/
|
||||
├── PROJECT.md # Shared
|
||||
├── config.json # Shared
|
||||
├── milestones/ # Shared
|
||||
├── codebase/ # Shared
|
||||
├── active-workstream # Legacy shared fallback only
|
||||
└── workstreams/
|
||||
├── feature-a/ # Workstream A
|
||||
│ ├── STATE.md
|
||||
│ ├── ROADMAP.md
|
||||
│ ├── REQUIREMENTS.md
|
||||
│ └── phases/
|
||||
└── feature-b/ # Workstream B
|
||||
├── STATE.md
|
||||
├── ROADMAP.md
|
||||
├── REQUIREMENTS.md
|
||||
└── phases/
|
||||
```
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
# All gsd-tools query commands accept --ws
|
||||
gsd-tools query state.json --ws feature-a
|
||||
gsd-tools query find-phase 3 --ws feature-b
|
||||
|
||||
# Session-local switching without --ws on every command
|
||||
GSD_SESSION_KEY=my-terminal-a gsd-tools query workstream.set feature-a
|
||||
GSD_SESSION_KEY=my-terminal-a gsd-tools query state.json
|
||||
GSD_SESSION_KEY=my-terminal-b gsd-tools query workstream.set feature-b
|
||||
GSD_SESSION_KEY=my-terminal-b gsd-tools query state.json
|
||||
|
||||
# Workstream CRUD
|
||||
gsd-tools query workstream.create <name>
|
||||
gsd-tools query workstream.list
|
||||
gsd-tools query workstream.status <name>
|
||||
gsd-tools query workstream.complete <name>
|
||||
```
|
||||
38
gsd-core/references/worktree-branch-check.md
Normal file
38
gsd-core/references/worktree-branch-check.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Worktree branch check (spawn-time guard)
|
||||
|
||||
Canonical, fail-closed, **verify-only** guard embedded into every worktree sub-agent
|
||||
prompt at dispatch. This is the single source of truth for the `worktree_branch_check`
|
||||
block — do not inline a copy elsewhere. History of coordinated edits: #2924, #2015, #3174, #48.
|
||||
|
||||
**Contract for orchestrators:** before dispatch, capture `EXPECTED_BASE=$(git rev-parse HEAD)`,
|
||||
then embed the block below into the sub-agent prompt verbatim, substituting `{EXPECTED_BASE}`
|
||||
with that captured SHA. The sub-agent only *verifies* and fails closed; the orchestrator
|
||||
(the worktree lifecycle owner) performs any base recovery — the sub-agent never rewrites a
|
||||
worktree it did not create (#48).
|
||||
|
||||
<worktree_branch_check>
|
||||
FIRST ACTION: HEAD assertion MUST run before anything else, and this block is
|
||||
VERIFY-ONLY. Worktrees spawned by Claude Code's `isolation="worktree"` use the
|
||||
`worktree-agent-<id>` namespace. The orchestrator owns this worktree's lifecycle;
|
||||
a sub-agent MUST NOT hold state-correction primitives (hard-reset, update-ref,
|
||||
force-move, index-discard) on a worktree it did not create (#48, #2924). If ANY
|
||||
assertion below fails, HALT immediately — print the FATAL line, `exit 42`, and let
|
||||
the orchestrator (the lifecycle owner) decide recovery. Do NOT self-recover, do NOT
|
||||
commit.
|
||||
```bash
|
||||
HEAD_REF=$(git symbolic-ref --quiet HEAD || echo "DETACHED")
|
||||
ACTUAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
if [ "$HEAD_REF" = "DETACHED" ] || echo "$ACTUAL_BRANCH" | grep -Eq '^(main|master|develop|trunk|release/.*)$'; then
|
||||
echo "FATAL: worktree HEAD on '$ACTUAL_BRANCH' (expected worktree-agent-*); refusing to commit or self-recover via 'git update-ref' (#2924)." >&2
|
||||
exit 42
|
||||
fi
|
||||
if ! echo "$ACTUAL_BRANCH" | grep -Eq '^worktree-agent-[A-Za-z0-9._/-]+$'; then
|
||||
echo "FATAL: worktree HEAD '$ACTUAL_BRANCH' is not in the worktree-agent-* namespace; refusing to commit (#2924)." >&2
|
||||
exit 42
|
||||
fi
|
||||
if [ "$(git rev-parse HEAD)" != "{EXPECTED_BASE}" ]; then
|
||||
echo "FATAL: worktree base mismatch — HEAD is $(git rev-parse HEAD), expected {EXPECTED_BASE}. Orchestrator owns recovery; sub-agent refuses to rewrite the worktree (#48)." >&2
|
||||
exit 42
|
||||
fi
|
||||
```
|
||||
</worktree_branch_check>
|
||||
67
gsd-core/references/worktree-path-safety.md
Normal file
67
gsd-core/references/worktree-path-safety.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Worktree Path Safety
|
||||
|
||||
Guards for executor agents running inside Claude Code worktrees. Three checks
|
||||
must run before any staging, Edit, or Write operation in worktree mode.
|
||||
|
||||
---
|
||||
|
||||
## Worktree branch check (run once at spawn-time)
|
||||
|
||||
The spawn-time HEAD/base guard now lives in the canonical fragment
|
||||
`gsd-core/references/worktree-branch-check.md`, which the orchestrator embeds directly
|
||||
into your prompt at dispatch. Run that block FIRST, before any reset/checkout or staging.
|
||||
If your prompt contains a `<worktree_branch_check>` embed instruction rather than the block itself, complete that read-and-embed step before any reset/checkout or staging.
|
||||
|
||||
---
|
||||
|
||||
## cwd-drift sentinel — step 0a (#3097)
|
||||
|
||||
A prior Bash call may have `cd`'d out of the worktree into the main repo. When
|
||||
that happens `[ -f .git ]` is false (main repo's `.git` is a directory), silently
|
||||
skipping all worktree guards. The sentinel captures the spawn-time toplevel and
|
||||
detects drift before every commit.
|
||||
|
||||
```bash
|
||||
if [ -f .git ]; then # we are in a worktree
|
||||
WT_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
|
||||
case "$WT_GIT_DIR" in
|
||||
*.git/worktrees/*)
|
||||
SENTINEL="$WT_GIT_DIR/gsd-spawn-toplevel"
|
||||
[ ! -f "$SENTINEL" ] && git rev-parse --show-toplevel > "$SENTINEL" 2>/dev/null
|
||||
EXPECTED_TL=$(cat "$SENTINEL" 2>/dev/null)
|
||||
ACTUAL_TL=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
if [ -n "$EXPECTED_TL" ] && [ "$ACTUAL_TL" != "$EXPECTED_TL" ]; then
|
||||
echo "FATAL: cwd drifted from spawn-time worktree root (#3097)" >&2
|
||||
echo " Spawn-time: $EXPECTED_TL" >&2
|
||||
echo " Current: $ACTUAL_TL" >&2
|
||||
echo "RECOVERY: cd \"$EXPECTED_TL\" before staging, then re-run this commit." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Absolute-path guard — step 0b (#3099)
|
||||
|
||||
Edit/Write calls using absolute paths constructed from the **orchestrator's** `pwd`
|
||||
(main repo root) will resolve to the main repo, not the worktree. Writes land in
|
||||
the wrong directory; `git commit` from the worktree sees a clean tree and the work
|
||||
is silently lost.
|
||||
|
||||
Before any Edit or Write using an absolute path:
|
||||
|
||||
```bash
|
||||
WT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
# Fail fast if ABS_PATH resolves outside the worktree
|
||||
if [[ "$ABS_PATH" != "$WT_ROOT"* ]]; then
|
||||
echo "WARNING: $ABS_PATH is outside the worktree ($WT_ROOT)" >&2
|
||||
echo "Use a relative path or recompute the absolute path from WT_ROOT." >&2
|
||||
fi
|
||||
```
|
||||
|
||||
**Prefer relative paths** for all Edit/Write operations. When an absolute path is
|
||||
unavoidable, always derive it from `git rev-parse --show-toplevel` run inside the
|
||||
worktree — never from `pwd` captured in the orchestrator context.
|
||||
246
gsd-core/templates/AI-SPEC.md
Normal file
246
gsd-core/templates/AI-SPEC.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# AI-SPEC — Phase {N}: {phase_name}
|
||||
|
||||
> AI design contract generated by `/gsd:ai-integration-phase`. Consumed by `gsd-planner` and `gsd-eval-auditor`.
|
||||
> Locks framework selection, implementation guidance, and evaluation strategy before planning begins.
|
||||
|
||||
---
|
||||
|
||||
## 1. System Classification
|
||||
|
||||
**System Type:** <!-- RAG | Multi-Agent | Conversational | Extraction | Autonomous Agent | Content Generation | Code Automation | Hybrid -->
|
||||
|
||||
**Description:**
|
||||
<!-- One-paragraph description of what this AI system does, who uses it, and what "good" looks like -->
|
||||
|
||||
**Critical Failure Modes:**
|
||||
<!-- The 3-5 behaviors that absolutely cannot go wrong in this system -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
---
|
||||
|
||||
## 1b. Domain Context
|
||||
|
||||
> Researched by `gsd-domain-researcher`. Grounds the evaluation strategy in domain expert knowledge.
|
||||
|
||||
**Industry Vertical:** <!-- healthcare | legal | finance | customer service | education | developer tooling | e-commerce | etc. -->
|
||||
|
||||
**User Population:** <!-- who uses this system and in what context -->
|
||||
|
||||
**Stakes Level:** <!-- Low | Medium | High | Critical -->
|
||||
|
||||
**Output Consequence:** <!-- what happens downstream when the AI output is acted on -->
|
||||
|
||||
### What Domain Experts Evaluate Against
|
||||
|
||||
<!-- Domain-specific rubric ingredients — in practitioner language, not AI jargon -->
|
||||
<!-- Format: Dimension / Good (expert accepts) / Bad (expert flags) / Stakes / Source -->
|
||||
|
||||
### Known Failure Modes in This Domain
|
||||
|
||||
<!-- Domain-specific failure modes from research — not generic hallucination, but how it manifests here -->
|
||||
|
||||
### Regulatory / Compliance Context
|
||||
|
||||
<!-- Relevant regulations or constraints — or "None identified" if genuinely none apply -->
|
||||
|
||||
### Domain Expert Roles for Evaluation
|
||||
|
||||
| Role | Responsibility |
|
||||
|------|---------------|
|
||||
| <!-- e.g., Senior practitioner --> | <!-- Dataset labeling / rubric calibration / production sampling --> |
|
||||
|
||||
---
|
||||
|
||||
## 2. Framework Decision
|
||||
|
||||
**Selected Framework:** <!-- e.g., LlamaIndex v0.10.x -->
|
||||
|
||||
**Version:** <!-- Pin the version -->
|
||||
|
||||
**Rationale:**
|
||||
<!-- Why this framework fits this system type, team context, and production requirements -->
|
||||
|
||||
**Alternatives Considered:**
|
||||
|
||||
| Framework | Ruled Out Because |
|
||||
|-----------|------------------|
|
||||
| | |
|
||||
|
||||
**Vendor Lock-In Accepted:** <!-- Yes / No / Partial — document the trade-off consciously -->
|
||||
|
||||
---
|
||||
|
||||
## 3. Framework Quick Reference
|
||||
|
||||
> Fetched from official docs by `gsd-ai-researcher`. Distilled for this specific use case.
|
||||
|
||||
### Installation
|
||||
```bash
|
||||
# Install command(s)
|
||||
```
|
||||
|
||||
### Core Imports
|
||||
```python
|
||||
# Key imports for this use case
|
||||
```
|
||||
|
||||
### Entry Point Pattern
|
||||
```python
|
||||
# Minimal working example for this system type
|
||||
```
|
||||
|
||||
### Key Abstractions
|
||||
<!-- Framework-specific concepts the developer must understand before coding -->
|
||||
| Concept | What It Is | When You Use It |
|
||||
|---------|-----------|-----------------|
|
||||
| | | |
|
||||
|
||||
### Common Pitfalls
|
||||
<!-- Gotchas specific to this framework and system type — from docs, issues, and community reports -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Recommended Project Structure
|
||||
```
|
||||
project/
|
||||
├── # Framework-specific folder layout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Implementation Guidance
|
||||
|
||||
**Model Configuration:**
|
||||
<!-- Which model(s), temperature, max tokens, and other key parameters -->
|
||||
|
||||
**Core Pattern:**
|
||||
<!-- The primary implementation pattern for this system type in this framework -->
|
||||
|
||||
**Tool Use:**
|
||||
<!-- Tools/integrations needed and how to configure them -->
|
||||
|
||||
**State Management:**
|
||||
<!-- How state is persisted, retrieved, and updated -->
|
||||
|
||||
**Context Window Strategy:**
|
||||
<!-- How to manage context limits for this system type -->
|
||||
|
||||
---
|
||||
|
||||
## 4b. AI Systems Best Practices
|
||||
|
||||
> Written by `gsd-ai-researcher`. Cross-cutting patterns every developer building AI systems needs — independent of framework choice.
|
||||
|
||||
### Structured Outputs with Pydantic
|
||||
|
||||
<!-- Framework-specific Pydantic integration pattern for this use case -->
|
||||
<!-- Include: output model definition, how the framework uses it, retry logic on validation failure -->
|
||||
|
||||
```python
|
||||
# Pydantic output model for this system type
|
||||
```
|
||||
|
||||
### Async-First Design
|
||||
|
||||
<!-- How async is handled in this framework, the one common mistake, and when to stream vs. await -->
|
||||
|
||||
### Prompt Engineering Discipline
|
||||
|
||||
<!-- System vs. user prompt separation, few-shot guidance, token budget strategy -->
|
||||
|
||||
### Context Window Management
|
||||
|
||||
<!-- Strategy specific to this system type: RAG chunking / conversation summarisation / agent compaction -->
|
||||
|
||||
### Cost and Latency Budget
|
||||
|
||||
<!-- Per-call cost estimate, caching strategy, sub-task model routing -->
|
||||
|
||||
---
|
||||
|
||||
## 5. Evaluation Strategy
|
||||
|
||||
### Dimensions
|
||||
|
||||
| Dimension | Rubric (Pass/Fail or 1-5) | Measurement Approach | Priority |
|
||||
|-----------|--------------------------|---------------------|----------|
|
||||
| | | Code / LLM Judge / Human | Critical / High / Medium |
|
||||
|
||||
### Eval Tooling
|
||||
|
||||
**Primary Tool:** <!-- e.g., RAGAS + Langfuse -->
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Install and configure
|
||||
```
|
||||
|
||||
**CI/CD Integration:**
|
||||
```bash
|
||||
# Command to run evals in CI/CD pipeline
|
||||
```
|
||||
|
||||
### Reference Dataset
|
||||
|
||||
**Size:** <!-- e.g., 20 examples to start -->
|
||||
|
||||
**Composition:**
|
||||
<!-- What scenario types the dataset covers: critical paths, edge cases, failure modes -->
|
||||
|
||||
**Labeling:**
|
||||
<!-- Who labels examples and how (domain expert, LLM judge with calibration, etc.) -->
|
||||
|
||||
---
|
||||
|
||||
## 6. Guardrails
|
||||
|
||||
### Online (Real-Time)
|
||||
|
||||
| Guardrail | Trigger | Intervention |
|
||||
|-----------|---------|--------------|
|
||||
| | | Block / Escalate / Flag |
|
||||
|
||||
### Offline (Flywheel)
|
||||
|
||||
| Metric | Sampling Strategy | Action on Degradation |
|
||||
|--------|------------------|----------------------|
|
||||
| | | |
|
||||
|
||||
---
|
||||
|
||||
## 7. Production Monitoring
|
||||
|
||||
**Tracing Tool:** <!-- e.g., Langfuse self-hosted -->
|
||||
|
||||
**Key Metrics to Track:**
|
||||
<!-- 3-5 metrics that will be monitored in production -->
|
||||
|
||||
**Alert Thresholds:**
|
||||
<!-- When to page/alert -->
|
||||
|
||||
**Smart Sampling Strategy:**
|
||||
<!-- How to select interactions for human review — signal-based filters -->
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] System type classified
|
||||
- [ ] Critical failure modes identified (≥ 3)
|
||||
- [ ] Domain context researched (Section 1b: vertical, stakes, expert criteria, failure modes)
|
||||
- [ ] Regulatory/compliance context identified or explicitly noted as none
|
||||
- [ ] Domain expert roles defined for evaluation involvement
|
||||
- [ ] Framework selected with rationale documented
|
||||
- [ ] Alternatives considered and ruled out
|
||||
- [ ] Framework quick reference written (install, imports, pattern, pitfalls)
|
||||
- [ ] AI systems best practices written (Section 4b: Pydantic, async, prompt discipline, context)
|
||||
- [ ] Evaluation dimensions grounded in domain rubric ingredients
|
||||
- [ ] Each eval dimension has a concrete rubric (Good/Bad in domain language)
|
||||
- [ ] Eval tooling selected — Arize Phoenix default confirmed or override noted
|
||||
- [ ] Reference dataset spec written (size ≥ 10, composition + labeling defined)
|
||||
- [ ] CI/CD eval integration specified
|
||||
- [ ] Online guardrails defined
|
||||
- [ ] Production monitoring configured (tracing tool + sampling strategy)
|
||||
169
gsd-core/templates/DEBUG.md
Normal file
169
gsd-core/templates/DEBUG.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Debug Template
|
||||
|
||||
Template for `.planning/debug/[slug].md` — active debug session tracking.
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
---
|
||||
status: gathering | investigating | fixing | verifying | awaiting_human_verify | resolved
|
||||
trigger: "[verbatim user input]"
|
||||
created: [ISO timestamp]
|
||||
updated: [ISO timestamp]
|
||||
---
|
||||
|
||||
## Current Focus
|
||||
<!-- OVERWRITE on each update - always reflects NOW -->
|
||||
|
||||
hypothesis: [current theory being tested]
|
||||
test: [how testing it]
|
||||
expecting: [what result means if true/false]
|
||||
next_action: [immediate next step — be specific, not "continue investigating"]
|
||||
reasoning_checkpoint: null <!-- populated before every fix attempt — see structured_returns -->
|
||||
tdd_checkpoint: null <!-- populated when tdd_mode is active after root cause confirmed -->
|
||||
|
||||
## Symptoms
|
||||
<!-- Written during gathering, then immutable -->
|
||||
|
||||
expected: [what should happen]
|
||||
actual: [what actually happens]
|
||||
errors: [error messages if any]
|
||||
reproduction: [how to trigger]
|
||||
started: [when it broke / always broken]
|
||||
|
||||
## Eliminated
|
||||
<!-- APPEND only - prevents re-investigating after /clear -->
|
||||
|
||||
- hypothesis: [theory that was wrong]
|
||||
evidence: [what disproved it]
|
||||
timestamp: [when eliminated]
|
||||
|
||||
## Evidence
|
||||
<!-- APPEND only - facts discovered during investigation -->
|
||||
|
||||
- timestamp: [when found]
|
||||
checked: [what was examined]
|
||||
found: [what was observed]
|
||||
implication: [what this means]
|
||||
|
||||
## Resolution
|
||||
<!-- OVERWRITE as understanding evolves -->
|
||||
|
||||
root_cause: [empty until found]
|
||||
fix: [empty until applied]
|
||||
verification: [empty until verified]
|
||||
files_changed: []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<section_rules>
|
||||
|
||||
**Frontmatter (status, trigger, timestamps):**
|
||||
- `status`: OVERWRITE - reflects current phase
|
||||
- `trigger`: IMMUTABLE - verbatim user input, never changes
|
||||
- `created`: IMMUTABLE - set once
|
||||
- `updated`: OVERWRITE - update on every change
|
||||
|
||||
**Current Focus:**
|
||||
- OVERWRITE entirely on each update
|
||||
- Always reflects what Claude is doing RIGHT NOW
|
||||
- If Claude reads this after /clear, it knows exactly where to resume
|
||||
- Fields: hypothesis, test, expecting, next_action, reasoning_checkpoint, tdd_checkpoint
|
||||
- `next_action`: must be concrete and actionable — bad: "continue investigating"; good: "Add logging at line 47 of auth.js to observe token value before jwt.verify()"
|
||||
- `reasoning_checkpoint`: OVERWRITE before every fix_and_verify — five-field structured reasoning record (hypothesis, confirming_evidence, falsification_test, fix_rationale, blind_spots)
|
||||
- `tdd_checkpoint`: OVERWRITE during TDD red/green phases — test file, name, status, failure output
|
||||
|
||||
**Symptoms:**
|
||||
- Written during initial gathering phase
|
||||
- IMMUTABLE after gathering complete
|
||||
- Reference point for what we're trying to fix
|
||||
- Fields: expected, actual, errors, reproduction, started
|
||||
|
||||
**Eliminated:**
|
||||
- APPEND only - never remove entries
|
||||
- Prevents re-investigating dead ends after context reset
|
||||
- Each entry: hypothesis, evidence that disproved it, timestamp
|
||||
- Critical for efficiency across /clear boundaries
|
||||
|
||||
**Evidence:**
|
||||
- APPEND only - never remove entries
|
||||
- Facts discovered during investigation
|
||||
- Each entry: timestamp, what checked, what found, implication
|
||||
- Builds the case for root cause
|
||||
|
||||
**Resolution:**
|
||||
- OVERWRITE as understanding evolves
|
||||
- May update multiple times as fixes are tried
|
||||
- Final state shows confirmed root cause and verified fix
|
||||
- Fields: root_cause, fix, verification, files_changed
|
||||
|
||||
</section_rules>
|
||||
|
||||
<lifecycle>
|
||||
|
||||
**Creation:** Immediately when /gsd:debug is called
|
||||
- Create file with trigger from user input
|
||||
- Set status to "gathering"
|
||||
- Current Focus: next_action = "gather symptoms"
|
||||
- Symptoms: empty, to be filled
|
||||
|
||||
**During symptom gathering:**
|
||||
- Update Symptoms section as user answers questions
|
||||
- Update Current Focus with each question
|
||||
- When complete: status → "investigating"
|
||||
|
||||
**During investigation:**
|
||||
- OVERWRITE Current Focus with each hypothesis
|
||||
- APPEND to Evidence with each finding
|
||||
- APPEND to Eliminated when hypothesis disproved
|
||||
- Update timestamp in frontmatter
|
||||
|
||||
**During fixing:**
|
||||
- status → "fixing"
|
||||
- Update Resolution.root_cause when confirmed
|
||||
- Update Resolution.fix when applied
|
||||
- Update Resolution.files_changed
|
||||
|
||||
**During verification:**
|
||||
- status → "verifying"
|
||||
- Update Resolution.verification with results
|
||||
- If verification fails: status → "investigating", try again
|
||||
|
||||
**After self-verification passes:**
|
||||
- status -> "awaiting_human_verify"
|
||||
- Request explicit user confirmation in a checkpoint
|
||||
- Do NOT move file to resolved yet
|
||||
|
||||
**On resolution:**
|
||||
- status → "resolved"
|
||||
- Move file to .planning/debug/resolved/ (only after user confirms fix)
|
||||
|
||||
</lifecycle>
|
||||
|
||||
<resume_behavior>
|
||||
|
||||
When Claude reads this file after /clear:
|
||||
|
||||
1. Parse frontmatter → know status
|
||||
2. Read Current Focus → know exactly what was happening
|
||||
3. Read Eliminated → know what NOT to retry
|
||||
4. Read Evidence → know what's been learned
|
||||
5. Continue from next_action
|
||||
|
||||
The file IS the debugging brain. Claude should be able to resume perfectly from any interruption point.
|
||||
|
||||
</resume_behavior>
|
||||
|
||||
<size_constraint>
|
||||
|
||||
Keep debug files focused:
|
||||
- Evidence entries: 1-2 lines each, just the facts
|
||||
- Eliminated: brief - hypothesis + why it failed
|
||||
- No narrative prose - structured data only
|
||||
|
||||
If evidence grows very large (10+ entries), consider whether you're going in circles. Check Eliminated to ensure you're not re-treading.
|
||||
|
||||
</size_constraint>
|
||||
77
gsd-core/templates/README.md
Normal file
77
gsd-core/templates/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# GSD Canonical Artifact Registry
|
||||
|
||||
This directory contains the template files for every artifact that GSD workflows officially produce. The table below is the authoritative index: **if a `.planning/` root file is not listed here, `gsd-health` will flag it as W019** (unrecognized artifact).
|
||||
|
||||
Agents should query this file before treating a `.planning/` file as authoritative. If the file name does not appear below, it is not a canonical GSD artifact.
|
||||
|
||||
---
|
||||
|
||||
## `.planning/` Root Artifacts
|
||||
|
||||
These files live directly at `.planning/` — not inside phase subdirectories.
|
||||
|
||||
| File | Template | Produced by | Purpose |
|
||||
|------|----------|-------------|---------|
|
||||
| `PROJECT.md` | `project.md` | `/gsd:new-project` | Project identity, goals, requirements summary |
|
||||
| `ROADMAP.md` | `roadmap.md` | `/gsd:new-milestone`, `/gsd:new-project` | Phase plan with milestones and progress tracking |
|
||||
| `STATE.md` | `state.md` | `/gsd:new-project`, `/gsd:health --repair` | Current session state, active phase, last activity |
|
||||
| `REQUIREMENTS.md` | `requirements.md` | `/gsd:new-milestone` | Functional requirements with traceability |
|
||||
| `MILESTONES.md` | `milestone.md` | `/gsd:complete-milestone` | Log of completed milestones with accomplishments |
|
||||
| `BACKLOG.md` | *(inline)* | `/gsd-add-backlog` | Pending ideas and deferred work |
|
||||
| `LEARNINGS.md` | *(inline)* | `/gsd:extract-learnings`, `/gsd:execute-phase` | Phase retrospective learnings for future plans |
|
||||
| `THREADS.md` | *(inline)* | `/gsd:thread` | Persistent discussion threads |
|
||||
| `config.json` | `config.json` | `/gsd:new-project`, `/gsd:health --repair` | Project-specific GSD configuration |
|
||||
| `CLAUDE.md` | `claude-md.md` | `/gsd-profile` | Auto-assembled Claude Code context file |
|
||||
| `RETROSPECTIVE.md` | *(inline)* | `/gsd:complete-milestone` | Living milestone retrospective updated at each milestone close |
|
||||
|
||||
### Version-stamped artifacts (pattern: `vX.Y-*.md`)
|
||||
|
||||
| Pattern | Produced by | Purpose |
|
||||
|---------|-------------|---------|
|
||||
| `vX.Y-MILESTONE-AUDIT.md` | `/gsd:audit-milestone` | Milestone audit report before archiving |
|
||||
|
||||
These files are archived to `.planning/milestones/` by `/gsd:complete-milestone`. Finding them at the `.planning/` root after completion indicates the archive step was skipped.
|
||||
|
||||
---
|
||||
|
||||
## Phase Subdirectory Artifacts (`.planning/phases/NN-name/`)
|
||||
|
||||
These files live inside a phase directory. They are NOT checked by W019 (which only inspects the `.planning/` root).
|
||||
|
||||
| File Pattern | Template | Produced by | Purpose |
|
||||
|-------------|----------|-------------|---------|
|
||||
| `NN-MM-PLAN.md` | `phase-prompt.md` | `/gsd:plan-phase` | Executable implementation plan |
|
||||
| `NN-MM-SUMMARY.md` | `summary.md` | `/gsd:execute-phase` | Post-execution summary with learnings |
|
||||
| `NN-CONTEXT.md` | `context.md` | `/gsd:discuss-phase` | Scoped discussion decisions for the phase |
|
||||
| `NN-RESEARCH.md` | `research.md` | `/gsd:plan-phase`, `/gsd:plan-phase --research-phase <N>` | Technical research for the phase |
|
||||
| `NN-VALIDATION.md` | `VALIDATION.md` | `/gsd:plan-phase` (Nyquist) | Validation architecture (Nyquist method) |
|
||||
| `NN-UAT.md` | `UAT.md` | `/gsd:validate-phase` | User acceptance test results |
|
||||
| `NN-PATTERNS.md` | *(inline)* | `/gsd:plan-phase` (pattern mapper) | Analog file mapping for the phase |
|
||||
| `NN-UI-SPEC.md` | `UI-SPEC.md` | `/gsd:ui-phase` | UI design contract |
|
||||
| `NN-SECURITY.md` | `SECURITY.md` | `/gsd:secure-phase` | Security threat model |
|
||||
| `NN-AI-SPEC.md` | `AI-SPEC.md` | `/gsd:ai-integration-phase` | AI integration spec with eval strategy |
|
||||
| `NN-DEBUG.md` | `DEBUG.md` | `/gsd:debug` | Debug session log |
|
||||
| `NN-REVIEWS.md` | *(inline)* | `/gsd:review` | Cross-AI review feedback |
|
||||
|
||||
---
|
||||
|
||||
## Milestone Archive (`.planning/milestones/`)
|
||||
|
||||
Files archived by `/gsd:complete-milestone`. These are never checked by W019.
|
||||
|
||||
| File Pattern | Source |
|
||||
|-------------|--------|
|
||||
| `vX.Y-ROADMAP.md` | Snapshot of ROADMAP.md at milestone close |
|
||||
| `vX.Y-REQUIREMENTS.md` | Snapshot of REQUIREMENTS.md at milestone close |
|
||||
| `vX.Y-MILESTONE-AUDIT.md` | Moved from `.planning/` root |
|
||||
| `vX.Y-phases/` | Archived phase directories (if `--archive-phases` used) |
|
||||
|
||||
---
|
||||
|
||||
## Adding a New Canonical Artifact
|
||||
|
||||
When a new workflow produces a `.planning/` root file:
|
||||
|
||||
1. Add the file name to `CANONICAL_EXACT` in `gsd-core/bin/lib/artifacts.cjs`
|
||||
2. Add a row to the **`.planning/` Root Artifacts** table above
|
||||
3. Add the template to `gsd-core/templates/` if one exists
|
||||
61
gsd-core/templates/SECURITY.md
Normal file
61
gsd-core/templates/SECURITY.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
phase: {N}
|
||||
slug: {phase-slug}
|
||||
status: draft
|
||||
threats_open: 0
|
||||
asvs_level: 1
|
||||
created: {date}
|
||||
---
|
||||
|
||||
# Phase {N} — Security
|
||||
|
||||
> Per-phase security contract: threat register, accepted risks, and audit trail.
|
||||
|
||||
---
|
||||
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description | Data Crossing |
|
||||
|----------|-------------|---------------|
|
||||
| {boundary} | {description} | {data type / sensitivity} |
|
||||
|
||||
---
|
||||
|
||||
## Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Disposition | Mitigation | Status |
|
||||
|-----------|----------|-----------|-------------|------------|--------|
|
||||
| T-{N}-01 | {STRIDE category} | {component} | {mitigate / accept / transfer} | {control or reference} | open |
|
||||
|
||||
*Status: open · closed*
|
||||
*Disposition: mitigate (implementation required) · accept (documented risk) · transfer (third-party)*
|
||||
|
||||
---
|
||||
|
||||
## Accepted Risks Log
|
||||
|
||||
| Risk ID | Threat Ref | Rationale | Accepted By | Date |
|
||||
|---------|------------|-----------|-------------|------|
|
||||
|
||||
*Accepted risks do not resurface in future audit runs.*
|
||||
|
||||
*If none: "No accepted risks."*
|
||||
|
||||
---
|
||||
|
||||
## Security Audit Trail
|
||||
|
||||
| Audit Date | Threats Total | Closed | Open | Run By |
|
||||
|------------|---------------|--------|------|--------|
|
||||
| {YYYY-MM-DD} | {N} | {N} | {N} | {name / agent} |
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off
|
||||
|
||||
- [ ] All threats have a disposition (mitigate / accept / transfer)
|
||||
- [ ] Accepted risks documented in Accepted Risks Log
|
||||
- [ ] `threats_open: 0` confirmed
|
||||
- [ ] `status: verified` set in frontmatter
|
||||
|
||||
**Approval:** {pending / verified YYYY-MM-DD}
|
||||
265
gsd-core/templates/UAT.md
Normal file
265
gsd-core/templates/UAT.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# UAT Template
|
||||
|
||||
Template for `.planning/phases/XX-name/{phase_num}-UAT.md` — persistent UAT session tracking.
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
---
|
||||
status: testing | partial | complete | diagnosed
|
||||
phase: XX-name
|
||||
source: [list of SUMMARY.md files tested]
|
||||
started: [ISO timestamp]
|
||||
updated: [ISO timestamp]
|
||||
---
|
||||
|
||||
## Current Test
|
||||
<!-- OVERWRITE each test - shows where we are -->
|
||||
|
||||
number: [N]
|
||||
name: [test name]
|
||||
expected: |
|
||||
[what user should observe]
|
||||
awaiting: user response
|
||||
|
||||
## Tests
|
||||
|
||||
### 1. [Test Name]
|
||||
expected: [observable behavior - what user should see]
|
||||
result: [pending]
|
||||
|
||||
### 2. [Test Name]
|
||||
expected: [observable behavior]
|
||||
result: pass
|
||||
|
||||
### 3. [Test Name]
|
||||
expected: [observable behavior]
|
||||
result: issue
|
||||
reported: "[verbatim user response]"
|
||||
severity: major
|
||||
|
||||
### 4. [Test Name]
|
||||
expected: [observable behavior]
|
||||
result: skipped
|
||||
reason: [why skipped]
|
||||
|
||||
### 5. [Test Name]
|
||||
expected: [observable behavior]
|
||||
result: blocked
|
||||
blocked_by: server | physical-device | release-build | third-party | prior-phase
|
||||
reason: [why blocked]
|
||||
|
||||
...
|
||||
|
||||
## Summary
|
||||
|
||||
total: [N]
|
||||
passed: [N]
|
||||
issues: [N]
|
||||
pending: [N]
|
||||
skipped: [N]
|
||||
blocked: [N]
|
||||
|
||||
## Gaps
|
||||
|
||||
<!-- YAML format for plan-phase --gaps consumption -->
|
||||
- truth: "[expected behavior from test]"
|
||||
status: failed
|
||||
reason: "User reported: [verbatim response]"
|
||||
severity: blocker | major | minor | cosmetic
|
||||
test: [N]
|
||||
root_cause: "" # Filled by diagnosis
|
||||
artifacts: [] # Filled by diagnosis
|
||||
missing: [] # Filled by diagnosis
|
||||
debug_session: "" # Filled by diagnosis
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<section_rules>
|
||||
|
||||
**Frontmatter:**
|
||||
- `status`: OVERWRITE - "testing", "partial", or "complete"
|
||||
- `phase`: IMMUTABLE - set on creation
|
||||
- `source`: IMMUTABLE - SUMMARY files being tested
|
||||
- `started`: IMMUTABLE - set on creation
|
||||
- `updated`: OVERWRITE - update on every change
|
||||
|
||||
**Current Test:**
|
||||
- OVERWRITE entirely on each test transition
|
||||
- Shows which test is active and what's awaited
|
||||
- On completion: "[testing complete]"
|
||||
|
||||
**Tests:**
|
||||
- Each test: OVERWRITE result field when user responds
|
||||
- `result` values: [pending], pass, issue, skipped, blocked
|
||||
- If issue: add `reported` (verbatim) and `severity` (inferred)
|
||||
- If skipped: add `reason` if provided
|
||||
- If blocked: add `blocked_by` (tag) and `reason` (if provided)
|
||||
|
||||
**Summary:**
|
||||
- OVERWRITE counts after each response
|
||||
- Tracks: total, passed, issues, pending, skipped
|
||||
|
||||
**Gaps:**
|
||||
- APPEND only when issue found (YAML format)
|
||||
- After diagnosis: fill `root_cause`, `artifacts`, `missing`, `debug_session`
|
||||
- This section feeds directly into /gsd:plan-phase --gaps
|
||||
|
||||
</section_rules>
|
||||
|
||||
<diagnosis_lifecycle>
|
||||
|
||||
**After testing complete (status: complete), if gaps exist:**
|
||||
|
||||
1. User runs diagnosis (from verify-work offer or manually)
|
||||
2. diagnose-issues workflow spawns parallel debug agents
|
||||
3. Each agent investigates one gap, returns root cause
|
||||
4. UAT.md Gaps section updated with diagnosis:
|
||||
- Each gap gets `root_cause`, `artifacts`, `missing`, `debug_session` filled
|
||||
5. status → "diagnosed"
|
||||
6. Ready for /gsd:plan-phase --gaps with root causes
|
||||
|
||||
**After diagnosis:**
|
||||
```yaml
|
||||
## Gaps
|
||||
|
||||
- truth: "Comment appears immediately after submission"
|
||||
status: failed
|
||||
reason: "User reported: works but doesn't show until I refresh the page"
|
||||
severity: major
|
||||
test: 2
|
||||
root_cause: "useEffect in CommentList.tsx missing commentCount dependency"
|
||||
artifacts:
|
||||
- path: "src/components/CommentList.tsx"
|
||||
issue: "useEffect missing dependency"
|
||||
missing:
|
||||
- "Add commentCount to useEffect dependency array"
|
||||
debug_session: ".planning/debug/comment-not-refreshing.md"
|
||||
```
|
||||
|
||||
</diagnosis_lifecycle>
|
||||
|
||||
<lifecycle>
|
||||
|
||||
**Creation:** When /gsd:verify-work starts new session
|
||||
- Extract tests from SUMMARY.md files
|
||||
- Set status to "testing"
|
||||
- Current Test points to test 1
|
||||
- All tests have result: [pending]
|
||||
|
||||
**During testing:**
|
||||
- Present test from Current Test section
|
||||
- User responds with pass confirmation or issue description
|
||||
- Update test result (pass/issue/skipped)
|
||||
- Update Summary counts
|
||||
- If issue: append to Gaps section (YAML format), infer severity
|
||||
- Move Current Test to next pending test
|
||||
|
||||
**On completion:**
|
||||
- status → "complete"
|
||||
- Current Test → "[testing complete]"
|
||||
- Commit file
|
||||
- Present summary with next steps
|
||||
|
||||
**Partial completion:**
|
||||
- status → "partial" (if pending, blocked, or unresolved skipped tests remain)
|
||||
- Current Test → "[testing paused — {N} items outstanding]"
|
||||
- Commit file
|
||||
- Present summary with outstanding items highlighted
|
||||
|
||||
**Resuming partial session:**
|
||||
- `/gsd:verify-work {phase}` picks up from first pending/blocked test
|
||||
- When all items resolved, status advances to "complete"
|
||||
|
||||
**Resume after /clear:**
|
||||
1. Read frontmatter → know phase and status
|
||||
2. Read Current Test → know where we are
|
||||
3. Find first [pending] result → continue from there
|
||||
4. Summary shows progress so far
|
||||
|
||||
</lifecycle>
|
||||
|
||||
<severity_guide>
|
||||
|
||||
Severity is INFERRED from user's natural language, never asked.
|
||||
|
||||
| User describes | Infer |
|
||||
|----------------|-------|
|
||||
| Crash, error, exception, fails completely, unusable | blocker |
|
||||
| Doesn't work, nothing happens, wrong behavior, missing | major |
|
||||
| Works but..., slow, weird, minor, small issue | minor |
|
||||
| Color, font, spacing, alignment, visual, looks off | cosmetic |
|
||||
|
||||
Default: **major** (safe default, user can clarify if wrong)
|
||||
|
||||
</severity_guide>
|
||||
|
||||
<good_example>
|
||||
```markdown
|
||||
---
|
||||
status: diagnosed
|
||||
phase: 04-comments
|
||||
source: 04-01-SUMMARY.md, 04-02-SUMMARY.md
|
||||
started: 2025-01-15T10:30:00Z
|
||||
updated: 2025-01-15T10:45:00Z
|
||||
---
|
||||
|
||||
## Current Test
|
||||
|
||||
[testing complete]
|
||||
|
||||
## Tests
|
||||
|
||||
### 1. View Comments on Post
|
||||
expected: Comments section expands, shows count and comment list
|
||||
result: pass
|
||||
|
||||
### 2. Create Top-Level Comment
|
||||
expected: Submit comment via rich text editor, appears in list with author info
|
||||
result: issue
|
||||
reported: "works but doesn't show until I refresh the page"
|
||||
severity: major
|
||||
|
||||
### 3. Reply to a Comment
|
||||
expected: Click Reply, inline composer appears, submit shows nested reply
|
||||
result: pass
|
||||
|
||||
### 4. Visual Nesting
|
||||
expected: 3+ level thread shows indentation, left borders, caps at reasonable depth
|
||||
result: pass
|
||||
|
||||
### 5. Delete Own Comment
|
||||
expected: Click delete on own comment, removed or shows [deleted] if has replies
|
||||
result: pass
|
||||
|
||||
### 6. Comment Count
|
||||
expected: Post shows accurate count, increments when adding comment
|
||||
result: pass
|
||||
|
||||
## Summary
|
||||
|
||||
total: 6
|
||||
passed: 5
|
||||
issues: 1
|
||||
pending: 0
|
||||
skipped: 0
|
||||
|
||||
## Gaps
|
||||
|
||||
- truth: "Comment appears immediately after submission in list"
|
||||
status: failed
|
||||
reason: "User reported: works but doesn't show until I refresh the page"
|
||||
severity: major
|
||||
test: 2
|
||||
root_cause: "useEffect in CommentList.tsx missing commentCount dependency"
|
||||
artifacts:
|
||||
- path: "src/components/CommentList.tsx"
|
||||
issue: "useEffect missing dependency"
|
||||
missing:
|
||||
- "Add commentCount to useEffect dependency array"
|
||||
debug_session: ".planning/debug/comment-not-refreshing.md"
|
||||
```
|
||||
</good_example>
|
||||
100
gsd-core/templates/UI-SPEC.md
Normal file
100
gsd-core/templates/UI-SPEC.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
phase: {N}
|
||||
slug: {phase-slug}
|
||||
status: draft
|
||||
shadcn_initialized: false
|
||||
preset: none
|
||||
created: {date}
|
||||
---
|
||||
|
||||
# Phase {N} — UI Design Contract
|
||||
|
||||
> Visual and interaction contract for frontend phases. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
|
||||
|
||||
---
|
||||
|
||||
## Design System
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Tool | {shadcn / none} |
|
||||
| Preset | {preset string or "not applicable"} |
|
||||
| Component library | {radix / base-ui / none} |
|
||||
| Icon library | {library} |
|
||||
| Font | {font} |
|
||||
|
||||
---
|
||||
|
||||
## Spacing Scale
|
||||
|
||||
Declared values (must be multiples of 4):
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| xs | 4px | Icon gaps, inline padding |
|
||||
| sm | 8px | Compact element spacing |
|
||||
| md | 16px | Default element spacing |
|
||||
| lg | 24px | Section padding |
|
||||
| xl | 32px | Layout gaps |
|
||||
| 2xl | 48px | Major section breaks |
|
||||
| 3xl | 64px | Page-level spacing |
|
||||
|
||||
Exceptions: {list any, or "none"}
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
| Role | Size | Weight | Line Height |
|
||||
|------|------|--------|-------------|
|
||||
| Body | {px} | {weight} | {ratio} |
|
||||
| Label | {px} | {weight} | {ratio} |
|
||||
| Heading | {px} | {weight} | {ratio} |
|
||||
| Display | {px} | {weight} | {ratio} |
|
||||
|
||||
---
|
||||
|
||||
## Color
|
||||
|
||||
| Role | Value | Usage |
|
||||
|------|-------|-------|
|
||||
| Dominant (60%) | {hex} | Background, surfaces |
|
||||
| Secondary (30%) | {hex} | Cards, sidebar, nav |
|
||||
| Accent (10%) | {hex} | {list specific elements only} |
|
||||
| Destructive | {hex} | Destructive actions only |
|
||||
|
||||
Accent reserved for: {explicit list — never "all interactive elements"}
|
||||
|
||||
---
|
||||
|
||||
## Copywriting Contract
|
||||
|
||||
| Element | Copy |
|
||||
|---------|------|
|
||||
| Primary CTA | {specific verb + noun} |
|
||||
| Empty state heading | {copy} |
|
||||
| Empty state body | {copy + next step} |
|
||||
| Error state | {problem + solution path} |
|
||||
| Destructive confirmation | {action name}: {confirmation copy} |
|
||||
|
||||
---
|
||||
|
||||
## Registry Safety
|
||||
|
||||
| Registry | Blocks Used | Safety Gate |
|
||||
|----------|-------------|-------------|
|
||||
| shadcn official | {list} | not required |
|
||||
| {third-party name} | {list} | shadcn view + diff required |
|
||||
|
||||
---
|
||||
|
||||
## Checker Sign-Off
|
||||
|
||||
- [ ] Dimension 1 Copywriting: PASS
|
||||
- [ ] Dimension 2 Visuals: PASS
|
||||
- [ ] Dimension 3 Color: PASS
|
||||
- [ ] Dimension 4 Typography: PASS
|
||||
- [ ] Dimension 5 Spacing: PASS
|
||||
- [ ] Dimension 6 Registry Safety: PASS
|
||||
|
||||
**Approval:** {pending / approved YYYY-MM-DD}
|
||||
76
gsd-core/templates/VALIDATION.md
Normal file
76
gsd-core/templates/VALIDATION.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
phase: {N}
|
||||
slug: {phase-slug}
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
wave_0_complete: false
|
||||
created: {date}
|
||||
---
|
||||
|
||||
# Phase {N} — Validation Strategy
|
||||
|
||||
> Per-phase validation contract for feedback sampling during execution.
|
||||
|
||||
---
|
||||
|
||||
## Test Infrastructure
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Framework** | {pytest 7.x / jest 29.x / vitest / go test / other} |
|
||||
| **Config file** | {path or "none — Wave 0 installs"} |
|
||||
| **Quick run command** | `{quick command}` |
|
||||
| **Full suite command** | `{full command}` |
|
||||
| **Estimated runtime** | ~{N} seconds |
|
||||
|
||||
---
|
||||
|
||||
## Sampling Rate
|
||||
|
||||
- **After every task commit:** Run `{quick run command}`
|
||||
- **After every plan wave:** Run `{full suite command}`
|
||||
- **Before `/gsd:verify-work`:** Full suite must be green
|
||||
- **Max feedback latency:** {N} seconds
|
||||
|
||||
---
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
|
||||
| {N}-01-01 | 01 | 1 | REQ-{XX} | T-{N}-01 / — | {expected secure behavior or "N/A"} | unit | `{command}` | ✅ / ❌ W0 | ⬜ pending |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
---
|
||||
|
||||
## Wave 0 Requirements
|
||||
|
||||
- [ ] `{tests/test_file.py}` — stubs for REQ-{XX}
|
||||
- [ ] `{tests/conftest.py}` — shared fixtures
|
||||
- [ ] `{framework install}` — if no framework detected
|
||||
|
||||
*If none: "Existing infrastructure covers all phase requirements."*
|
||||
|
||||
---
|
||||
|
||||
## Manual-Only Verifications
|
||||
|
||||
| Behavior | Requirement | Why Manual | Test Instructions |
|
||||
|----------|-------------|------------|-------------------|
|
||||
| {behavior} | REQ-{XX} | {reason} | {steps} |
|
||||
|
||||
*If none: "All phase behaviors have automated verification."*
|
||||
|
||||
---
|
||||
|
||||
## Validation Sign-Off
|
||||
|
||||
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
|
||||
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
|
||||
- [ ] Wave 0 covers all MISSING references
|
||||
- [ ] No watch-mode flags
|
||||
- [ ] Feedback latency < {N}s
|
||||
- [ ] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** {pending / approved YYYY-MM-DD}
|
||||
145
gsd-core/templates/claude-md.md
Normal file
145
gsd-core/templates/claude-md.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# CLAUDE.md Template
|
||||
|
||||
Template for project-root `CLAUDE.md` — auto-generated by `gsd-tools generate-claude-md`.
|
||||
|
||||
Contains 7 marker-bounded sections. Each section is independently updatable.
|
||||
The `generate-claude-md` subcommand manages 6 sections (project, stack, conventions, architecture, skills, workflow enforcement).
|
||||
The profile section is managed exclusively by `generate-claude-profile`.
|
||||
|
||||
---
|
||||
|
||||
## Section Templates
|
||||
|
||||
### Project Section
|
||||
```
|
||||
<!-- GSD:project-start source:PROJECT.md -->
|
||||
## Project
|
||||
|
||||
{{project_content}}
|
||||
<!-- GSD:project-end -->
|
||||
```
|
||||
|
||||
**Fallback text:**
|
||||
```
|
||||
Project not yet initialized. Run /gsd:new-project to set up.
|
||||
```
|
||||
|
||||
### Stack Section
|
||||
```
|
||||
<!-- GSD:stack-start source:STACK.md -->
|
||||
## Technology Stack
|
||||
|
||||
{{stack_content}}
|
||||
<!-- GSD:stack-end -->
|
||||
```
|
||||
|
||||
**Fallback text:**
|
||||
```
|
||||
Technology stack not yet documented. Will populate after codebase mapping or first phase.
|
||||
```
|
||||
|
||||
### Conventions Section
|
||||
```
|
||||
<!-- GSD:conventions-start source:CONVENTIONS.md -->
|
||||
## Conventions
|
||||
|
||||
{{conventions_content}}
|
||||
<!-- GSD:conventions-end -->
|
||||
```
|
||||
|
||||
**Fallback text:**
|
||||
```
|
||||
Conventions not yet established. Will populate as patterns emerge during development.
|
||||
```
|
||||
|
||||
### Architecture Section
|
||||
```
|
||||
<!-- GSD:architecture-start source:ARCHITECTURE.md -->
|
||||
## Architecture
|
||||
|
||||
{{architecture_content}}
|
||||
<!-- GSD:architecture-end -->
|
||||
```
|
||||
|
||||
**Fallback text:**
|
||||
```
|
||||
Architecture not yet mapped. Follow existing patterns found in the codebase.
|
||||
```
|
||||
|
||||
### Skills Section
|
||||
```
|
||||
<!-- GSD:skills-start source:skills/ -->
|
||||
## Project Skills
|
||||
|
||||
| Skill | Description | Path |
|
||||
| -------------- | --------------------- | ------------------------- |
|
||||
| {{skill_name}} | {{skill_description}} | `{{skill_path}}/SKILL.md` |
|
||||
<!-- GSD:skills-end -->
|
||||
```
|
||||
|
||||
**Fallback text:**
|
||||
```
|
||||
No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, or `.github/skills/` with a `SKILL.md` index file.
|
||||
```
|
||||
|
||||
**Discovery behavior:**
|
||||
- Scans `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, `.github/skills/` for subdirectories containing `SKILL.md`
|
||||
- Extracts `name` and `description` from YAML frontmatter (supports multi-line descriptions)
|
||||
- Skips GSD's own installed skills (directories starting with `gsd-`)
|
||||
- Deduplicates by skill name across directories
|
||||
|
||||
### Workflow Enforcement Section
|
||||
```
|
||||
<!-- GSD:workflow-start source:GSD defaults -->
|
||||
## GSD Workflow Enforcement
|
||||
|
||||
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
|
||||
|
||||
Use these entry points:
|
||||
- `/gsd:quick` for small fixes, doc updates, and ad-hoc tasks
|
||||
- `/gsd:debug` for investigation and bug fixing
|
||||
- `/gsd:execute-phase` for planned phase work
|
||||
|
||||
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
|
||||
<!-- GSD:workflow-end -->
|
||||
```
|
||||
|
||||
### Profile Section (Placeholder Only)
|
||||
```
|
||||
<!-- GSD:profile-start -->
|
||||
## Developer Profile
|
||||
|
||||
> Profile not yet configured. Run `/gsd:profile-user` to generate your developer profile.
|
||||
> This section is managed by `generate-claude-profile` — do not edit manually.
|
||||
<!-- GSD:profile-end -->
|
||||
```
|
||||
|
||||
**Note:** This section is NOT managed by `generate-claude-md`. It is managed exclusively
|
||||
by `generate-claude-profile`. The placeholder above is only used when creating a new
|
||||
CLAUDE.md file and no profile section exists yet.
|
||||
|
||||
---
|
||||
|
||||
## Section Ordering
|
||||
|
||||
1. **Project** — Identity and purpose (what this project is)
|
||||
2. **Stack** — Technology choices (what tools are used)
|
||||
3. **Conventions** — Code patterns and rules (how code is written)
|
||||
4. **Architecture** — System structure (how components fit together)
|
||||
5. **Skills** — Discovered project skills with name and description (what domain knowledge is available)
|
||||
6. **Workflow Enforcement** — Default GSD entry points for file-changing work
|
||||
7. **Profile** — Developer behavioral preferences (how to interact)
|
||||
|
||||
## Marker Format
|
||||
|
||||
- Start: `<!-- GSD:{name}-start source:{file} -->`
|
||||
- End: `<!-- GSD:{name}-end -->`
|
||||
- Source attribute enables targeted updates when source files change
|
||||
- Partial match on start marker (without closing `-->`) for detection
|
||||
|
||||
## Fallback Behavior
|
||||
|
||||
When a source file is missing, fallback text provides Claude-actionable guidance:
|
||||
- Guides Claude's behavior in the absence of data
|
||||
- Not placeholder ads or "missing" notices
|
||||
- Each fallback tells Claude what to do, not just what's absent
|
||||
255
gsd-core/templates/codebase/architecture.md
Normal file
255
gsd-core/templates/codebase/architecture.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Architecture Template
|
||||
|
||||
Template for `.planning/codebase/ARCHITECTURE.md` - captures conceptual code organization.
|
||||
|
||||
**Purpose:** Document how the code is organized at a conceptual level. Complements STRUCTURE.md (which shows physical file locations).
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Architecture
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Pattern Overview
|
||||
|
||||
**Overall:** [Pattern name: e.g., "Monolithic CLI", "Serverless API", "Full-stack MVC"]
|
||||
|
||||
**Key Characteristics:**
|
||||
- [Characteristic 1: e.g., "Single executable"]
|
||||
- [Characteristic 2: e.g., "Stateless request handling"]
|
||||
- [Characteristic 3: e.g., "Event-driven"]
|
||||
|
||||
## Layers
|
||||
|
||||
[Describe the conceptual layers and their responsibilities]
|
||||
|
||||
**[Layer Name]:**
|
||||
- Purpose: [What this layer does]
|
||||
- Contains: [Types of code: e.g., "route handlers", "business logic"]
|
||||
- Depends on: [What it uses: e.g., "data layer only"]
|
||||
- Used by: [What uses it: e.g., "API routes"]
|
||||
|
||||
**[Layer Name]:**
|
||||
- Purpose: [What this layer does]
|
||||
- Contains: [Types of code]
|
||||
- Depends on: [What it uses]
|
||||
- Used by: [What uses it]
|
||||
|
||||
## Data Flow
|
||||
|
||||
[Describe the typical request/execution lifecycle]
|
||||
|
||||
**[Flow Name] (e.g., "HTTP Request", "CLI Command", "Event Processing"):**
|
||||
|
||||
1. [Entry point: e.g., "User runs command"]
|
||||
2. [Processing step: e.g., "Router matches path"]
|
||||
3. [Processing step: e.g., "Controller validates input"]
|
||||
4. [Processing step: e.g., "Service executes logic"]
|
||||
5. [Output: e.g., "Response returned"]
|
||||
|
||||
**State Management:**
|
||||
- [How state is handled: e.g., "Stateless - no persistent state", "Database per request", "In-memory cache"]
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
[Core concepts/patterns used throughout the codebase]
|
||||
|
||||
**[Abstraction Name]:**
|
||||
- Purpose: [What it represents]
|
||||
- Examples: [e.g., "UserService, ProjectService"]
|
||||
- Pattern: [e.g., "Singleton", "Factory", "Repository"]
|
||||
|
||||
**[Abstraction Name]:**
|
||||
- Purpose: [What it represents]
|
||||
- Examples: [Concrete examples]
|
||||
- Pattern: [Pattern used]
|
||||
|
||||
## Entry Points
|
||||
|
||||
[Where execution begins]
|
||||
|
||||
**[Entry Point]:**
|
||||
- Location: [Brief: e.g., "src/index.ts", "API Gateway triggers"]
|
||||
- Triggers: [What invokes it: e.g., "CLI invocation", "HTTP request"]
|
||||
- Responsibilities: [What it does: e.g., "Parse args, route to command"]
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Strategy:** [How errors are handled: e.g., "Exception bubbling to top-level handler", "Per-route error middleware"]
|
||||
|
||||
**Patterns:**
|
||||
- [Pattern: e.g., "try/catch at controller level"]
|
||||
- [Pattern: e.g., "Error codes returned to user"]
|
||||
|
||||
## Cross-Cutting Concerns
|
||||
|
||||
[Aspects that affect multiple layers]
|
||||
|
||||
**Logging:**
|
||||
- [Approach: e.g., "Winston logger, injected per-request"]
|
||||
|
||||
**Validation:**
|
||||
- [Approach: e.g., "Zod schemas at API boundary"]
|
||||
|
||||
**Authentication:**
|
||||
- [Approach: e.g., "JWT middleware on protected routes"]
|
||||
|
||||
---
|
||||
|
||||
*Architecture analysis: [date]*
|
||||
*Update when major patterns change*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Architecture
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Pattern Overview
|
||||
|
||||
**Overall:** CLI Application with Plugin System
|
||||
|
||||
**Key Characteristics:**
|
||||
- Single executable with subcommands
|
||||
- Plugin-based extensibility
|
||||
- File-based state (no database)
|
||||
- Synchronous execution model
|
||||
|
||||
## Layers
|
||||
|
||||
**Command Layer:**
|
||||
- Purpose: Parse user input and route to appropriate handler
|
||||
- Contains: Command definitions, argument parsing, help text
|
||||
- Location: `src/commands/*.ts`
|
||||
- Depends on: Service layer for business logic
|
||||
- Used by: CLI entry point (`src/index.ts`)
|
||||
|
||||
**Service Layer:**
|
||||
- Purpose: Core business logic
|
||||
- Contains: FileService, TemplateService, InstallService
|
||||
- Location: `src/services/*.ts`
|
||||
- Depends on: File system utilities, external tools
|
||||
- Used by: Command handlers
|
||||
|
||||
**Utility Layer:**
|
||||
- Purpose: Shared helpers and abstractions
|
||||
- Contains: File I/O wrappers, path resolution, string formatting
|
||||
- Location: `src/utils/*.ts`
|
||||
- Depends on: Node.js built-ins only
|
||||
- Used by: Service layer
|
||||
|
||||
## Data Flow
|
||||
|
||||
**CLI Command Execution:**
|
||||
|
||||
1. User runs: `gsd new-project`
|
||||
2. Commander parses args and flags
|
||||
3. Command handler invoked (`src/commands/new-project.ts`)
|
||||
4. Handler calls service methods (`src/services/project.ts` → `create()`)
|
||||
5. Service reads templates, processes files, writes output
|
||||
6. Results logged to console
|
||||
7. Process exits with status code
|
||||
|
||||
**State Management:**
|
||||
- File-based: All state lives in `.planning/` directory
|
||||
- No persistent in-memory state
|
||||
- Each command execution is independent
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
**Service:**
|
||||
- Purpose: Encapsulate business logic for a domain
|
||||
- Examples: `src/services/file.ts`, `src/services/template.ts`, `src/services/project.ts`
|
||||
- Pattern: Singleton-like (imported as modules, not instantiated)
|
||||
|
||||
**Command:**
|
||||
- Purpose: CLI command definition
|
||||
- Examples: `src/commands/new-project.ts`, `src/commands/plan-phase.ts`
|
||||
- Pattern: Commander.js command registration
|
||||
|
||||
**Template:**
|
||||
- Purpose: Reusable document structures
|
||||
- Examples: PROJECT.md, PLAN.md templates
|
||||
- Pattern: Markdown files with substitution variables
|
||||
|
||||
## Entry Points
|
||||
|
||||
**CLI Entry:**
|
||||
- Location: `src/index.ts`
|
||||
- Triggers: User runs `gsd <command>`
|
||||
- Responsibilities: Register commands, parse args, display help
|
||||
|
||||
**Commands:**
|
||||
- Location: `src/commands/*.ts`
|
||||
- Triggers: Matched command from CLI
|
||||
- Responsibilities: Validate input, call services, format output
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Strategy:** Throw exceptions, catch at command level, log and exit
|
||||
|
||||
**Patterns:**
|
||||
- Services throw Error with descriptive messages
|
||||
- Command handlers catch, log error to stderr, exit(1)
|
||||
- Validation errors shown before execution (fail fast)
|
||||
|
||||
## Cross-Cutting Concerns
|
||||
|
||||
**Logging:**
|
||||
- Console.log for normal output
|
||||
- Console.error for errors
|
||||
- Chalk for colored output
|
||||
|
||||
**Validation:**
|
||||
- Zod schemas for config file parsing
|
||||
- Manual validation in command handlers
|
||||
- Fail fast on invalid input
|
||||
|
||||
**File Operations:**
|
||||
- FileService abstraction over fs-extra
|
||||
- All paths validated before operations
|
||||
- Atomic writes (temp file + rename)
|
||||
|
||||
---
|
||||
|
||||
*Architecture analysis: 2025-01-20*
|
||||
*Update when major patterns change*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in ARCHITECTURE.md:**
|
||||
- Overall architectural pattern (monolith, microservices, layered, etc.)
|
||||
- Conceptual layers and their relationships
|
||||
- Data flow / request lifecycle
|
||||
- Key abstractions and patterns
|
||||
- Entry points
|
||||
- Error handling strategy
|
||||
- Cross-cutting concerns (logging, auth, validation)
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Exhaustive file listings (that's STRUCTURE.md)
|
||||
- Technology choices (that's STACK.md)
|
||||
- Line-by-line code walkthrough (defer to code reading)
|
||||
- Implementation details of specific features
|
||||
|
||||
**File paths ARE welcome:**
|
||||
Include file paths as concrete examples of abstractions. Use backtick formatting: `src/services/user.ts`. This makes the architecture document actionable for Claude when planning.
|
||||
|
||||
**When filling this template:**
|
||||
- Read main entry points (index, server, main)
|
||||
- Identify layers by reading imports/dependencies
|
||||
- Trace a typical request/command execution
|
||||
- Note recurring patterns (services, controllers, repositories)
|
||||
- Keep descriptions conceptual, not mechanical
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Adding new features (where does it fit in the layers?)
|
||||
- Refactoring (understanding current patterns)
|
||||
- Identifying where to add code (which layer handles X?)
|
||||
- Understanding dependencies between components
|
||||
</guidelines>
|
||||
310
gsd-core/templates/codebase/concerns.md
Normal file
310
gsd-core/templates/codebase/concerns.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# Codebase Concerns Template
|
||||
|
||||
Template for `.planning/codebase/CONCERNS.md` - captures known issues and areas requiring care.
|
||||
|
||||
**Purpose:** Surface actionable warnings about the codebase. Focused on "what to watch out for when making changes."
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Codebase Concerns
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Tech Debt
|
||||
|
||||
**[Area/Component]:**
|
||||
- Issue: [What's the shortcut/workaround]
|
||||
- Why: [Why it was done this way]
|
||||
- Impact: [What breaks or degrades because of it]
|
||||
- Fix approach: [How to properly address it]
|
||||
|
||||
**[Area/Component]:**
|
||||
- Issue: [What's the shortcut/workaround]
|
||||
- Why: [Why it was done this way]
|
||||
- Impact: [What breaks or degrades because of it]
|
||||
- Fix approach: [How to properly address it]
|
||||
|
||||
## Known Bugs
|
||||
|
||||
**[Bug description]:**
|
||||
- Symptoms: [What happens]
|
||||
- Trigger: [How to reproduce]
|
||||
- Workaround: [Temporary mitigation if any]
|
||||
- Root cause: [If known]
|
||||
- Blocked by: [If waiting on something]
|
||||
|
||||
**[Bug description]:**
|
||||
- Symptoms: [What happens]
|
||||
- Trigger: [How to reproduce]
|
||||
- Workaround: [Temporary mitigation if any]
|
||||
- Root cause: [If known]
|
||||
|
||||
## Security Considerations
|
||||
|
||||
**[Area requiring security care]:**
|
||||
- Risk: [What could go wrong]
|
||||
- Current mitigation: [What's in place now]
|
||||
- Recommendations: [What should be added]
|
||||
|
||||
**[Area requiring security care]:**
|
||||
- Risk: [What could go wrong]
|
||||
- Current mitigation: [What's in place now]
|
||||
- Recommendations: [What should be added]
|
||||
|
||||
## Performance Bottlenecks
|
||||
|
||||
**[Slow operation/endpoint]:**
|
||||
- Problem: [What's slow]
|
||||
- Measurement: [Actual numbers: "500ms p95", "2s load time"]
|
||||
- Cause: [Why it's slow]
|
||||
- Improvement path: [How to speed it up]
|
||||
|
||||
**[Slow operation/endpoint]:**
|
||||
- Problem: [What's slow]
|
||||
- Measurement: [Actual numbers]
|
||||
- Cause: [Why it's slow]
|
||||
- Improvement path: [How to speed it up]
|
||||
|
||||
## Fragile Areas
|
||||
|
||||
**[Component/Module]:**
|
||||
- Why fragile: [What makes it break easily]
|
||||
- Common failures: [What typically goes wrong]
|
||||
- Safe modification: [How to change it without breaking]
|
||||
- Test coverage: [Is it tested? Gaps?]
|
||||
|
||||
**[Component/Module]:**
|
||||
- Why fragile: [What makes it break easily]
|
||||
- Common failures: [What typically goes wrong]
|
||||
- Safe modification: [How to change it without breaking]
|
||||
- Test coverage: [Is it tested? Gaps?]
|
||||
|
||||
## Scaling Limits
|
||||
|
||||
**[Resource/System]:**
|
||||
- Current capacity: [Numbers: "100 req/sec", "10k users"]
|
||||
- Limit: [Where it breaks]
|
||||
- Symptoms at limit: [What happens]
|
||||
- Scaling path: [How to increase capacity]
|
||||
|
||||
## Dependencies at Risk
|
||||
|
||||
**[Package/Service]:**
|
||||
- Risk: [e.g., "deprecated", "unmaintained", "breaking changes coming"]
|
||||
- Impact: [What breaks if it fails]
|
||||
- Migration plan: [Alternative or upgrade path]
|
||||
|
||||
## Missing Critical Features
|
||||
|
||||
**[Feature gap]:**
|
||||
- Problem: [What's missing]
|
||||
- Current workaround: [How users cope]
|
||||
- Blocks: [What can't be done without it]
|
||||
- Implementation complexity: [Rough effort estimate]
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**[Untested area]:**
|
||||
- What's not tested: [Specific functionality]
|
||||
- Risk: [What could break unnoticed]
|
||||
- Priority: [High/Medium/Low]
|
||||
- Difficulty to test: [Why it's not tested yet]
|
||||
|
||||
---
|
||||
|
||||
*Concerns audit: [date]*
|
||||
*Update as issues are fixed or new ones discovered*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Codebase Concerns
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Tech Debt
|
||||
|
||||
**Database queries in React components:**
|
||||
- Issue: Direct Supabase queries in 15+ page components instead of server actions
|
||||
- Files: `app/dashboard/page.tsx`, `app/profile/page.tsx`, `app/courses/[id]/page.tsx`, `app/settings/page.tsx` (and 11 more in `app/`)
|
||||
- Why: Rapid prototyping during MVP phase
|
||||
- Impact: Can't implement RLS properly, exposes DB structure to client
|
||||
- Fix approach: Move all queries to server actions in `app/actions/`, add proper RLS policies
|
||||
|
||||
**Manual webhook signature validation:**
|
||||
- Issue: Copy-pasted Stripe webhook verification code in 3 different endpoints
|
||||
- Files: `app/api/webhooks/stripe/route.ts`, `app/api/webhooks/checkout/route.ts`, `app/api/webhooks/subscription/route.ts`
|
||||
- Why: Each webhook added ad-hoc without abstraction
|
||||
- Impact: Easy to miss verification in new webhooks (security risk)
|
||||
- Fix approach: Create shared `lib/stripe/validate-webhook.ts` middleware
|
||||
|
||||
## Known Bugs
|
||||
|
||||
**Race condition in subscription updates:**
|
||||
- Symptoms: User shows as "free" tier for 5-10 seconds after successful payment
|
||||
- Trigger: Fast navigation after Stripe checkout redirect, before webhook processes
|
||||
- Files: `app/checkout/success/page.tsx` (redirect handler), `app/api/webhooks/stripe/route.ts` (webhook)
|
||||
- Workaround: Stripe webhook eventually updates status (self-heals)
|
||||
- Root cause: Webhook processing slower than user navigation, no optimistic UI update
|
||||
- Fix: Add polling in `app/checkout/success/page.tsx` after redirect
|
||||
|
||||
**Inconsistent session state after logout:**
|
||||
- Symptoms: User redirected to /dashboard after logout instead of /login
|
||||
- Trigger: Logout via button in mobile nav (desktop works fine)
|
||||
- File: `components/MobileNav.tsx` (line ~45, logout handler)
|
||||
- Workaround: Manual URL navigation to /login works
|
||||
- Root cause: Mobile nav component not awaiting supabase.auth.signOut()
|
||||
- Fix: Add await to logout handler in `components/MobileNav.tsx`
|
||||
|
||||
## Security Considerations
|
||||
|
||||
**Admin role check client-side only:**
|
||||
- Risk: Admin dashboard pages check isAdmin from Supabase client, no server verification
|
||||
- Files: `app/admin/page.tsx`, `app/admin/users/page.tsx`, `components/AdminGuard.tsx`
|
||||
- Current mitigation: None (relying on UI hiding)
|
||||
- Recommendations: Add middleware to admin routes in `middleware.ts`, verify role server-side
|
||||
|
||||
**Unvalidated file uploads:**
|
||||
- Risk: Users can upload any file type to avatar bucket (no size/type validation)
|
||||
- File: `components/AvatarUpload.tsx` (upload handler)
|
||||
- Current mitigation: Supabase bucket limits to 2MB (configured in dashboard)
|
||||
- Recommendations: Add file type validation (image/* only) in `lib/storage/validate.ts`
|
||||
|
||||
## Performance Bottlenecks
|
||||
|
||||
**/api/courses endpoint:**
|
||||
- Problem: Fetching all courses with nested lessons and authors
|
||||
- File: `app/api/courses/route.ts`
|
||||
- Measurement: 1.2s p95 response time with 50+ courses
|
||||
- Cause: N+1 query pattern (separate query per course for lessons)
|
||||
- Improvement path: Use Prisma include to eager-load lessons in `lib/db/courses.ts`, add Redis caching
|
||||
|
||||
**Dashboard initial load:**
|
||||
- Problem: Waterfall of 5 serial API calls on mount
|
||||
- File: `app/dashboard/page.tsx`
|
||||
- Measurement: 3.5s until interactive on slow 3G
|
||||
- Cause: Each component fetches own data independently
|
||||
- Improvement path: Convert to Server Component with single parallel fetch
|
||||
|
||||
## Fragile Areas
|
||||
|
||||
**Authentication middleware chain:**
|
||||
- File: `middleware.ts`
|
||||
- Why fragile: 4 different middleware functions run in specific order (auth -> role -> subscription -> logging)
|
||||
- Common failures: Middleware order change breaks everything, hard to debug
|
||||
- Safe modification: Add tests before changing order, document dependencies in comments
|
||||
- Test coverage: No integration tests for middleware chain (only unit tests)
|
||||
|
||||
**Stripe webhook event handling:**
|
||||
- File: `app/api/webhooks/stripe/route.ts`
|
||||
- Why fragile: Giant switch statement with 12 event types, shared transaction logic
|
||||
- Common failures: New event type added without handling, partial DB updates on error
|
||||
- Safe modification: Extract each event handler to `lib/stripe/handlers/*.ts`
|
||||
- Test coverage: Only 3 of 12 event types have tests
|
||||
|
||||
## Scaling Limits
|
||||
|
||||
**Supabase Free Tier:**
|
||||
- Current capacity: 500MB database, 1GB file storage, 2GB bandwidth/month
|
||||
- Limit: ~5000 users estimated before hitting limits
|
||||
- Symptoms at limit: 429 rate limit errors, DB writes fail
|
||||
- Scaling path: Upgrade to Pro ($25/mo) extends to 8GB DB, 100GB storage
|
||||
|
||||
**Server-side render blocking:**
|
||||
- Current capacity: ~50 concurrent users before slowdown
|
||||
- Limit: Vercel Hobby plan (10s function timeout, 100GB-hrs/mo)
|
||||
- Symptoms at limit: 504 gateway timeouts on course pages
|
||||
- Scaling path: Upgrade to Vercel Pro ($20/mo), add edge caching
|
||||
|
||||
## Dependencies at Risk
|
||||
|
||||
**react-hot-toast:**
|
||||
- Risk: Unmaintained (last update 18 months ago), React 19 compatibility unknown
|
||||
- Impact: Toast notifications break, no graceful degradation
|
||||
- Migration plan: Switch to sonner (actively maintained, similar API)
|
||||
|
||||
## Missing Critical Features
|
||||
|
||||
**Payment failure handling:**
|
||||
- Problem: No retry mechanism or user notification when subscription payment fails
|
||||
- Current workaround: Users manually re-enter payment info (if they notice)
|
||||
- Blocks: Can't retain users with expired cards, no dunning process
|
||||
- Implementation complexity: Medium (Stripe webhooks + email flow + UI)
|
||||
|
||||
**Course progress tracking:**
|
||||
- Problem: No persistent state for which lessons completed
|
||||
- Current workaround: Users manually track progress
|
||||
- Blocks: Can't show completion percentage, can't recommend next lesson
|
||||
- Implementation complexity: Low (add completed_lessons junction table)
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**Payment flow end-to-end:**
|
||||
- What's not tested: Full Stripe checkout -> webhook -> subscription activation flow
|
||||
- Risk: Payment processing could break silently (has happened twice)
|
||||
- Priority: High
|
||||
- Difficulty to test: Need Stripe test fixtures and webhook simulation setup
|
||||
|
||||
**Error boundary behavior:**
|
||||
- What's not tested: How app behaves when components throw errors
|
||||
- Risk: White screen of death for users, no error reporting
|
||||
- Priority: Medium
|
||||
- Difficulty to test: Need to intentionally trigger errors in test environment
|
||||
|
||||
---
|
||||
|
||||
*Concerns audit: 2025-01-20*
|
||||
*Update as issues are fixed or new ones discovered*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in CONCERNS.md:**
|
||||
- Tech debt with clear impact and fix approach
|
||||
- Known bugs with reproduction steps
|
||||
- Security gaps and mitigation recommendations
|
||||
- Performance bottlenecks with measurements
|
||||
- Fragile code that breaks easily
|
||||
- Scaling limits with numbers
|
||||
- Dependencies that need attention
|
||||
- Missing features that block workflows
|
||||
- Test coverage gaps
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Opinions without evidence ("code is messy")
|
||||
- Complaints without solutions ("auth sucks")
|
||||
- Future feature ideas (that's for product planning)
|
||||
- Normal TODOs (those live in code comments)
|
||||
- Architectural decisions that are working fine
|
||||
- Minor code style issues
|
||||
|
||||
**When filling this template:**
|
||||
- **Always include file paths** - Concerns without locations are not actionable. Use backticks: `src/file.ts`
|
||||
- Be specific with measurements ("500ms p95" not "slow")
|
||||
- Include reproduction steps for bugs
|
||||
- Suggest fix approaches, not just problems
|
||||
- Focus on actionable items
|
||||
- Prioritize by risk/impact
|
||||
- Update as issues get resolved
|
||||
- Add new concerns as discovered
|
||||
|
||||
**Tone guidelines:**
|
||||
- Professional, not emotional ("N+1 query pattern" not "terrible queries")
|
||||
- Solution-oriented ("Fix: add index" not "needs fixing")
|
||||
- Risk-focused ("Could expose user data" not "security is bad")
|
||||
- Factual ("3.5s load time" not "really slow")
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Deciding what to work on next
|
||||
- Estimating risk of changes
|
||||
- Understanding where to be careful
|
||||
- Prioritizing improvements
|
||||
- Onboarding new Claude contexts
|
||||
- Planning refactoring work
|
||||
|
||||
**How this gets populated:**
|
||||
Explore agents detect these during codebase mapping. Manual additions welcome for human-discovered issues. This is living documentation, not a complaint list.
|
||||
</guidelines>
|
||||
307
gsd-core/templates/codebase/conventions.md
Normal file
307
gsd-core/templates/codebase/conventions.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# Coding Conventions Template
|
||||
|
||||
Template for `.planning/codebase/CONVENTIONS.md` - captures coding style and patterns.
|
||||
|
||||
**Purpose:** Document how code is written in this codebase. Prescriptive guide for Claude to match existing style.
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Files:**
|
||||
- [Pattern: e.g., "kebab-case for all files"]
|
||||
- [Test files: e.g., "*.test.ts alongside source"]
|
||||
- [Components: e.g., "PascalCase.tsx for React components"]
|
||||
|
||||
**Functions:**
|
||||
- [Pattern: e.g., "camelCase for all functions"]
|
||||
- [Async: e.g., "no special prefix for async functions"]
|
||||
- [Handlers: e.g., "handleEventName for event handlers"]
|
||||
|
||||
**Variables:**
|
||||
- [Pattern: e.g., "camelCase for variables"]
|
||||
- [Constants: e.g., "UPPER_SNAKE_CASE for constants"]
|
||||
- [Private: e.g., "_prefix for private members" or "no prefix"]
|
||||
|
||||
**Types:**
|
||||
- [Interfaces: e.g., "PascalCase, no I prefix"]
|
||||
- [Types: e.g., "PascalCase for type aliases"]
|
||||
- [Enums: e.g., "PascalCase for enum name, UPPER_CASE for values"]
|
||||
|
||||
## Code Style
|
||||
|
||||
**Formatting:**
|
||||
- [Tool: e.g., "Prettier with config in .prettierrc"]
|
||||
- [Line length: e.g., "100 characters max"]
|
||||
- [Quotes: e.g., "single quotes for strings"]
|
||||
- [Semicolons: e.g., "required" or "omitted"]
|
||||
|
||||
**Linting:**
|
||||
- [Tool: e.g., "ESLint with eslint.config.js"]
|
||||
- [Rules: e.g., "extends airbnb-base, no console in production"]
|
||||
- [Run: e.g., "npm run lint"]
|
||||
|
||||
## Import Organization
|
||||
|
||||
**Order:**
|
||||
1. [e.g., "External packages (react, express, etc.)"]
|
||||
2. [e.g., "Internal modules (@/lib, @/components)"]
|
||||
3. [e.g., "Relative imports (., ..)"]
|
||||
4. [e.g., "Type imports (import type {})"]
|
||||
|
||||
**Grouping:**
|
||||
- [Blank lines: e.g., "blank line between groups"]
|
||||
- [Sorting: e.g., "alphabetical within each group"]
|
||||
|
||||
**Path Aliases:**
|
||||
- [Aliases used: e.g., "@/ for src/, @components/ for src/components/"]
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Patterns:**
|
||||
- [Strategy: e.g., "throw errors, catch at boundaries"]
|
||||
- [Custom errors: e.g., "extend Error class, named *Error"]
|
||||
- [Async: e.g., "use try/catch, no .catch() chains"]
|
||||
|
||||
**Error Types:**
|
||||
- [When to throw: e.g., "invalid input, missing dependencies"]
|
||||
- [When to return: e.g., "expected failures return Result<T, E>"]
|
||||
- [Logging: e.g., "log error with context before throwing"]
|
||||
|
||||
## Logging
|
||||
|
||||
**Framework:**
|
||||
- [Tool: e.g., "console.log, pino, winston"]
|
||||
- [Levels: e.g., "debug, info, warn, error"]
|
||||
|
||||
**Patterns:**
|
||||
- [Format: e.g., "structured logging with context object"]
|
||||
- [When: e.g., "log state transitions, external calls"]
|
||||
- [Where: e.g., "log at service boundaries, not in utils"]
|
||||
|
||||
## Comments
|
||||
|
||||
**When to Comment:**
|
||||
- [e.g., "explain why, not what"]
|
||||
- [e.g., "document business logic, algorithms, edge cases"]
|
||||
- [e.g., "avoid obvious comments like // increment counter"]
|
||||
|
||||
**JSDoc/TSDoc:**
|
||||
- [Usage: e.g., "required for public APIs, optional for internal"]
|
||||
- [Format: e.g., "use @param, @returns, @throws tags"]
|
||||
|
||||
**TODO Comments:**
|
||||
- [Pattern: e.g., "// TODO(username): description"]
|
||||
- [Tracking: e.g., "link to issue number if available"]
|
||||
|
||||
## Function Design
|
||||
|
||||
**Size:**
|
||||
- [e.g., "keep under 50 lines, extract helpers"]
|
||||
|
||||
**Parameters:**
|
||||
- [e.g., "max 3 parameters, use object for more"]
|
||||
- [e.g., "destructure objects in parameter list"]
|
||||
|
||||
**Return Values:**
|
||||
- [e.g., "explicit returns, no implicit undefined"]
|
||||
- [e.g., "return early for guard clauses"]
|
||||
|
||||
## Module Design
|
||||
|
||||
**Exports:**
|
||||
- [e.g., "named exports preferred, default exports for React components"]
|
||||
- [e.g., "export from index.ts for public API"]
|
||||
|
||||
**Barrel Files:**
|
||||
- [e.g., "use index.ts to re-export public API"]
|
||||
- [e.g., "avoid circular dependencies"]
|
||||
|
||||
---
|
||||
|
||||
*Convention analysis: [date]*
|
||||
*Update when patterns change*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Files:**
|
||||
- kebab-case for all files (command-handler.ts, user-service.ts)
|
||||
- *.test.ts alongside source files
|
||||
- index.ts for barrel exports
|
||||
|
||||
**Functions:**
|
||||
- camelCase for all functions
|
||||
- No special prefix for async functions
|
||||
- handleEventName for event handlers (handleClick, handleSubmit)
|
||||
|
||||
**Variables:**
|
||||
- camelCase for variables
|
||||
- UPPER_SNAKE_CASE for constants (MAX_RETRIES, API_BASE_URL)
|
||||
- No underscore prefix (no private marker in TS)
|
||||
|
||||
**Types:**
|
||||
- PascalCase for interfaces, no I prefix (User, not IUser)
|
||||
- PascalCase for type aliases (UserConfig, ResponseData)
|
||||
- PascalCase for enum names, UPPER_CASE for values (Status.PENDING)
|
||||
|
||||
## Code Style
|
||||
|
||||
**Formatting:**
|
||||
- Prettier with .prettierrc
|
||||
- 100 character line length
|
||||
- Single quotes for strings
|
||||
- Semicolons required
|
||||
- 2 space indentation
|
||||
|
||||
**Linting:**
|
||||
- ESLint with eslint.config.js
|
||||
- Extends @typescript-eslint/recommended
|
||||
- No console.log in production code (use logger)
|
||||
- Run: npm run lint
|
||||
|
||||
## Import Organization
|
||||
|
||||
**Order:**
|
||||
1. External packages (react, express, commander)
|
||||
2. Internal modules (@/lib, @/services)
|
||||
3. Relative imports (./utils, ../types)
|
||||
4. Type imports (import type { User })
|
||||
|
||||
**Grouping:**
|
||||
- Blank line between groups
|
||||
- Alphabetical within each group
|
||||
- Type imports last within each group
|
||||
|
||||
**Path Aliases:**
|
||||
- @/ maps to src/
|
||||
- No other aliases defined
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Patterns:**
|
||||
- Throw errors, catch at boundaries (route handlers, main functions)
|
||||
- Extend Error class for custom errors (ValidationError, NotFoundError)
|
||||
- Async functions use try/catch, no .catch() chains
|
||||
|
||||
**Error Types:**
|
||||
- Throw on invalid input, missing dependencies, invariant violations
|
||||
- Log error with context before throwing: logger.error({ err, userId }, 'Failed to process')
|
||||
- Include cause in error message: new Error('Failed to X', { cause: originalError })
|
||||
|
||||
## Logging
|
||||
|
||||
**Framework:**
|
||||
- pino logger instance exported from lib/logger.ts
|
||||
- Levels: debug, info, warn, error (no trace)
|
||||
|
||||
**Patterns:**
|
||||
- Structured logging with context: logger.info({ userId, action }, 'User action')
|
||||
- Log at service boundaries, not in utility functions
|
||||
- Log state transitions, external API calls, errors
|
||||
- No console.log in committed code
|
||||
|
||||
## Comments
|
||||
|
||||
**When to Comment:**
|
||||
- Explain why, not what: // Retry 3 times because API has transient failures
|
||||
- Document business rules: // Users must verify email within 24 hours
|
||||
- Explain non-obvious algorithms or workarounds
|
||||
- Avoid obvious comments: // set count to 0
|
||||
|
||||
**JSDoc/TSDoc:**
|
||||
- Required for public API functions
|
||||
- Optional for internal functions if signature is self-explanatory
|
||||
- Use @param, @returns, @throws tags
|
||||
|
||||
**TODO Comments:**
|
||||
- Format: // TODO: description (no username, using git blame)
|
||||
- Link to issue if exists: // TODO: Fix race condition (issue #123)
|
||||
|
||||
## Function Design
|
||||
|
||||
**Size:**
|
||||
- Keep under 50 lines
|
||||
- Extract helpers for complex logic
|
||||
- One level of abstraction per function
|
||||
|
||||
**Parameters:**
|
||||
- Max 3 parameters
|
||||
- Use options object for 4+ parameters: function create(options: CreateOptions)
|
||||
- Destructure in parameter list: function process({ id, name }: ProcessParams)
|
||||
|
||||
**Return Values:**
|
||||
- Explicit return statements
|
||||
- Return early for guard clauses
|
||||
- Use Result<T, E> type for expected failures
|
||||
|
||||
## Module Design
|
||||
|
||||
**Exports:**
|
||||
- Named exports preferred
|
||||
- Default exports only for React components
|
||||
- Export public API from index.ts barrel files
|
||||
|
||||
**Barrel Files:**
|
||||
- index.ts re-exports public API
|
||||
- Keep internal helpers private (don't export from index)
|
||||
- Avoid circular dependencies (import from specific files if needed)
|
||||
|
||||
---
|
||||
|
||||
*Convention analysis: 2025-01-20*
|
||||
*Update when patterns change*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in CONVENTIONS.md:**
|
||||
- Naming patterns observed in the codebase
|
||||
- Formatting rules (Prettier config, linting rules)
|
||||
- Import organization patterns
|
||||
- Error handling strategy
|
||||
- Logging approach
|
||||
- Comment conventions
|
||||
- Function and module design patterns
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Architecture decisions (that's ARCHITECTURE.md)
|
||||
- Technology choices (that's STACK.md)
|
||||
- Test patterns (that's TESTING.md)
|
||||
- File organization (that's STRUCTURE.md)
|
||||
|
||||
**When filling this template:**
|
||||
- Check .prettierrc, .eslintrc, or similar config files
|
||||
- Examine 5-10 representative source files for patterns
|
||||
- Look for consistency: if 80%+ follows a pattern, document it
|
||||
- Be prescriptive: "Use X" not "Sometimes Y is used"
|
||||
- Note deviations: "Legacy code uses Y, new code should use X"
|
||||
- Keep under ~150 lines total
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Writing new code (match existing style)
|
||||
- Adding features (follow naming patterns)
|
||||
- Refactoring (apply consistent conventions)
|
||||
- Code review (check against documented patterns)
|
||||
- Onboarding (understand style expectations)
|
||||
|
||||
**Analysis approach:**
|
||||
- Scan src/ directory for file naming patterns
|
||||
- Check package.json scripts for lint/format commands
|
||||
- Read 5-10 files to identify function naming, error handling
|
||||
- Look for config files (.prettierrc, eslint.config.js)
|
||||
- Note patterns in imports, comments, function signatures
|
||||
</guidelines>
|
||||
280
gsd-core/templates/codebase/integrations.md
Normal file
280
gsd-core/templates/codebase/integrations.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# External Integrations Template
|
||||
|
||||
Template for `.planning/codebase/INTEGRATIONS.md` - captures external service dependencies.
|
||||
|
||||
**Purpose:** Document what external systems this codebase communicates with. Focused on "what lives outside our code that we depend on."
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# External Integrations
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## APIs & External Services
|
||||
|
||||
**Payment Processing:**
|
||||
- [Service] - [What it's used for: e.g., "subscription billing, one-time payments"]
|
||||
- SDK/Client: [e.g., "stripe npm package v14.x"]
|
||||
- Auth: [e.g., "API key in STRIPE_SECRET_KEY env var"]
|
||||
- Endpoints used: [e.g., "checkout sessions, webhooks"]
|
||||
|
||||
**Email/SMS:**
|
||||
- [Service] - [What it's used for: e.g., "transactional emails"]
|
||||
- SDK/Client: [e.g., "sendgrid/mail v8.x"]
|
||||
- Auth: [e.g., "API key in SENDGRID_API_KEY env var"]
|
||||
- Templates: [e.g., "managed in SendGrid dashboard"]
|
||||
|
||||
**External APIs:**
|
||||
- [Service] - [What it's used for]
|
||||
- Integration method: [e.g., "REST API via fetch", "GraphQL client"]
|
||||
- Auth: [e.g., "OAuth2 token in AUTH_TOKEN env var"]
|
||||
- Rate limits: [if applicable]
|
||||
|
||||
## Data Storage
|
||||
|
||||
**Databases:**
|
||||
- [Type/Provider] - [e.g., "PostgreSQL on Supabase"]
|
||||
- Connection: [e.g., "via DATABASE_URL env var"]
|
||||
- Client: [e.g., "Prisma ORM v5.x"]
|
||||
- Migrations: [e.g., "prisma migrate in migrations/"]
|
||||
|
||||
**File Storage:**
|
||||
- [Service] - [e.g., "AWS S3 for user uploads"]
|
||||
- SDK/Client: [e.g., "@aws-sdk/client-s3"]
|
||||
- Auth: [e.g., "IAM credentials in AWS_* env vars"]
|
||||
- Buckets: [e.g., "prod-uploads, dev-uploads"]
|
||||
|
||||
**Caching:**
|
||||
- [Service] - [e.g., "Redis for session storage"]
|
||||
- Connection: [e.g., "REDIS_URL env var"]
|
||||
- Client: [e.g., "ioredis v5.x"]
|
||||
|
||||
## Authentication & Identity
|
||||
|
||||
**Auth Provider:**
|
||||
- [Service] - [e.g., "Supabase Auth", "Auth0", "custom JWT"]
|
||||
- Implementation: [e.g., "Supabase client SDK"]
|
||||
- Token storage: [e.g., "httpOnly cookies", "localStorage"]
|
||||
- Session management: [e.g., "JWT refresh tokens"]
|
||||
|
||||
**OAuth Integrations:**
|
||||
- [Provider] - [e.g., "Google OAuth for sign-in"]
|
||||
- Credentials: [e.g., "GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET"]
|
||||
- Scopes: [e.g., "email, profile"]
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
- [Service] - [e.g., "Sentry"]
|
||||
- DSN: [e.g., "SENTRY_DSN env var"]
|
||||
- Release tracking: [e.g., "via SENTRY_RELEASE"]
|
||||
|
||||
**Analytics:**
|
||||
- [Service] - [e.g., "Mixpanel for product analytics"]
|
||||
- Token: [e.g., "MIXPANEL_TOKEN env var"]
|
||||
- Events tracked: [e.g., "user actions, page views"]
|
||||
|
||||
**Logs:**
|
||||
- [Service] - [e.g., "CloudWatch", "Datadog", "none (stdout only)"]
|
||||
- Integration: [e.g., "AWS Lambda built-in"]
|
||||
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
- [Platform] - [e.g., "Vercel", "AWS Lambda", "Docker on ECS"]
|
||||
- Deployment: [e.g., "automatic on main branch push"]
|
||||
- Environment vars: [e.g., "configured in Vercel dashboard"]
|
||||
|
||||
**CI Pipeline:**
|
||||
- [Service] - [e.g., "GitHub Actions"]
|
||||
- Workflows: [e.g., "test.yml, deploy.yml"]
|
||||
- Secrets: [e.g., "stored in GitHub repo secrets"]
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Development:**
|
||||
- Required env vars: [List critical vars]
|
||||
- Secrets location: [e.g., ".env.local (gitignored)", "1Password vault"]
|
||||
- Mock/stub services: [e.g., "Stripe test mode", "local PostgreSQL"]
|
||||
|
||||
**Staging:**
|
||||
- Environment-specific differences: [e.g., "uses staging Stripe account"]
|
||||
- Data: [e.g., "separate staging database"]
|
||||
|
||||
**Production:**
|
||||
- Secrets management: [e.g., "Vercel environment variables"]
|
||||
- Failover/redundancy: [e.g., "multi-region DB replication"]
|
||||
|
||||
## Webhooks & Callbacks
|
||||
|
||||
**Incoming:**
|
||||
- [Service] - [Endpoint: e.g., "/api/webhooks/stripe"]
|
||||
- Verification: [e.g., "signature validation via stripe.webhooks.constructEvent"]
|
||||
- Events: [e.g., "payment_intent.succeeded, customer.subscription.updated"]
|
||||
|
||||
**Outgoing:**
|
||||
- [Service] - [What triggers it]
|
||||
- Endpoint: [e.g., "external CRM webhook on user signup"]
|
||||
- Retry logic: [if applicable]
|
||||
|
||||
---
|
||||
|
||||
*Integration audit: [date]*
|
||||
*Update when adding/removing external services*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# External Integrations
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## APIs & External Services
|
||||
|
||||
**Payment Processing:**
|
||||
- Stripe - Subscription billing and one-time course payments
|
||||
- SDK/Client: stripe npm package v14.8
|
||||
- Auth: API key in STRIPE_SECRET_KEY env var
|
||||
- Endpoints used: checkout sessions, customer portal, webhooks
|
||||
|
||||
**Email/SMS:**
|
||||
- SendGrid - Transactional emails (receipts, password resets)
|
||||
- SDK/Client: @sendgrid/mail v8.1
|
||||
- Auth: API key in SENDGRID_API_KEY env var
|
||||
- Templates: Managed in SendGrid dashboard (template IDs in code)
|
||||
|
||||
**External APIs:**
|
||||
- OpenAI API - Course content generation
|
||||
- Integration method: REST API via openai npm package v4.x
|
||||
- Auth: Bearer token in OPENAI_API_KEY env var
|
||||
- Rate limits: 3500 requests/min (tier 3)
|
||||
|
||||
## Data Storage
|
||||
|
||||
**Databases:**
|
||||
- PostgreSQL on Supabase - Primary data store
|
||||
- Connection: via DATABASE_URL env var
|
||||
- Client: Prisma ORM v5.8
|
||||
- Migrations: prisma migrate in prisma/migrations/
|
||||
|
||||
**File Storage:**
|
||||
- Supabase Storage - User uploads (profile images, course materials)
|
||||
- SDK/Client: @supabase/supabase-js v2.x
|
||||
- Auth: Service role key in SUPABASE_SERVICE_ROLE_KEY
|
||||
- Buckets: avatars (public), course-materials (private)
|
||||
|
||||
**Caching:**
|
||||
- None currently (all database queries, no Redis)
|
||||
|
||||
## Authentication & Identity
|
||||
|
||||
**Auth Provider:**
|
||||
- Supabase Auth - Email/password + OAuth
|
||||
- Implementation: Supabase client SDK with server-side session management
|
||||
- Token storage: httpOnly cookies via @supabase/ssr
|
||||
- Session management: JWT refresh tokens handled by Supabase
|
||||
|
||||
**OAuth Integrations:**
|
||||
- Google OAuth - Social sign-in
|
||||
- Credentials: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET (Supabase dashboard)
|
||||
- Scopes: email, profile
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
- Sentry - Server and client errors
|
||||
- DSN: SENTRY_DSN env var
|
||||
- Release tracking: Git commit SHA via SENTRY_RELEASE
|
||||
|
||||
**Analytics:**
|
||||
- None (planned: Mixpanel)
|
||||
|
||||
**Logs:**
|
||||
- Vercel logs - stdout/stderr only
|
||||
- Retention: 7 days on Pro plan
|
||||
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
- Vercel - Next.js app hosting
|
||||
- Deployment: Automatic on main branch push
|
||||
- Environment vars: Configured in Vercel dashboard (synced to .env.example)
|
||||
|
||||
**CI Pipeline:**
|
||||
- GitHub Actions - Tests and type checking
|
||||
- Workflows: .github/workflows/ci.yml
|
||||
- Secrets: None needed (public repo tests only)
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Development:**
|
||||
- Required env vars: DATABASE_URL, NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||
- Secrets location: .env.local (gitignored), team shared via 1Password vault
|
||||
- Mock/stub services: Stripe test mode, Supabase local dev project
|
||||
|
||||
**Staging:**
|
||||
- Uses separate Supabase staging project
|
||||
- Stripe test mode
|
||||
- Same Vercel account, different environment
|
||||
|
||||
**Production:**
|
||||
- Secrets management: Vercel environment variables
|
||||
- Database: Supabase production project with daily backups
|
||||
|
||||
## Webhooks & Callbacks
|
||||
|
||||
**Incoming:**
|
||||
- Stripe - /api/webhooks/stripe
|
||||
- Verification: Signature validation via stripe.webhooks.constructEvent
|
||||
- Events: payment_intent.succeeded, customer.subscription.updated, customer.subscription.deleted
|
||||
|
||||
**Outgoing:**
|
||||
- None
|
||||
|
||||
---
|
||||
|
||||
*Integration audit: 2025-01-20*
|
||||
*Update when adding/removing external services*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in INTEGRATIONS.md:**
|
||||
- External services the code communicates with
|
||||
- Authentication patterns (where secrets live, not the secrets themselves)
|
||||
- SDKs and client libraries used
|
||||
- Environment variable names (not values)
|
||||
- Webhook endpoints and verification methods
|
||||
- Database connection patterns
|
||||
- File storage locations
|
||||
- Monitoring and logging services
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Actual API keys or secrets (NEVER write these)
|
||||
- Internal architecture (that's ARCHITECTURE.md)
|
||||
- Code patterns (that's PATTERNS.md)
|
||||
- Technology choices (that's STACK.md)
|
||||
- Performance issues (that's CONCERNS.md)
|
||||
|
||||
**When filling this template:**
|
||||
- Check .env.example or .env.template for required env vars
|
||||
- Look for SDK imports (stripe, @sendgrid/mail, etc.)
|
||||
- Check for webhook handlers in routes/endpoints
|
||||
- Note where secrets are managed (not the secrets)
|
||||
- Document environment-specific differences (dev/staging/prod)
|
||||
- Include auth patterns for each service
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Adding new external service integrations
|
||||
- Debugging authentication issues
|
||||
- Understanding data flow outside the application
|
||||
- Setting up new environments
|
||||
- Auditing third-party dependencies
|
||||
- Planning for service outages or migrations
|
||||
|
||||
**Security note:**
|
||||
Document WHERE secrets live (env vars, Vercel dashboard, 1Password), never WHAT the secrets are.
|
||||
</guidelines>
|
||||
186
gsd-core/templates/codebase/stack.md
Normal file
186
gsd-core/templates/codebase/stack.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# Technology Stack Template
|
||||
|
||||
Template for `.planning/codebase/STACK.md` - captures the technology foundation.
|
||||
|
||||
**Purpose:** Document what technologies run this codebase. Focused on "what executes when you run the code."
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Technology Stack
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Languages
|
||||
|
||||
**Primary:**
|
||||
- [Language] [Version] - [Where used: e.g., "all application code"]
|
||||
|
||||
**Secondary:**
|
||||
- [Language] [Version] - [Where used: e.g., "build scripts, tooling"]
|
||||
|
||||
## Runtime
|
||||
|
||||
**Environment:**
|
||||
- [Runtime] [Version] - [e.g., "Node.js 20.x"]
|
||||
- [Additional requirements if any]
|
||||
|
||||
**Package Manager:**
|
||||
- [Manager] [Version] - [e.g., "npm 10.x"]
|
||||
- Lockfile: [e.g., "package-lock.json present"]
|
||||
|
||||
## Frameworks
|
||||
|
||||
**Core:**
|
||||
- [Framework] [Version] - [Purpose: e.g., "web server", "UI framework"]
|
||||
|
||||
**Testing:**
|
||||
- [Framework] [Version] - [e.g., "Jest for unit tests"]
|
||||
- [Framework] [Version] - [e.g., "Playwright for E2E"]
|
||||
|
||||
**Build/Dev:**
|
||||
- [Tool] [Version] - [e.g., "Vite for bundling"]
|
||||
- [Tool] [Version] - [e.g., "TypeScript compiler"]
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
[Only include dependencies critical to understanding the stack - limit to 5-10 most important]
|
||||
|
||||
**Critical:**
|
||||
- [Package] [Version] - [Why it matters: e.g., "authentication", "database access"]
|
||||
- [Package] [Version] - [Why it matters]
|
||||
|
||||
**Infrastructure:**
|
||||
- [Package] [Version] - [e.g., "Express for HTTP routing"]
|
||||
- [Package] [Version] - [e.g., "PostgreSQL client"]
|
||||
|
||||
## Configuration
|
||||
|
||||
**Environment:**
|
||||
- [How configured: e.g., ".env files", "environment variables"]
|
||||
- [Key configs: e.g., "DATABASE_URL, API_KEY required"]
|
||||
|
||||
**Build:**
|
||||
- [Build config files: e.g., "vite.config.ts, tsconfig.json"]
|
||||
|
||||
## Platform Requirements
|
||||
|
||||
**Development:**
|
||||
- [OS requirements or "any platform"]
|
||||
- [Additional tooling: e.g., "Docker for local DB"]
|
||||
|
||||
**Production:**
|
||||
- [Deployment target: e.g., "Vercel", "AWS Lambda", "Docker container"]
|
||||
- [Version requirements]
|
||||
|
||||
---
|
||||
|
||||
*Stack analysis: [date]*
|
||||
*Update after major dependency changes*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Technology Stack
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Languages
|
||||
|
||||
**Primary:**
|
||||
- TypeScript 5.3 - All application code
|
||||
|
||||
**Secondary:**
|
||||
- JavaScript - Build scripts, config files
|
||||
|
||||
## Runtime
|
||||
|
||||
**Environment:**
|
||||
- Node.js 20.x (LTS)
|
||||
- No browser runtime (CLI tool only)
|
||||
|
||||
**Package Manager:**
|
||||
- npm 10.x
|
||||
- Lockfile: `package-lock.json` present
|
||||
|
||||
## Frameworks
|
||||
|
||||
**Core:**
|
||||
- None (vanilla Node.js CLI)
|
||||
|
||||
**Testing:**
|
||||
- Vitest 1.0 - Unit tests
|
||||
- tsx - TypeScript execution without build step
|
||||
|
||||
**Build/Dev:**
|
||||
- TypeScript 5.3 - Compilation to JavaScript
|
||||
- esbuild - Used by Vitest for fast transforms
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
**Critical:**
|
||||
- commander 11.x - CLI argument parsing and command structure
|
||||
- chalk 5.x - Terminal output styling
|
||||
- fs-extra 11.x - Extended file system operations
|
||||
|
||||
**Infrastructure:**
|
||||
- Node.js built-ins - fs, path, child_process for file operations
|
||||
|
||||
## Configuration
|
||||
|
||||
**Environment:**
|
||||
- No environment variables required
|
||||
- Configuration via CLI flags only
|
||||
|
||||
**Build:**
|
||||
- `tsconfig.json` - TypeScript compiler options
|
||||
- `vitest.config.ts` - Test runner configuration
|
||||
|
||||
## Platform Requirements
|
||||
|
||||
**Development:**
|
||||
- macOS/Linux/Windows (any platform with Node.js)
|
||||
- No external dependencies
|
||||
|
||||
**Production:**
|
||||
- Distributed as npm package
|
||||
- Installed globally via npm install -g
|
||||
- Runs on user's Node.js installation
|
||||
|
||||
---
|
||||
|
||||
*Stack analysis: 2025-01-20*
|
||||
*Update after major dependency changes*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in STACK.md:**
|
||||
- Languages and versions
|
||||
- Runtime requirements (Node, Bun, Deno, browser)
|
||||
- Package manager and lockfile
|
||||
- Framework choices
|
||||
- Critical dependencies (limit to 5-10 most important)
|
||||
- Build tooling
|
||||
- Platform/deployment requirements
|
||||
|
||||
**What does NOT belong here:**
|
||||
- File structure (that's STRUCTURE.md)
|
||||
- Architectural patterns (that's ARCHITECTURE.md)
|
||||
- Every dependency in package.json (only critical ones)
|
||||
- Implementation details (defer to code)
|
||||
|
||||
**When filling this template:**
|
||||
- Check package.json for dependencies
|
||||
- Note runtime version from .nvmrc or package.json engines
|
||||
- Include only dependencies that affect understanding (not every utility)
|
||||
- Specify versions only when version matters (breaking changes, compatibility)
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Adding new dependencies (check compatibility)
|
||||
- Upgrading frameworks (know what's in use)
|
||||
- Choosing implementation approach (must work with existing stack)
|
||||
- Understanding build requirements
|
||||
</guidelines>
|
||||
285
gsd-core/templates/codebase/structure.md
Normal file
285
gsd-core/templates/codebase/structure.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Structure Template
|
||||
|
||||
Template for `.planning/codebase/STRUCTURE.md` - captures physical file organization.
|
||||
|
||||
**Purpose:** Document where things physically live in the codebase. Answers "where do I put X?"
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Codebase Structure
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Directory Layout
|
||||
|
||||
[ASCII box-drawing tree of top-level directories with purpose - use ├── └── │ characters for tree structure only]
|
||||
|
||||
```
|
||||
[project-root]/
|
||||
├── [dir]/ # [Purpose]
|
||||
├── [dir]/ # [Purpose]
|
||||
├── [dir]/ # [Purpose]
|
||||
└── [file] # [Purpose]
|
||||
```
|
||||
|
||||
## Directory Purposes
|
||||
|
||||
**[Directory Name]:**
|
||||
- Purpose: [What lives here]
|
||||
- Contains: [Types of files: e.g., "*.ts source files", "component directories"]
|
||||
- Key files: [Important files in this directory]
|
||||
- Subdirectories: [If nested, describe structure]
|
||||
|
||||
**[Directory Name]:**
|
||||
- Purpose: [What lives here]
|
||||
- Contains: [Types of files]
|
||||
- Key files: [Important files]
|
||||
- Subdirectories: [Structure]
|
||||
|
||||
## Key File Locations
|
||||
|
||||
**Entry Points:**
|
||||
- [Path]: [Purpose: e.g., "CLI entry point"]
|
||||
- [Path]: [Purpose: e.g., "Server startup"]
|
||||
|
||||
**Configuration:**
|
||||
- [Path]: [Purpose: e.g., "TypeScript config"]
|
||||
- [Path]: [Purpose: e.g., "Build configuration"]
|
||||
- [Path]: [Purpose: e.g., "Environment variables"]
|
||||
|
||||
**Core Logic:**
|
||||
- [Path]: [Purpose: e.g., "Business services"]
|
||||
- [Path]: [Purpose: e.g., "Database models"]
|
||||
- [Path]: [Purpose: e.g., "API routes"]
|
||||
|
||||
**Testing:**
|
||||
- [Path]: [Purpose: e.g., "Unit tests"]
|
||||
- [Path]: [Purpose: e.g., "Test fixtures"]
|
||||
|
||||
**Documentation:**
|
||||
- [Path]: [Purpose: e.g., "User-facing docs"]
|
||||
- [Path]: [Purpose: e.g., "Developer guide"]
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
**Files:**
|
||||
- [Pattern]: [Example: e.g., "kebab-case.ts for modules"]
|
||||
- [Pattern]: [Example: e.g., "PascalCase.tsx for React components"]
|
||||
- [Pattern]: [Example: e.g., "*.test.ts for test files"]
|
||||
|
||||
**Directories:**
|
||||
- [Pattern]: [Example: e.g., "kebab-case for feature directories"]
|
||||
- [Pattern]: [Example: e.g., "plural names for collections"]
|
||||
|
||||
**Special Patterns:**
|
||||
- [Pattern]: [Example: e.g., "index.ts for directory exports"]
|
||||
- [Pattern]: [Example: e.g., "__tests__ for test directories"]
|
||||
|
||||
## Where to Add New Code
|
||||
|
||||
**New Feature:**
|
||||
- Primary code: [Directory path]
|
||||
- Tests: [Directory path]
|
||||
- Config if needed: [Directory path]
|
||||
|
||||
**New Component/Module:**
|
||||
- Implementation: [Directory path]
|
||||
- Types: [Directory path]
|
||||
- Tests: [Directory path]
|
||||
|
||||
**New Route/Command:**
|
||||
- Definition: [Directory path]
|
||||
- Handler: [Directory path]
|
||||
- Tests: [Directory path]
|
||||
|
||||
**Utilities:**
|
||||
- Shared helpers: [Directory path]
|
||||
- Type definitions: [Directory path]
|
||||
|
||||
## Special Directories
|
||||
|
||||
[Any directories with special meaning or generation]
|
||||
|
||||
**[Directory]:**
|
||||
- Purpose: [e.g., "Generated code", "Build output"]
|
||||
- Source: [e.g., "Auto-generated by X", "Build artifacts"]
|
||||
- Committed: [Yes/No - in .gitignore?]
|
||||
|
||||
---
|
||||
|
||||
*Structure analysis: [date]*
|
||||
*Update when directory structure changes*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Codebase Structure
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
gsd-core/
|
||||
├── bin/ # Executable entry points
|
||||
├── commands/ # Slash command definitions
|
||||
│ └── gsd/ # GSD-specific commands
|
||||
├── gsd-core/ # Skill resources
|
||||
│ ├── references/ # Principle documents
|
||||
│ ├── templates/ # File templates
|
||||
│ └── workflows/ # Multi-step procedures
|
||||
├── src/ # Source code (if applicable)
|
||||
├── tests/ # Test files
|
||||
├── package.json # Project manifest
|
||||
└── README.md # User documentation
|
||||
```
|
||||
|
||||
## Directory Purposes
|
||||
|
||||
**bin/**
|
||||
- Purpose: CLI entry points
|
||||
- Contains: install.js (installer script)
|
||||
- Key files: install.js - handles npx installation
|
||||
- Subdirectories: None
|
||||
|
||||
**commands/gsd/**
|
||||
- Purpose: Slash command definitions for Claude Code
|
||||
- Contains: *.md files (one per command)
|
||||
- Key files: new-project.md, plan-phase.md, execute-plan.md
|
||||
- Subdirectories: None (flat structure)
|
||||
|
||||
**gsd-core/references/**
|
||||
- Purpose: Core philosophy and guidance documents
|
||||
- Contains: principles.md, questioning.md, plan-format.md
|
||||
- Key files: principles.md - system philosophy
|
||||
- Subdirectories: None
|
||||
|
||||
**gsd-core/templates/**
|
||||
- Purpose: Document templates for .planning/ files
|
||||
- Contains: Template definitions with frontmatter
|
||||
- Key files: project.md, roadmap.md, plan.md, summary.md
|
||||
- Subdirectories: codebase/ (new - for stack/architecture/structure templates)
|
||||
|
||||
**gsd-core/workflows/**
|
||||
- Purpose: Reusable multi-step procedures
|
||||
- Contains: Workflow definitions called by commands
|
||||
- Key files: execute-plan.md, research-phase.md
|
||||
- Subdirectories: None
|
||||
|
||||
## Key File Locations
|
||||
|
||||
**Entry Points:**
|
||||
- `bin/install.js` - Installation script (npx entry)
|
||||
|
||||
**Configuration:**
|
||||
- `package.json` - Project metadata, dependencies, bin entry
|
||||
- `.gitignore` - Excluded files
|
||||
|
||||
**Core Logic:**
|
||||
- `bin/install.js` - All installation logic (file copying, path replacement)
|
||||
|
||||
**Testing:**
|
||||
- `tests/` - Test files (if present)
|
||||
|
||||
**Documentation:**
|
||||
- `README.md` - User-facing installation and usage guide
|
||||
- `CLAUDE.md` - Instructions for Claude Code when working in this repo
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
**Files:**
|
||||
- kebab-case.md: Markdown documents
|
||||
- kebab-case.js: JavaScript source files
|
||||
- UPPERCASE.md: Important project files (README, CLAUDE, CHANGELOG)
|
||||
|
||||
**Directories:**
|
||||
- kebab-case: All directories
|
||||
- Plural for collections: templates/, commands/, workflows/
|
||||
|
||||
**Special Patterns:**
|
||||
- {command-name}.md: Slash command definition
|
||||
- *-template.md: Could be used but templates/ directory preferred
|
||||
|
||||
## Where to Add New Code
|
||||
|
||||
**New Slash Command:**
|
||||
- Primary code: `commands/gsd/{command-name}.md`
|
||||
- Tests: `tests/commands/{command-name}.test.js` (if testing implemented)
|
||||
- Documentation: Update `README.md` with new command
|
||||
|
||||
**New Template:**
|
||||
- Implementation: `gsd-core/templates/{name}.md`
|
||||
- Documentation: Template is self-documenting (includes guidelines)
|
||||
|
||||
**New Workflow:**
|
||||
- Implementation: `gsd-core/workflows/{name}.md`
|
||||
- Usage: Reference from command with `@~/.claude/gsd-core/workflows/{name}.md`
|
||||
|
||||
**New Reference Document:**
|
||||
- Implementation: `gsd-core/references/{name}.md`
|
||||
- Usage: Reference from commands/workflows as needed
|
||||
|
||||
**Utilities:**
|
||||
- No utilities yet (`install.js` is monolithic)
|
||||
- If extracted: `src/utils/`
|
||||
|
||||
## Special Directories
|
||||
|
||||
**gsd-core/**
|
||||
- Purpose: Resources installed to ~/.claude/
|
||||
- Source: Copied by bin/install.js during installation
|
||||
- Committed: Yes (source of truth)
|
||||
|
||||
**commands/**
|
||||
- Purpose: Slash commands installed to ~/.claude/commands/
|
||||
- Source: Copied by bin/install.js during installation
|
||||
- Committed: Yes (source of truth)
|
||||
|
||||
---
|
||||
|
||||
*Structure analysis: 2025-01-20*
|
||||
*Update when directory structure changes*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in STRUCTURE.md:**
|
||||
- Directory layout (ASCII box-drawing tree for structure visualization)
|
||||
- Purpose of each directory
|
||||
- Key file locations (entry points, configs, core logic)
|
||||
- Naming conventions
|
||||
- Where to add new code (by type)
|
||||
- Special/generated directories
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Conceptual architecture (that's ARCHITECTURE.md)
|
||||
- Technology stack (that's STACK.md)
|
||||
- Code implementation details (defer to code reading)
|
||||
- Every single file (focus on directories and key files)
|
||||
|
||||
**When filling this template:**
|
||||
- Use `tree -L 2` or similar to visualize structure
|
||||
- Identify top-level directories and their purposes
|
||||
- Note naming patterns by observing existing files
|
||||
- Locate entry points, configs, and main logic areas
|
||||
- Keep directory tree concise (max 2-3 levels)
|
||||
|
||||
**Tree format (ASCII box-drawing characters for structure only):**
|
||||
```
|
||||
root/
|
||||
├── dir1/ # Purpose
|
||||
│ ├── subdir/ # Purpose
|
||||
│ └── file.ts # Purpose
|
||||
├── dir2/ # Purpose
|
||||
└── file.ts # Purpose
|
||||
```
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Adding new features (where should files go?)
|
||||
- Understanding project organization
|
||||
- Finding where specific logic lives
|
||||
- Following existing conventions
|
||||
</guidelines>
|
||||
480
gsd-core/templates/codebase/testing.md
Normal file
480
gsd-core/templates/codebase/testing.md
Normal file
@@ -0,0 +1,480 @@
|
||||
# Testing Patterns Template
|
||||
|
||||
Template for `.planning/codebase/TESTING.md` - captures test framework and patterns.
|
||||
|
||||
**Purpose:** Document how tests are written and run. Guide for adding tests that match existing patterns.
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Testing Patterns
|
||||
|
||||
**Analysis Date:** [YYYY-MM-DD]
|
||||
|
||||
## Test Framework
|
||||
|
||||
**Runner:**
|
||||
- [Framework: e.g., "Jest 29.x", "Vitest 1.x"]
|
||||
- [Config: e.g., "jest.config.js in project root"]
|
||||
|
||||
**Assertion Library:**
|
||||
- [Library: e.g., "built-in expect", "chai"]
|
||||
- [Matchers: e.g., "toBe, toEqual, toThrow"]
|
||||
|
||||
**Run Commands:**
|
||||
```bash
|
||||
[e.g., "npm test" or "npm run test"] # Run all tests
|
||||
[e.g., "npm test -- --watch"] # Watch mode
|
||||
[e.g., "npm test -- path/to/file.test.ts"] # Single file
|
||||
[e.g., "npm run test:coverage"] # Coverage report
|
||||
```
|
||||
|
||||
## Test File Organization
|
||||
|
||||
**Location:**
|
||||
- [Pattern: e.g., "*.test.ts alongside source files"]
|
||||
- [Alternative: e.g., "__tests__/ directory" or "separate tests/ tree"]
|
||||
|
||||
**Naming:**
|
||||
- [Unit tests: e.g., "module-name.test.ts"]
|
||||
- [Integration: e.g., "feature-name.integration.test.ts"]
|
||||
- [E2E: e.g., "user-flow.e2e.test.ts"]
|
||||
|
||||
**Structure:**
|
||||
```
|
||||
[Show actual directory pattern, e.g.:
|
||||
src/
|
||||
lib/
|
||||
utils.ts
|
||||
utils.test.ts
|
||||
services/
|
||||
user-service.ts
|
||||
user-service.test.ts
|
||||
]
|
||||
```
|
||||
|
||||
## Test Structure
|
||||
|
||||
**Suite Organization:**
|
||||
```typescript
|
||||
[Show actual pattern used, e.g.:
|
||||
|
||||
describe('ModuleName', () => {
|
||||
describe('functionName', () => {
|
||||
it('should handle success case', () => {
|
||||
// arrange
|
||||
// act
|
||||
// assert
|
||||
});
|
||||
|
||||
it('should handle error case', () => {
|
||||
// test code
|
||||
});
|
||||
});
|
||||
});
|
||||
]
|
||||
```
|
||||
|
||||
**Patterns:**
|
||||
- [Setup: e.g., "beforeEach for shared setup, avoid beforeAll"]
|
||||
- [Teardown: e.g., "afterEach to clean up, restore mocks"]
|
||||
- [Structure: e.g., "arrange/act/assert pattern required"]
|
||||
|
||||
## Mocking
|
||||
|
||||
**Framework:**
|
||||
- [Tool: e.g., "Jest built-in mocking", "Vitest vi", "Sinon"]
|
||||
- [Import mocking: e.g., "vi.mock() at top of file"]
|
||||
|
||||
**Patterns:**
|
||||
```typescript
|
||||
[Show actual mocking pattern, e.g.:
|
||||
|
||||
// Mock external dependency
|
||||
vi.mock('./external-service', () => ({
|
||||
fetchData: vi.fn()
|
||||
}));
|
||||
|
||||
// Mock in test
|
||||
const mockFetch = vi.mocked(fetchData);
|
||||
mockFetch.mockResolvedValue({ data: 'test' });
|
||||
]
|
||||
```
|
||||
|
||||
**What to Mock:**
|
||||
- [e.g., "External APIs, file system, database"]
|
||||
- [e.g., "Time/dates (use vi.useFakeTimers)"]
|
||||
- [e.g., "Network calls (use mock fetch)"]
|
||||
|
||||
**What NOT to Mock:**
|
||||
- [e.g., "Pure functions, utilities"]
|
||||
- [e.g., "Internal business logic"]
|
||||
|
||||
## Fixtures and Factories
|
||||
|
||||
**Test Data:**
|
||||
```typescript
|
||||
[Show pattern for creating test data, e.g.:
|
||||
|
||||
// Factory pattern
|
||||
function createTestUser(overrides?: Partial<User>): User {
|
||||
return {
|
||||
id: 'test-id',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
// Fixture file
|
||||
// tests/fixtures/users.ts
|
||||
export const mockUsers = [/* ... */];
|
||||
]
|
||||
```
|
||||
|
||||
**Location:**
|
||||
- [e.g., "tests/fixtures/ for shared fixtures"]
|
||||
- [e.g., "factory functions in test file or tests/factories/"]
|
||||
|
||||
## Coverage
|
||||
|
||||
**Requirements:**
|
||||
- [Target: e.g., "80% line coverage", "no specific target"]
|
||||
- [Enforcement: e.g., "CI blocks <80%", "coverage for awareness only"]
|
||||
|
||||
**Configuration:**
|
||||
- [Tool: e.g., "built-in coverage via --coverage flag"]
|
||||
- [Exclusions: e.g., "exclude *.test.ts, config files"]
|
||||
|
||||
**View Coverage:**
|
||||
```bash
|
||||
[e.g., "npm run test:coverage"]
|
||||
[e.g., "open coverage/index.html"]
|
||||
```
|
||||
|
||||
## Test Types
|
||||
|
||||
**Unit Tests:**
|
||||
- [Scope: e.g., "test single function/class in isolation"]
|
||||
- [Mocking: e.g., "mock all external dependencies"]
|
||||
- [Speed: e.g., "must run in <1s per test"]
|
||||
|
||||
**Integration Tests:**
|
||||
- [Scope: e.g., "test multiple modules together"]
|
||||
- [Mocking: e.g., "mock external services, use real internal modules"]
|
||||
- [Setup: e.g., "use test database, seed data"]
|
||||
|
||||
**E2E Tests:**
|
||||
- [Framework: e.g., "Playwright for E2E"]
|
||||
- [Scope: e.g., "test full user flows"]
|
||||
- [Location: e.g., "e2e/ directory separate from unit tests"]
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Async Testing:**
|
||||
```typescript
|
||||
[Show pattern, e.g.:
|
||||
|
||||
it('should handle async operation', async () => {
|
||||
const result = await asyncFunction();
|
||||
expect(result).toBe('expected');
|
||||
});
|
||||
]
|
||||
```
|
||||
|
||||
**Error Testing:**
|
||||
```typescript
|
||||
[Show pattern, e.g.:
|
||||
|
||||
it('should throw on invalid input', () => {
|
||||
expect(() => functionCall()).toThrow('error message');
|
||||
});
|
||||
|
||||
// Async error
|
||||
it('should reject on failure', async () => {
|
||||
await expect(asyncCall()).rejects.toThrow('error message');
|
||||
});
|
||||
]
|
||||
```
|
||||
|
||||
**Snapshot Testing:**
|
||||
- [Usage: e.g., "for React components only" or "not used"]
|
||||
- [Location: e.g., "__snapshots__/ directory"]
|
||||
|
||||
---
|
||||
|
||||
*Testing analysis: [date]*
|
||||
*Update when test patterns change*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
```markdown
|
||||
# Testing Patterns
|
||||
|
||||
**Analysis Date:** 2025-01-20
|
||||
|
||||
## Test Framework
|
||||
|
||||
**Runner:**
|
||||
- Vitest 1.0.4
|
||||
- Config: vitest.config.ts in project root
|
||||
|
||||
**Assertion Library:**
|
||||
- Vitest built-in expect
|
||||
- Matchers: toBe, toEqual, toThrow, toMatchObject
|
||||
|
||||
**Run Commands:**
|
||||
```bash
|
||||
npm test # Run all tests
|
||||
npm test -- --watch # Watch mode
|
||||
npm test -- path/to/file.test.ts # Single file
|
||||
npm run test:coverage # Coverage report
|
||||
```
|
||||
|
||||
## Test File Organization
|
||||
|
||||
**Location:**
|
||||
- *.test.ts alongside source files
|
||||
- No separate tests/ directory
|
||||
|
||||
**Naming:**
|
||||
- unit-name.test.ts for all tests
|
||||
- No distinction between unit/integration in filename
|
||||
|
||||
**Structure:**
|
||||
```
|
||||
src/
|
||||
lib/
|
||||
parser.ts
|
||||
parser.test.ts
|
||||
services/
|
||||
install-service.ts
|
||||
install-service.test.ts
|
||||
bin/
|
||||
install.ts
|
||||
(no test - integration tested via CLI)
|
||||
```
|
||||
|
||||
## Test Structure
|
||||
|
||||
**Suite Organization:**
|
||||
```typescript
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
|
||||
describe('ModuleName', () => {
|
||||
describe('functionName', () => {
|
||||
beforeEach(() => {
|
||||
// reset state
|
||||
});
|
||||
|
||||
it('should handle valid input', () => {
|
||||
// arrange
|
||||
const input = createTestInput();
|
||||
|
||||
// act
|
||||
const result = functionName(input);
|
||||
|
||||
// assert
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should throw on invalid input', () => {
|
||||
expect(() => functionName(null)).toThrow('Invalid input');
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Patterns:**
|
||||
- Use beforeEach for per-test setup, avoid beforeAll
|
||||
- Use afterEach to restore mocks: vi.restoreAllMocks()
|
||||
- Explicit arrange/act/assert comments in complex tests
|
||||
- One assertion focus per test (but multiple expects OK)
|
||||
|
||||
## Mocking
|
||||
|
||||
**Framework:**
|
||||
- Vitest built-in mocking (vi)
|
||||
- Module mocking via vi.mock() at top of test file
|
||||
|
||||
**Patterns:**
|
||||
```typescript
|
||||
import { vi } from 'vitest';
|
||||
import { externalFunction } from './external';
|
||||
|
||||
// Mock module
|
||||
vi.mock('./external', () => ({
|
||||
externalFunction: vi.fn()
|
||||
}));
|
||||
|
||||
describe('test suite', () => {
|
||||
it('mocks function', () => {
|
||||
const mockFn = vi.mocked(externalFunction);
|
||||
mockFn.mockReturnValue('mocked result');
|
||||
|
||||
// test code using mocked function
|
||||
|
||||
expect(mockFn).toHaveBeenCalledWith('expected arg');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**What to Mock:**
|
||||
- File system operations (fs-extra)
|
||||
- Child process execution (child_process.exec)
|
||||
- External API calls
|
||||
- Environment variables (process.env)
|
||||
|
||||
**What NOT to Mock:**
|
||||
- Internal pure functions
|
||||
- Simple utilities (string manipulation, array helpers)
|
||||
- TypeScript types
|
||||
|
||||
## Fixtures and Factories
|
||||
|
||||
**Test Data:**
|
||||
```typescript
|
||||
// Factory functions in test file
|
||||
function createTestConfig(overrides?: Partial<Config>): Config {
|
||||
return {
|
||||
targetDir: '/tmp/test',
|
||||
global: false,
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
// Shared fixtures in tests/fixtures/
|
||||
// tests/fixtures/sample-command.md
|
||||
export const sampleCommand = `---
|
||||
description: Test command
|
||||
---
|
||||
Content here`;
|
||||
```
|
||||
|
||||
**Location:**
|
||||
- Factory functions: define in test file near usage
|
||||
- Shared fixtures: tests/fixtures/ (for multi-file test data)
|
||||
- Mock data: inline in test when simple, factory when complex
|
||||
|
||||
## Coverage
|
||||
|
||||
**Requirements:**
|
||||
- No enforced coverage target
|
||||
- Coverage tracked for awareness
|
||||
- Focus on critical paths (parsers, service logic)
|
||||
|
||||
**Configuration:**
|
||||
- Vitest coverage via c8 (built-in)
|
||||
- Excludes: *.test.ts, bin/install.ts, config files
|
||||
|
||||
**View Coverage:**
|
||||
```bash
|
||||
npm run test:coverage
|
||||
open coverage/index.html
|
||||
```
|
||||
|
||||
## Test Types
|
||||
|
||||
**Unit Tests:**
|
||||
- Test single function in isolation
|
||||
- Mock all external dependencies (fs, child_process)
|
||||
- Fast: each test <100ms
|
||||
- Examples: parser.test.ts, validator.test.ts
|
||||
|
||||
**Integration Tests:**
|
||||
- Test multiple modules together
|
||||
- Mock only external boundaries (file system, process)
|
||||
- Examples: install-service.test.ts (tests service + parser)
|
||||
|
||||
**E2E Tests:**
|
||||
- Not currently used
|
||||
- CLI integration tested manually
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Async Testing:**
|
||||
```typescript
|
||||
it('should handle async operation', async () => {
|
||||
const result = await asyncFunction();
|
||||
expect(result).toBe('expected');
|
||||
});
|
||||
```
|
||||
|
||||
**Error Testing:**
|
||||
```typescript
|
||||
it('should throw on invalid input', () => {
|
||||
expect(() => parse(null)).toThrow('Cannot parse null');
|
||||
});
|
||||
|
||||
// Async error
|
||||
it('should reject on file not found', async () => {
|
||||
await expect(readConfig('invalid.txt')).rejects.toThrow('ENOENT');
|
||||
});
|
||||
```
|
||||
|
||||
**File System Mocking:**
|
||||
```typescript
|
||||
import { vi } from 'vitest';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
vi.mock('fs-extra');
|
||||
|
||||
it('mocks file system', () => {
|
||||
vi.mocked(fs.readFile).mockResolvedValue('file content');
|
||||
// test code
|
||||
});
|
||||
```
|
||||
|
||||
**Snapshot Testing:**
|
||||
- Not used in this codebase
|
||||
- Prefer explicit assertions for clarity
|
||||
|
||||
---
|
||||
|
||||
*Testing analysis: 2025-01-20*
|
||||
*Update when test patterns change*
|
||||
```
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**What belongs in TESTING.md:**
|
||||
- Test framework and runner configuration
|
||||
- Test file location and naming patterns
|
||||
- Test structure (describe/it, beforeEach patterns)
|
||||
- Mocking approach and examples
|
||||
- Fixture/factory patterns
|
||||
- Coverage requirements
|
||||
- How to run tests (commands)
|
||||
- Common testing patterns in actual code
|
||||
|
||||
**What does NOT belong here:**
|
||||
- Specific test cases (defer to actual test files)
|
||||
- Technology choices (that's STACK.md)
|
||||
- CI/CD setup (that's deployment docs)
|
||||
|
||||
**When filling this template:**
|
||||
- Check package.json scripts for test commands
|
||||
- Find test config file (jest.config.js, vitest.config.ts)
|
||||
- Read 3-5 existing test files to identify patterns
|
||||
- Look for test utilities in tests/ or test-utils/
|
||||
- Check for coverage configuration
|
||||
- Document actual patterns used, not ideal patterns
|
||||
|
||||
**Useful for phase planning when:**
|
||||
- Adding new features (write matching tests)
|
||||
- Refactoring (maintain test patterns)
|
||||
- Fixing bugs (add regression tests)
|
||||
- Understanding verification approach
|
||||
- Setting up test infrastructure
|
||||
|
||||
**Analysis approach:**
|
||||
- Check package.json for test framework and scripts
|
||||
- Read test config file for coverage, setup
|
||||
- Examine test file organization (collocated vs separate)
|
||||
- Review 5 test files for patterns (mocking, structure, assertions)
|
||||
- Look for test utilities, fixtures, factories
|
||||
- Note any test types (unit, integration, e2e)
|
||||
- Document commands for running tests
|
||||
</guidelines>
|
||||
62
gsd-core/templates/config.json
Normal file
62
gsd-core/templates/config.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"mode": "interactive",
|
||||
"granularity": "standard",
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"auto_advance": false,
|
||||
"nyquist_validation": true,
|
||||
"security_enforcement": true,
|
||||
"security_asvs_level": 1,
|
||||
"security_block_on": "high",
|
||||
"discuss_mode": "discuss",
|
||||
"research_before_questions": false,
|
||||
"code_review_command": null,
|
||||
"plan_bounce": false,
|
||||
"plan_bounce_script": null,
|
||||
"plan_bounce_passes": 2,
|
||||
"cross_ai_execution": false,
|
||||
"cross_ai_command": "",
|
||||
"cross_ai_timeout": 300
|
||||
},
|
||||
"ship": {
|
||||
"pr_body_sections": []
|
||||
},
|
||||
"planning": {
|
||||
"commit_docs": true,
|
||||
"search_gitignored": false,
|
||||
"sub_repos": []
|
||||
},
|
||||
"git": {
|
||||
"create_tag": true
|
||||
},
|
||||
"parallelization": {
|
||||
"enabled": true,
|
||||
"plan_level": true,
|
||||
"task_level": false,
|
||||
"skip_checkpoints": true,
|
||||
"max_concurrent_agents": 3,
|
||||
"min_plans_for_parallel": 2
|
||||
},
|
||||
"gates": {
|
||||
"confirm_project": true,
|
||||
"confirm_phases": true,
|
||||
"confirm_roadmap": true,
|
||||
"confirm_breakdown": true,
|
||||
"confirm_plan": true,
|
||||
"execute_next_plan": true,
|
||||
"issues_review": true,
|
||||
"confirm_transition": true
|
||||
},
|
||||
"safety": {
|
||||
"always_confirm_destructive": true,
|
||||
"always_confirm_external_services": true
|
||||
},
|
||||
"hooks": {
|
||||
"context_warnings": true
|
||||
},
|
||||
"project_code": null,
|
||||
"agent_skills": {},
|
||||
"claude_md_path": "./CLAUDE.md"
|
||||
}
|
||||
352
gsd-core/templates/context.md
Normal file
352
gsd-core/templates/context.md
Normal file
@@ -0,0 +1,352 @@
|
||||
# Phase Context Template
|
||||
|
||||
Template for `.planning/phases/XX-name/{phase_num}-CONTEXT.md` - captures implementation decisions for a phase.
|
||||
|
||||
**Purpose:** Document decisions that downstream agents need. Researcher uses this to know WHAT to investigate. Planner uses this to know WHAT choices are locked vs flexible.
|
||||
|
||||
**Key principle:** Categories are NOT predefined. They emerge from what was actually discussed for THIS phase. A CLI phase has CLI-relevant sections, a UI phase has UI-relevant sections.
|
||||
|
||||
**Downstream consumers:**
|
||||
- `gsd-phase-researcher` — Reads decisions to focus research (e.g., "card layout" → research card component patterns)
|
||||
- `gsd-planner` — Reads decisions to create specific tasks (e.g., "infinite scroll" → task includes virtualization)
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
# Phase [X]: [Name] - Context
|
||||
|
||||
**Gathered:** [date]
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
[Clear statement of what this phase delivers — the scope anchor. This comes from ROADMAP.md and is fixed. Discussion clarifies implementation within this boundary.]
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### [Area 1 that was discussed]
|
||||
- **D-01:** [Specific decision made]
|
||||
- **D-02:** [Another decision if applicable]
|
||||
|
||||
### [Area 2 that was discussed]
|
||||
- **D-03:** [Specific decision made]
|
||||
|
||||
### [Area 3 that was discussed]
|
||||
- **D-04:** [Specific decision made]
|
||||
|
||||
### Claude's Discretion
|
||||
[Areas where user explicitly said "you decide" — Claude has flexibility here during planning/implementation]
|
||||
|
||||
</decisions>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
[Any particular references, examples, or "I want it like X" moments from discussion. Product references, specific behaviors, interaction patterns.]
|
||||
|
||||
[If none: "No specific requirements — open to standard approaches"]
|
||||
|
||||
</specifics>
|
||||
|
||||
<canonical_refs>
|
||||
## Canonical References
|
||||
|
||||
**Downstream agents MUST read these before planning or implementing.**
|
||||
|
||||
[List every spec, ADR, feature doc, or design doc that defines requirements or constraints for this phase. Use full relative paths so agents can read them directly. Group by topic area when the phase has multiple concerns.]
|
||||
|
||||
### [Topic area 1]
|
||||
- `path/to/spec-or-adr.md` — [What this doc decides/defines that's relevant]
|
||||
- `path/to/doc.md` §N — [Specific section and what it covers]
|
||||
|
||||
### [Topic area 2]
|
||||
- `path/to/feature-doc.md` — [What capability this defines]
|
||||
|
||||
[If the project has no external specs: "No external specs — requirements are fully captured in decisions above"]
|
||||
|
||||
</canonical_refs>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- [Component/hook/utility]: [How it could be used in this phase]
|
||||
|
||||
### Established Patterns
|
||||
- [Pattern]: [How it constrains/enables this phase]
|
||||
|
||||
### Integration Points
|
||||
- [Where new code connects to existing system]
|
||||
|
||||
</code_context>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
[Ideas that came up during discussion but belong in other phases. Captured here so they're not lost, but explicitly out of scope for this phase.]
|
||||
|
||||
[If none: "None — discussion stayed within phase scope"]
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: XX-name*
|
||||
*Context gathered: [date]*
|
||||
```
|
||||
|
||||
<good_examples>
|
||||
|
||||
**Example 1: Visual feature (Post Feed)**
|
||||
|
||||
```markdown
|
||||
# Phase 3: Post Feed - Context
|
||||
|
||||
**Gathered:** 2025-01-20
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Display posts from followed users in a scrollable feed. Users can view posts and see engagement counts. Creating posts and interactions are separate phases.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Layout style
|
||||
- Card-based layout, not timeline or list
|
||||
- Each card shows: author avatar, name, timestamp, full post content, reaction counts
|
||||
- Cards have subtle shadows, rounded corners — modern feel
|
||||
|
||||
### Loading behavior
|
||||
- Infinite scroll, not pagination
|
||||
- Pull-to-refresh on mobile
|
||||
- New posts indicator at top ("3 new posts") rather than auto-inserting
|
||||
|
||||
### Empty state
|
||||
- Friendly illustration + "Follow people to see posts here"
|
||||
- Suggest 3-5 accounts to follow based on interests
|
||||
|
||||
### Claude's Discretion
|
||||
- Loading skeleton design
|
||||
- Exact spacing and typography
|
||||
- Error state handling
|
||||
|
||||
</decisions>
|
||||
|
||||
<canonical_refs>
|
||||
## Canonical References
|
||||
|
||||
### Feed display
|
||||
- `docs/features/social-feed.md` — Feed requirements, post card fields, engagement display rules
|
||||
- `docs/decisions/adr-012-infinite-scroll.md` — Scroll strategy decision, virtualization requirements
|
||||
|
||||
### Empty states
|
||||
- `docs/design/empty-states.md` — Empty state patterns, illustration guidelines
|
||||
|
||||
</canonical_refs>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- "I like how Twitter shows the new posts indicator without disrupting your scroll position"
|
||||
- Cards should feel like Linear's issue cards — clean, not cluttered
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- Commenting on posts — Phase 5
|
||||
- Bookmarking posts — add to backlog
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 03-post-feed*
|
||||
*Context gathered: 2025-01-20*
|
||||
```
|
||||
|
||||
**Example 2: CLI tool (Database backup)**
|
||||
|
||||
```markdown
|
||||
# Phase 2: Backup Command - Context
|
||||
|
||||
**Gathered:** 2025-01-20
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
CLI command to backup database to local file or S3. Supports full and incremental backups. Restore command is a separate phase.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Output format
|
||||
- JSON for programmatic use, table format for humans
|
||||
- Default to table, --json flag for JSON
|
||||
- Verbose mode (-v) shows progress, silent by default
|
||||
|
||||
### Flag design
|
||||
- Short flags for common options: -o (output), -v (verbose), -f (force)
|
||||
- Long flags for clarity: --incremental, --compress, --encrypt
|
||||
- Required: database connection string (positional or --db)
|
||||
|
||||
### Error recovery
|
||||
- Retry 3 times on network failure, then fail with clear message
|
||||
- --no-retry flag to fail fast
|
||||
- Partial backups are deleted on failure (no corrupt files)
|
||||
|
||||
### Claude's Discretion
|
||||
- Exact progress bar implementation
|
||||
- Compression algorithm choice
|
||||
- Temp file handling
|
||||
|
||||
</decisions>
|
||||
|
||||
<canonical_refs>
|
||||
## Canonical References
|
||||
|
||||
### Backup CLI
|
||||
- `docs/features/backup-restore.md` — Backup requirements, supported backends, encryption spec
|
||||
- `docs/decisions/adr-007-cli-conventions.md` — Flag naming, exit codes, output format standards
|
||||
|
||||
</canonical_refs>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- "I want it to feel like pg_dump — familiar to database people"
|
||||
- Should work in CI pipelines (exit codes, no interactive prompts)
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- Scheduled backups — separate phase
|
||||
- Backup rotation/retention — add to backlog
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 02-backup-command*
|
||||
*Context gathered: 2025-01-20*
|
||||
```
|
||||
|
||||
**Example 3: Organization task (Photo library)**
|
||||
|
||||
```markdown
|
||||
# Phase 1: Photo Organization - Context
|
||||
|
||||
**Gathered:** 2025-01-20
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Organize existing photo library into structured folders. Handle duplicates and apply consistent naming. Tagging and search are separate phases.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Grouping criteria
|
||||
- Primary grouping by year, then by month
|
||||
- Events detected by time clustering (photos within 2 hours = same event)
|
||||
- Event folders named by date + location if available
|
||||
|
||||
### Duplicate handling
|
||||
- Keep highest resolution version
|
||||
- Move duplicates to _duplicates folder (don't delete)
|
||||
- Log all duplicate decisions for review
|
||||
|
||||
### Naming convention
|
||||
- Format: YYYY-MM-DD_HH-MM-SS_originalname.ext
|
||||
- Preserve original filename as suffix for searchability
|
||||
- Handle name collisions with incrementing suffix
|
||||
|
||||
### Claude's Discretion
|
||||
- Exact clustering algorithm
|
||||
- How to handle photos with no EXIF data
|
||||
- Folder emoji usage
|
||||
|
||||
</decisions>
|
||||
|
||||
<canonical_refs>
|
||||
## Canonical References
|
||||
|
||||
### Organization rules
|
||||
- `docs/features/photo-organization.md` — Grouping rules, duplicate policy, naming spec
|
||||
- `docs/decisions/adr-003-exif-handling.md` — EXIF extraction strategy, fallback for missing metadata
|
||||
|
||||
</canonical_refs>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- "I want to be able to find photos by roughly when they were taken"
|
||||
- Don't delete anything — worst case, move to a review folder
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- Face detection grouping — future phase
|
||||
- Cloud sync — out of scope for now
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 01-photo-organization*
|
||||
*Context gathered: 2025-01-20*
|
||||
```
|
||||
|
||||
</good_examples>
|
||||
|
||||
<guidelines>
|
||||
**This template captures DECISIONS for downstream agents.**
|
||||
|
||||
The output should answer: "What does the researcher need to investigate? What choices are locked for the planner?"
|
||||
|
||||
**Good content (concrete decisions):**
|
||||
- "Card-based layout, not timeline"
|
||||
- "Retry 3 times on network failure, then fail"
|
||||
- "Group by year, then by month"
|
||||
- "JSON for programmatic use, table for humans"
|
||||
|
||||
**Bad content (too vague):**
|
||||
- "Should feel modern and clean"
|
||||
- "Good user experience"
|
||||
- "Fast and responsive"
|
||||
- "Easy to use"
|
||||
|
||||
**After creation:**
|
||||
- File lives in phase directory: `.planning/phases/XX-name/{phase_num}-CONTEXT.md`
|
||||
- `gsd-phase-researcher` uses decisions to focus investigation AND reads canonical_refs to know WHAT docs to study
|
||||
- `gsd-planner` uses decisions + research to create executable tasks AND reads canonical_refs to verify alignment
|
||||
- Downstream agents should NOT need to ask the user again about captured decisions
|
||||
|
||||
**CRITICAL — Canonical references:**
|
||||
- The `<canonical_refs>` section is MANDATORY. Every CONTEXT.md must have one.
|
||||
- If your project has external specs, ADRs, or design docs, list them with full relative paths grouped by topic
|
||||
- If ROADMAP.md lists `Canonical refs:` per phase, extract and expand those
|
||||
- Inline mentions like "see ADR-019" scattered in decisions are useless to downstream agents — they need full paths and section references in a dedicated section they can find
|
||||
- If no external specs exist, say so explicitly — don't silently omit the section
|
||||
</guidelines>
|
||||
78
gsd-core/templates/continue-here.md
Normal file
78
gsd-core/templates/continue-here.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Continue-Here Template
|
||||
|
||||
Copy and fill this structure for `.planning/phases/XX-name/.continue-here.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
phase: XX-name
|
||||
task: 3
|
||||
total_tasks: 7
|
||||
status: in_progress
|
||||
last_updated: 2025-01-15T14:30:00Z
|
||||
---
|
||||
```
|
||||
|
||||
```markdown
|
||||
<current_state>
|
||||
[Where exactly are we? What's the immediate context?]
|
||||
</current_state>
|
||||
|
||||
<completed_work>
|
||||
[What got done this session - be specific]
|
||||
|
||||
- Task 1: [name] - Done
|
||||
- Task 2: [name] - Done
|
||||
- Task 3: [name] - In progress, [what's done on it]
|
||||
</completed_work>
|
||||
|
||||
<remaining_work>
|
||||
[What's left in this phase]
|
||||
|
||||
- Task 3: [name] - [what's left to do]
|
||||
- Task 4: [name] - Not started
|
||||
- Task 5: [name] - Not started
|
||||
</remaining_work>
|
||||
|
||||
<decisions_made>
|
||||
[Key decisions and why - so next session doesn't re-debate]
|
||||
|
||||
- Decided to use [X] because [reason]
|
||||
- Chose [approach] over [alternative] because [reason]
|
||||
</decisions_made>
|
||||
|
||||
<blockers>
|
||||
[Anything stuck or waiting on external factors]
|
||||
|
||||
- [Blocker 1]: [status/workaround]
|
||||
</blockers>
|
||||
|
||||
<context>
|
||||
[Mental state, "vibe", anything that helps resume smoothly]
|
||||
|
||||
[What were you thinking about? What was the plan?
|
||||
This is the "pick up exactly where you left off" context.]
|
||||
</context>
|
||||
|
||||
<next_action>
|
||||
[The very first thing to do when resuming]
|
||||
|
||||
Start with: [specific action]
|
||||
</next_action>
|
||||
```
|
||||
|
||||
<yaml_fields>
|
||||
Required YAML frontmatter:
|
||||
|
||||
- `phase`: Directory name (e.g., `02-authentication`)
|
||||
- `task`: Current task number
|
||||
- `total_tasks`: How many tasks in phase
|
||||
- `status`: `in_progress`, `blocked`, `almost_done`
|
||||
- `last_updated`: ISO timestamp
|
||||
</yaml_fields>
|
||||
|
||||
<guidelines>
|
||||
- Be specific enough that a fresh Claude instance understands immediately
|
||||
- Include WHY decisions were made, not just what
|
||||
- The `<next_action>` should be actionable without reading anything else
|
||||
- This file gets DELETED after resume - it's not permanent storage
|
||||
</guidelines>
|
||||
7
gsd-core/templates/copilot-instructions.md
Normal file
7
gsd-core/templates/copilot-instructions.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Instructions for GSD
|
||||
|
||||
- Use the gsd-core skill when the user asks for GSD or uses a `gsd-*` command.
|
||||
- Treat `/gsd-...` or `gsd-...` as command invocations and load the matching file from `.github/skills/gsd-*`.
|
||||
- When a command says to spawn a subagent, prefer a matching custom agent from `.github/agents`.
|
||||
- Do not apply GSD workflows unless the user explicitly asks for them.
|
||||
- After completing any `gsd-*` command (or any deliverable it triggers: feature, bug fix, tests, docs, etc.), ALWAYS: (1) offer the user the next step by prompting via `ask_user`; repeat this feedback loop until the user explicitly indicates they are done.
|
||||
91
gsd-core/templates/debug-subagent-prompt.md
Normal file
91
gsd-core/templates/debug-subagent-prompt.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Debug Subagent Prompt Template
|
||||
|
||||
Template for spawning gsd-debugger agent. The agent contains all debugging expertise - this template provides problem context only.
|
||||
|
||||
---
|
||||
|
||||
## Template
|
||||
|
||||
```markdown
|
||||
<objective>
|
||||
Investigate issue: {issue_id}
|
||||
|
||||
**Summary:** {issue_summary}
|
||||
</objective>
|
||||
|
||||
<symptoms>
|
||||
expected: {expected}
|
||||
actual: {actual}
|
||||
errors: {errors}
|
||||
reproduction: {reproduction}
|
||||
timeline: {timeline}
|
||||
</symptoms>
|
||||
|
||||
<mode>
|
||||
symptoms_prefilled: {true_or_false}
|
||||
goal: {find_root_cause_only | find_and_fix}
|
||||
</mode>
|
||||
|
||||
<debug_file>
|
||||
Create: .planning/debug/{slug}.md
|
||||
</debug_file>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Placeholders
|
||||
|
||||
| Placeholder | Source | Example |
|
||||
|-------------|--------|---------|
|
||||
| `{issue_id}` | Orchestrator-assigned | `auth-screen-dark` |
|
||||
| `{issue_summary}` | User description | `Auth screen is too dark` |
|
||||
| `{expected}` | From symptoms | `See logo clearly` |
|
||||
| `{actual}` | From symptoms | `Screen is dark` |
|
||||
| `{errors}` | From symptoms | `None in console` |
|
||||
| `{reproduction}` | From symptoms | `Open /auth page` |
|
||||
| `{timeline}` | From symptoms | `After recent deploy` |
|
||||
| `{goal}` | Orchestrator sets | `find_and_fix` |
|
||||
| `{slug}` | Generated | `auth-screen-dark` |
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
**From /gsd:debug:**
|
||||
```python
|
||||
Task(
|
||||
prompt=filled_template,
|
||||
subagent_type="gsd-debugger",
|
||||
description="Debug {slug}"
|
||||
)
|
||||
```
|
||||
|
||||
**From diagnose-issues (UAT):**
|
||||
```python
|
||||
Task(prompt=template, subagent_type="gsd-debugger", description="Debug UAT-001")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Continuation
|
||||
|
||||
For checkpoints, spawn fresh agent with:
|
||||
|
||||
```markdown
|
||||
<objective>
|
||||
Continue debugging {slug}. Evidence is in the debug file.
|
||||
</objective>
|
||||
|
||||
<prior_state>
|
||||
Debug file: @.planning/debug/{slug}.md
|
||||
</prior_state>
|
||||
|
||||
<checkpoint_response>
|
||||
**Type:** {checkpoint_type}
|
||||
**Response:** {user_response}
|
||||
</checkpoint_response>
|
||||
|
||||
<mode>
|
||||
goal: {goal}
|
||||
</mode>
|
||||
```
|
||||
21
gsd-core/templates/dev-preferences.md
Normal file
21
gsd-core/templates/dev-preferences.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
description: Load developer preferences into this session
|
||||
---
|
||||
|
||||
# Developer Preferences
|
||||
|
||||
> Generated by GSD on {{generated_at}} from {{data_source}}.
|
||||
> Run `/gsd:profile-user --refresh` to regenerate.
|
||||
|
||||
## Behavioral Directives
|
||||
|
||||
Follow these directives when working with this developer. Higher confidence
|
||||
directives should be applied directly. Lower confidence directives should be
|
||||
tried with hedging ("Based on your profile, I'll try X -- let me know if
|
||||
that's off").
|
||||
|
||||
{{behavioral_directives}}
|
||||
|
||||
## Stack Preferences
|
||||
|
||||
{{stack_preferences}}
|
||||
146
gsd-core/templates/discovery.md
Normal file
146
gsd-core/templates/discovery.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Discovery Template
|
||||
|
||||
Template for `.planning/phases/XX-name/DISCOVERY.md` - shallow research for library/option decisions.
|
||||
|
||||
**Purpose:** Answer "which library/option should we use" questions during mandatory discovery in plan-phase.
|
||||
|
||||
For deep ecosystem research ("how do experts build this"), use `/gsd:plan-phase --research-phase` which produces RESEARCH.md.
|
||||
|
||||
---
|
||||
|
||||
## File Template
|
||||
|
||||
```markdown
|
||||
---
|
||||
phase: XX-name
|
||||
type: discovery
|
||||
topic: [discovery-topic]
|
||||
---
|
||||
|
||||
<session_initialization>
|
||||
Before beginning discovery, verify today's date:
|
||||
!`date +%Y-%m-%d`
|
||||
|
||||
Use this date when searching for "current" or "latest" information.
|
||||
Example: If today is 2025-11-22, search for "2025" not "2024".
|
||||
</session_initialization>
|
||||
|
||||
<discovery_objective>
|
||||
Discover [topic] to inform [phase name] implementation.
|
||||
|
||||
Purpose: [What decision/implementation this enables]
|
||||
Scope: [Boundaries]
|
||||
Output: DISCOVERY.md with recommendation
|
||||
</discovery_objective>
|
||||
|
||||
<discovery_scope>
|
||||
<include>
|
||||
- [Question to answer]
|
||||
- [Area to investigate]
|
||||
- [Specific comparison if needed]
|
||||
</include>
|
||||
|
||||
<exclude>
|
||||
- [Out of scope for this discovery]
|
||||
- [Defer to implementation phase]
|
||||
</exclude>
|
||||
</discovery_scope>
|
||||
|
||||
<discovery_protocol>
|
||||
|
||||
**Source Priority:**
|
||||
1. **Context7 MCP** - For library/framework documentation (current, authoritative)
|
||||
2. **Official Docs** - For platform-specific or non-indexed libraries
|
||||
3. **WebSearch** - For comparisons, trends, community patterns (verify all findings)
|
||||
|
||||
**Quality Checklist:**
|
||||
Before completing discovery, verify:
|
||||
- [ ] All claims have authoritative sources (Context7 or official docs)
|
||||
- [ ] Negative claims ("X is not possible") verified with official documentation
|
||||
- [ ] API syntax/configuration from Context7 or official docs (never WebSearch alone)
|
||||
- [ ] WebSearch findings cross-checked with authoritative sources
|
||||
- [ ] Recent updates/changelogs checked for breaking changes
|
||||
- [ ] Alternative approaches considered (not just first solution found)
|
||||
|
||||
**Confidence Levels:**
|
||||
- HIGH: Context7 or official docs confirm
|
||||
- MEDIUM: WebSearch + Context7/official docs confirm
|
||||
- LOW: WebSearch only or training knowledge only (mark for validation)
|
||||
|
||||
</discovery_protocol>
|
||||
|
||||
|
||||
<output_structure>
|
||||
Create `.planning/phases/XX-name/DISCOVERY.md`:
|
||||
|
||||
```markdown
|
||||
# [Topic] Discovery
|
||||
|
||||
## Summary
|
||||
[2-3 paragraph executive summary - what was researched, what was found, what's recommended]
|
||||
|
||||
## Primary Recommendation
|
||||
[What to do and why - be specific and actionable]
|
||||
|
||||
## Alternatives Considered
|
||||
[What else was evaluated and why not chosen]
|
||||
|
||||
## Key Findings
|
||||
|
||||
### [Category 1]
|
||||
- [Finding with source URL and relevance to our case]
|
||||
|
||||
### [Category 2]
|
||||
- [Finding with source URL and relevance]
|
||||
|
||||
## Code Examples
|
||||
[Relevant implementation patterns, if applicable]
|
||||
|
||||
## Metadata
|
||||
|
||||
<metadata>
|
||||
<confidence level="high|medium|low">
|
||||
[Why this confidence level - based on source quality and verification]
|
||||
</confidence>
|
||||
|
||||
<sources>
|
||||
- [Primary authoritative sources used]
|
||||
</sources>
|
||||
|
||||
<open_questions>
|
||||
[What couldn't be determined or needs validation during implementation]
|
||||
</open_questions>
|
||||
|
||||
<validation_checkpoints>
|
||||
[If confidence is LOW or MEDIUM, list specific things to verify during implementation]
|
||||
</validation_checkpoints>
|
||||
</metadata>
|
||||
```
|
||||
</output_structure>
|
||||
|
||||
<success_criteria>
|
||||
- All scope questions answered with authoritative sources
|
||||
- Quality checklist items completed
|
||||
- Clear primary recommendation
|
||||
- Low-confidence findings marked with validation checkpoints
|
||||
- Ready to inform PLAN.md creation
|
||||
</success_criteria>
|
||||
|
||||
<guidelines>
|
||||
**When to use discovery:**
|
||||
- Technology choice unclear (library A vs B)
|
||||
- Best practices needed for unfamiliar integration
|
||||
- API/library investigation required
|
||||
- Single decision pending
|
||||
|
||||
**When NOT to use:**
|
||||
- Established patterns (CRUD, auth with known library)
|
||||
- Implementation details (defer to execution)
|
||||
- Questions answerable from existing project context
|
||||
|
||||
**When to use RESEARCH.md instead:**
|
||||
- Niche/complex domains (3D, games, audio, shaders)
|
||||
- Need ecosystem knowledge, not just library choice
|
||||
- "How do experts build this" questions
|
||||
- Use `/gsd:plan-phase --research-phase` for these
|
||||
</guidelines>
|
||||
63
gsd-core/templates/discussion-log.md
Normal file
63
gsd-core/templates/discussion-log.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Discussion Log Template
|
||||
|
||||
Template for `.planning/phases/XX-name/{phase_num}-DISCUSSION-LOG.md` — audit trail of discuss-phase Q&A sessions.
|
||||
|
||||
**Purpose:** Software audit trail for decision-making. Captures all options considered, not just the selected one. Separate from CONTEXT.md which is the implementation artifact consumed by downstream agents.
|
||||
|
||||
**NOT for LLM consumption.** This file should never be referenced in `<files_to_read>` blocks or agent prompts.
|
||||
|
||||
## Format
|
||||
|
||||
```markdown
|
||||
# Phase [X]: [Name] - Discussion Log
|
||||
|
||||
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||
|
||||
**Date:** [ISO date]
|
||||
**Phase:** [phase number]-[phase name]
|
||||
**Areas discussed:** [comma-separated list]
|
||||
|
||||
---
|
||||
|
||||
## [Area 1 Name]
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| [Option 1] | [Brief description] | |
|
||||
| [Option 2] | [Brief description] | ✓ |
|
||||
| [Option 3] | [Brief description] | |
|
||||
|
||||
**User's choice:** [Selected option or verbatim free-text response]
|
||||
**Notes:** [Any clarifications or rationale provided during discussion]
|
||||
|
||||
---
|
||||
|
||||
## [Area 2 Name]
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
## Claude's Discretion
|
||||
|
||||
[Areas delegated to Claude's judgment — list what was deferred and why]
|
||||
|
||||
## Deferred Ideas
|
||||
|
||||
[Ideas mentioned but not in scope for this phase]
|
||||
|
||||
---
|
||||
|
||||
*Phase: XX-name*
|
||||
*Discussion log generated: [date]*
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
- Generated automatically at end of every discuss-phase session
|
||||
- Includes ALL options considered, not just the selected one
|
||||
- Includes user's freeform notes and clarifications
|
||||
- Clearly marked as audit-only, not an implementation artifact
|
||||
- Does NOT interfere with CONTEXT.md generation or downstream agent behavior
|
||||
- Committed alongside CONTEXT.md in the same git commit
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user