diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f1c6975..d3f1087 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,9 +4,7 @@ ## Required Checks - [ ] `npm run quality:contracts` -- [ ] `npm run docs:contracts` - [ ] `npm run architecture:contracts` -- [ ] `npm run entropy:check` - [ ] `npm run test:policy` - [ ] `npm test` - [ ] `npm run build` diff --git a/.github/workflows/quality-gates.yml b/.github/workflows/quality-gates.yml index 6036eb4..90bdf28 100644 --- a/.github/workflows/quality-gates.yml +++ b/.github/workflows/quality-gates.yml @@ -20,9 +20,7 @@ jobs: - run: npm ci - run: npm run quality:contracts - - run: npm run docs:contracts - run: npm run architecture:contracts - - run: npm run entropy:check - run: npm run test:policy - run: npm run test - run: npm run build diff --git a/.github/workflows/repo-gc.yml b/.github/workflows/repo-gc.yml deleted file mode 100644 index df8802c..0000000 --- a/.github/workflows/repo-gc.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Repo GC - -on: - schedule: - - cron: "0 14 * * 1" - workflow_dispatch: - -jobs: - gc: - name: Entropy + Docs Freshness - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: npm - - - run: npm ci - - run: npm run docs:contracts - - run: npm run entropy:check diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index eea66ee..684b262 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -28,8 +28,6 @@ Owner: Platform ## Enforced Gates - Contracts: `npm run quality:contracts`. -- Docs contracts: `npm run docs:contracts`. - Architecture contracts: `npm run architecture:contracts`. -- Entropy check: `npm run entropy:check`. - Policy tests: `npm run test:policy`. - Browser smoke: `npm run test:browser`. diff --git a/README.md b/README.md index ac5e779..e7b0368 100644 --- a/README.md +++ b/README.md @@ -200,9 +200,7 @@ src/ ## Harness Enforcement -- Docs contracts: `npm run docs:contracts` - Architecture contracts: `npm run architecture:contracts` -- Entropy guard: `npm run entropy:check` - Browser smoke validation: `npm run test:browser` - Autonomous iteration loop: `npm run iterate:autonomous` diff --git a/docs/QUALITY_SCORE.md b/docs/QUALITY_SCORE.md index ea908d2..7396e08 100644 --- a/docs/QUALITY_SCORE.md +++ b/docs/QUALITY_SCORE.md @@ -5,9 +5,7 @@ Owner: Platform ## Current Quality Domains - Contracts: `quality:contracts` -- Docs and knowledge base: `docs:contracts` - Architecture boundaries: `architecture:contracts` -- Entropy and drift: `entropy:check` - Product scoring policy: `test:policy` - Browser-visible behavior: `test:browser` diff --git a/docs/quality/GOLDEN_PRINCIPLES.md b/docs/quality/GOLDEN_PRINCIPLES.md index ca00c18..f29ec80 100644 --- a/docs/quality/GOLDEN_PRINCIPLES.md +++ b/docs/quality/GOLDEN_PRINCIPLES.md @@ -12,6 +12,4 @@ Owner: Platform - Favor fast, repeatable, automated checks over manual review. ## Garbage Collection Loop -- Run `npm run entropy:check` before merge windows. -- Run scheduled cleanup scan weekly via workflow. -- Track and burn down TODO/FIXME debt from script output. +- Track and burn down TODO/FIXME debt during routine reviews. diff --git a/docs/references/HARNESS_LEARNINGS_CHECKLIST.md b/docs/references/HARNESS_LEARNINGS_CHECKLIST.md index 29601b7..202d88f 100644 --- a/docs/references/HARNESS_LEARNINGS_CHECKLIST.md +++ b/docs/references/HARNESS_LEARNINGS_CHECKLIST.md @@ -14,7 +14,6 @@ Applied: Applied: - Root docs index and section indexes: `docs/INDEX.md`, `docs/*/INDEX.md`. - Core canonical docs: `docs/DESIGN.md`, `docs/FRONTEND.md`, `docs/PLANS.md`, `docs/PRODUCT_SENSE.md`, `docs/QUALITY_SCORE.md`, `docs/RELIABILITY.md`, `docs/SECURITY.md`. -- Contract enforcement: `scripts/docs-contract-check.mjs`. ## 3) Encode architecture as rigid, explicit constraints Applied: @@ -52,13 +51,11 @@ Applied: ## 9) Make quality checks mechanical and non-optional Applied: - Quality workflow: `.github/workflows/quality-gates.yml`. -- Required checks: contracts + docs + architecture + entropy + policy + tests + build + browser smoke. +- Required checks: contracts + architecture + policy + tests + build + browser smoke. ## 10) Treat entropy reduction as continuous garbage collection Applied: - Golden principles: `docs/quality/GOLDEN_PRINCIPLES.md`. -- Entropy scanner: `scripts/entropy-check.mjs`. -- Scheduled cleanup workflow: `.github/workflows/repo-gc.yml`. ## 11) Convert human review insights into reusable mechanisms Applied: diff --git a/docs/references/SCRIPT_CATALOG.md b/docs/references/SCRIPT_CATALOG.md index 8f2993b..2920300 100644 --- a/docs/references/SCRIPT_CATALOG.md +++ b/docs/references/SCRIPT_CATALOG.md @@ -13,7 +13,7 @@ Classify script entrypoints by operational role so one-off tooling does not mix - `scripts/scan-telemetry-report.mjs`: scan telemetry reporting. - `scripts/fixup-maps.mjs`: post-merge/map integrity normalization. - `scripts/populate-bfs.mjs`, `scripts/enrich-loop.mjs`, `scripts/enrich-agents.mjs`, `scripts/enrich-v4.mjs`: map enrichment population flows. -- `scripts/quality-contract-check.mjs`, `scripts/docs-contract-check.mjs`, `scripts/architecture-contract-check.mjs`, `scripts/entropy-check.mjs`, `scripts/browser-smoke.mjs`: CI/quality gates. +- `scripts/quality-contract-check.mjs`, `scripts/architecture-contract-check.mjs`, `scripts/browser-smoke.mjs`: CI/quality gates. ## Structured maintenance (keep, infrequent) - `scripts/migrations/`: one-time or low-frequency data migrations/backfills. diff --git a/package.json b/package.json index 348f4a3..10ebd7f 100644 --- a/package.json +++ b/package.json @@ -1 +1 @@ -{"name":"recon","version":"0.1.0","private":true,"scripts":{"dev":"next dev","build":"next build","start":"next start","lint":"next lint","test":"vitest run","test:watch":"vitest","test:policy":"vitest run src/lib/readiness-policy.test.ts src/lib/readiness-score.test.ts","quality:contracts":"node scripts/quality-contract-check.mjs","lane:start":"scripts/lane-start.sh","lane:stop":"scripts/lane-stop.sh","lane:status":"scripts/lane-status.sh","telemetry:report":"node scripts/scan-telemetry-report.mjs","iterate:autonomous":"node scripts/agent-iteration-loop.mjs","scan-jobs:health":"node scripts/scan-job-health.mjs","scan-jobs:reap":"node scripts/scan-job-reaper.mjs","throttle:health":"node scripts/redis-throttle-health.mjs","throttle:reset":"node scripts/redis-throttle-reset.mjs","optimize:loop":"node scripts/optimizer/run-product-loop.mjs","docs:contracts":"node scripts/docs-contract-check.mjs","architecture:contracts":"node scripts/architecture-contract-check.mjs","entropy:check":"node scripts/entropy-check.mjs","test:browser":"node scripts/browser-smoke.mjs","import:sources":"node scripts/import/ingest-sources.mjs","import:quality":"node scripts/import/quality-check.mjs","import:merge":"node scripts/import/merge-into-maps.mjs","import:verify-map":"node scripts/import/reverify-existing.mjs","migrate:postgres":"node scripts/migrate-file-storage-to-postgres.mjs","gemini:login":"node scripts/gemini-login.mjs","deep-research:login":"node scripts/deep-research-login.mjs","ideas:generate":"node idea-space-pipeline/cli.mjs --seen idea-space-pipeline/examples/seen-tuples.json --limit 20","ideas:export-tasks":"node idea-space-pipeline/export-tasks.mjs","ideas:retrain":"node idea-space-pipeline/retrain.mjs --lookback-hours 72 --limit 2000","ideas:observe":"node idea-space-pipeline/observe.mjs"},"dependencies":{"@anthropic-ai/sdk":"^0.39.0","@google/generative-ai":"^0.24.1","@opentelemetry/api":"^1.9.0","@opentelemetry/exporter-trace-otlp-http":"^0.212.0","@opentelemetry/sdk-trace-base":"^2.5.1","@opentelemetry/sdk-trace-node":"^2.5.1","@sentry/nextjs":"^10.40.0","autoprefixer":"^10.4.24","class-variance-authority":"^0.7.1","clsx":"^2.1.1","jsonrepair":"^3.13.2","lucide-react":"^0.469.0","next":"^15.1.0","pg":"^8.18.0","puppeteer":"^24.37.3","react":"^19.0.0","react-dom":"^19.0.0","react-markdown":"^10.1.0","recharts":"^3.7.0","redis":"^4.7.1","remark-gfm":"^4.0.1","tailwind-merge":"^2.6.0"},"devDependencies":{"@playwright/test":"^1.51.1","@types/node":"^22.0.0","@types/pg":"^8.16.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0","eslint":"^9.0.0","eslint-config-next":"^15.1.0","playwright":"^1.58.2","postcss":"^8.5.6","tailwindcss":"^3.4.19","typescript":"^5.0.0","vitest":"^4.0.18"}} \ No newline at end of file +{"name":"recon","version":"0.1.0","private":true,"scripts":{"dev":"next dev","build":"next build","start":"next start","lint":"next lint","test":"vitest run","test:watch":"vitest","test:policy":"vitest run src/lib/readiness-policy.test.ts src/lib/readiness-score.test.ts","quality:contracts":"node scripts/quality-contract-check.mjs","lane:start":"scripts/lane-start.sh","lane:stop":"scripts/lane-stop.sh","lane:status":"scripts/lane-status.sh","telemetry:report":"node scripts/scan-telemetry-report.mjs","iterate:autonomous":"node scripts/agent-iteration-loop.mjs","scan-jobs:health":"node scripts/scan-job-health.mjs","scan-jobs:reap":"node scripts/scan-job-reaper.mjs","throttle:health":"node scripts/redis-throttle-health.mjs","throttle:reset":"node scripts/redis-throttle-reset.mjs","optimize:loop":"node scripts/optimizer/run-product-loop.mjs","architecture:contracts":"node scripts/architecture-contract-check.mjs","test:browser":"node scripts/browser-smoke.mjs","import:sources":"node scripts/import/ingest-sources.mjs","import:quality":"node scripts/import/quality-check.mjs","import:merge":"node scripts/import/merge-into-maps.mjs","import:verify-map":"node scripts/import/reverify-existing.mjs","migrate:postgres":"node scripts/migrate-file-storage-to-postgres.mjs","gemini:login":"node scripts/gemini-login.mjs","deep-research:login":"node scripts/deep-research-login.mjs","ideas:generate":"node idea-space-pipeline/cli.mjs --seen idea-space-pipeline/examples/seen-tuples.json --limit 20","ideas:export-tasks":"node idea-space-pipeline/export-tasks.mjs","ideas:retrain":"node idea-space-pipeline/retrain.mjs --lookback-hours 72 --limit 2000","ideas:observe":"node idea-space-pipeline/observe.mjs"},"dependencies":{"@anthropic-ai/sdk":"^0.39.0","@google/generative-ai":"^0.24.1","@opentelemetry/api":"^1.9.0","@opentelemetry/exporter-trace-otlp-http":"^0.212.0","@opentelemetry/sdk-trace-base":"^2.5.1","@opentelemetry/sdk-trace-node":"^2.5.1","@sentry/nextjs":"^10.40.0","autoprefixer":"^10.4.24","class-variance-authority":"^0.7.1","clsx":"^2.1.1","jsonrepair":"^3.13.2","lucide-react":"^0.469.0","next":"^15.1.0","pg":"^8.18.0","puppeteer":"^24.37.3","react":"^19.0.0","react-dom":"^19.0.0","react-markdown":"^10.1.0","recharts":"^3.7.0","redis":"^4.7.1","remark-gfm":"^4.0.1","tailwind-merge":"^2.6.0"},"devDependencies":{"@playwright/test":"^1.51.1","@types/node":"^22.0.0","@types/pg":"^8.16.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0","eslint":"^9.0.0","eslint-config-next":"^15.1.0","playwright":"^1.58.2","postcss":"^8.5.6","tailwindcss":"^3.4.19","typescript":"^5.0.0","vitest":"^4.0.18"}} \ No newline at end of file diff --git a/scripts/agent-iteration-loop.mjs b/scripts/agent-iteration-loop.mjs index 4c36ec6..806a54c 100755 --- a/scripts/agent-iteration-loop.mjs +++ b/scripts/agent-iteration-loop.mjs @@ -20,9 +20,7 @@ async function oneCycle() { const checks = [ ['npm', ['run', 'quality:contracts']], - ['npm', ['run', 'docs:contracts']], ['npm', ['run', 'architecture:contracts']], - ['npm', ['run', 'entropy:check']], ['npm', ['run', 'test:policy']], ['npm', ['test']], ] diff --git a/scripts/docs-contract-check.mjs b/scripts/docs-contract-check.mjs deleted file mode 100755 index 7b48b62..0000000 --- a/scripts/docs-contract-check.mjs +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env node -import fs from "fs" -import path from "path" - -const root = process.cwd() -const requiredFiles = [ - "AGENTS.md", - "ARCHITECTURE.md", - "docs/INDEX.md", - "docs/DESIGN.md", - "docs/FRONTEND.md", - "docs/PLANS.md", - "docs/PRODUCT_SENSE.md", - "docs/QUALITY_SCORE.md", - "docs/RELIABILITY.md", - "docs/SECURITY.md", - "docs/design-docs/INDEX.md", - "docs/product-specs/INDEX.md", - "docs/exec-plans/INDEX.md", - "docs/quality/INDEX.md", - "docs/reliability/INDEX.md", - "docs/security/INDEX.md", - "docs/references/INDEX.md", - "docs/references/HARNESS_LEARNINGS_CHECKLIST.md", - "docs/references/PROVIDER_MODEL.md", - "docs/references/BROWSER_VALIDATION.md", - "docs/references/AUTONOMY.md", - "docs/references/MERGE_PHILOSOPHY.md", - "docs/references/ENGINEER_ROLE.md", -] - -let failures = 0 - -function fail(msg) { - console.error(msg) - failures += 1 -} - -for (const rel of requiredFiles) { - const full = path.join(root, rel) - if (!fs.existsSync(full)) fail(`MISSING: ${rel}`) -} - -function collectMd(dir) { - const out = [] - for (const name of fs.readdirSync(dir)) { - const full = path.join(dir, name) - const st = fs.statSync(full) - if (st.isDirectory()) out.push(...collectMd(full)) - else if (name.endsWith(".md")) out.push(full) - } - return out -} - -for (const file of [path.join(root, "AGENTS.md"), path.join(root, "ARCHITECTURE.md"), ...collectMd(path.join(root, "docs"))]) { - const text = fs.readFileSync(file, "utf8") - if (!/Last reviewed:\s*\d{4}-\d{2}-\d{2}/.test(text)) { - fail(`MISSING Last reviewed marker: ${path.relative(root, file)}`) - } - if (!/Owner:\s*[A-Za-z]/.test(text)) { - fail(`MISSING Owner marker: ${path.relative(root, file)}`) - } -} - -if (failures > 0) { - console.error(`docs-contract-check failed (${failures} issue(s))`) - process.exit(2) -} - -console.log("docs-contract-check passed") diff --git a/scripts/entropy-check.mjs b/scripts/entropy-check.mjs deleted file mode 100755 index 848713f..0000000 --- a/scripts/entropy-check.mjs +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env node -import fs from "fs" -import path from "path" - -const root = process.cwd() -const maxLoc = Number(process.env.ENTROPY_MAX_LOC || 1200) -const warnLoc = Number(process.env.ENTROPY_WARN_LOC || 1000) -const staleDocDays = Number(process.env.ENTROPY_DOC_STALE_DAYS || 45) -const now = Date.now() -let failures = 0 - -function fail(msg) { - console.error(msg) - failures += 1 -} - -function walk(dir, exts, out = []) { - for (const name of fs.readdirSync(dir)) { - if (name === "node_modules" || name === ".next" || name === ".git") continue - const full = path.join(dir, name) - const st = fs.statSync(full) - if (st.isDirectory()) walk(full, exts, out) - else if (exts.some((e) => name.endsWith(e))) out.push(full) - } - return out -} - -const codeFiles = walk(path.join(root, "src"), [".ts", ".tsx"]) -for (const file of codeFiles) { - const rel = path.relative(root, file) - const loc = fs.readFileSync(file, "utf8").split("\n").length - if (loc > warnLoc) { - console.warn(`ENTROPY_WARN: ${rel} has ${loc} LOC (> ${warnLoc})`) - } - if (loc > maxLoc) fail(`ENTROPY: ${rel} has ${loc} LOC (> ${maxLoc})`) -} - -const allFiles = walk(root, [".ts", ".tsx", ".js", ".mjs", ".md"]) -let todoCount = 0 -for (const file of allFiles) { - const rel = path.relative(root, file) - if (rel.startsWith(".next/") || rel.includes("package-lock.json")) continue - const text = fs.readFileSync(file, "utf8") - const matches = text.match(/\b(TODO|FIXME|HACK)\b/g) - if (matches) todoCount += matches.length -} -if (todoCount > 80) fail(`ENTROPY: TODO/FIXME/HACK count too high (${todoCount})`) - -const mdFiles = walk(path.join(root, "docs"), [".md"]) -for (const file of mdFiles) { - const text = fs.readFileSync(file, "utf8") - const m = text.match(/Last reviewed:\s*(\d{4}-\d{2}-\d{2})/) - if (!m) continue - const ageDays = (now - new Date(`${m[1]}T00:00:00Z`).getTime()) / (24 * 3600 * 1000) - if (ageDays > staleDocDays) { - fail(`ENTROPY: stale docs review marker in ${path.relative(root, file)} (${Math.floor(ageDays)} days old)`) - } -} - -if (failures > 0) { - console.error(`entropy-check failed (${failures} issue(s))`) - process.exit(2) -} -console.log("entropy-check passed") diff --git a/scripts/quality-contract-check.mjs b/scripts/quality-contract-check.mjs index 467920c..a371612 100755 --- a/scripts/quality-contract-check.mjs +++ b/scripts/quality-contract-check.mjs @@ -17,9 +17,7 @@ const requiredFiles = [ 'scripts/lane-start.sh', 'scripts/lane-stop.sh', 'scripts/lane-status.sh', - 'scripts/docs-contract-check.mjs', 'scripts/architecture-contract-check.mjs', - 'scripts/entropy-check.mjs', 'scripts/browser-smoke.mjs', ]