Skip to content

sdlc 1.0 audit — Phase 4 findings and recommended task list

State: open/active · Genre: analysis

Scope: Phase 4 of docs/planning/sdlc-1.0-plan.md — a read-only audit of solutions/ontological: grade every skill/CLI-op/config-key, code-review the whole tree against a fixed rubric, reconcile the 2026-07-19 simplification audit, and produce a recommended task list. 19 sub-agents produced the raw findings under .sdlc/runs/; this document synthesizes them.

Date: 2026-09-24 Worktree: /Users/sksizer/Developer/dev-sdlc-p4


solutions/ontological is in good shape for a codebase that has been through three completed migrations (Python→TypeScript, the apps/sdlc→solutions/ontological move, and the op-substrate cutover) without a dedicated sweep. Of the 99 findings across the 12 code-quality shards, 9 are blocking and 31 are major; every one of the 9 blocking findings and a 65% sample of the majors (20 of 31) were independently re-verified, and every one held up — 29 of 29 sampled blocking/major findings confirmed (100%), with one ancillary sub-claim (a duplication count inside an otherwise-sound finding) downgraded from “3x” to “2x” without changing the finding’s severity.

The dominant theme, recurring in nearly every shard, is stale comments outliving the code they describe: dead-doc-link error messages (python-runtime.md, never renamed to typescript-runtime.md), test-file headers still describing a plugin/ directory tree that was retired months ago, module docs still forwarding to migrate_entities.ts/validate_frontmatter.ts shims that no longer exist, READMEs listing files (cli/task_cli/index.ts, cli/task_cli/_common.ts) that were deleted, and a user-facing --help string that states the wrong exit code. None of these break anything today, but several are actively misleading (a misconfigured-lease-authority error points a real user at a nonexistent doc; backlog --help prints exit code 8 for a failure that actually exits 16).

The second theme is “single home” claims that are false. The July 2026 audit’s consolidation work landed cleanly in most places it touched, but new instances of the same duplication shape keep appearing: a hand-rolled ancestor-walk in lib/config/load.ts sits beside the very findAncestor helper that claims to be its “single home”; a misnamed local pyResolve in migrate-runtime-state silently implements the other, weaker pyResolve contract under the stronger one’s name; three call sites independently mint the ~19-field task-lease payload; and lib/util/yaml.ts’s “every caller” claim is false for six production files. The July audit’s own biggest miss — the dead lib/model/index.ts/corpus/index.ts barrels (PR1 item 6) — is still unfixed and remains the single largest unaddressed item from that audit.

Third, the surface audit found the codebase’s own execution model is ahead of its wiring in a few places: sdlc verify changes and pr survey/pr update are exactly the ops the 1.0 plan describes as core to the phase gate (“judge” and “merges” respectively), fully built and tested, but nothing dispatches them yet. Genuine dead/unused surface is otherwise rare: 0 of 41 skills and 0 of 47 config keys are a clean “remove,” and only one CLI op (quality.baseline.prune) is a true orphan.


The skills directory holds 41 skill subdirectories with a SKILL.md (plus README.md and CLAUDE.md, which are not skills) — the task brief assumed 43; the actual count, confirmed by directory listing, is 41.

Verdict counts: keep = 12, extras = 28, remove = 0, move-out-to-repo-scripts = 1 (41 total).

SkillCore loop?VerdictReason
setupYeskeepProject-bootstrap entry point of the loop.
find-verbsYeskeepSub-step of setup populating verbs.check/verbs.setup.
task-newYeskeepCreates the entities the loop executes.
task-defineYeskeepFills a task to the implementation-ready contract.
task-auto-defineYeskeepAutomated fallback inside the readiness gate.
task-ensure-readyYeskeepThe readiness gate at the head of every task-work run.
task-workYeskeepThe task-execution stage itself.
pr-checkYeskeepClassifies PR state for orchestrate’s dispatch.
pr-respondYeskeepThe PR-response stage of the loop.
task-close-outYeskeepThe close-out stage of the loop.
orchestrateYeskeepTies the whole loop together.
spawn-task-prYes (task-work Step 8)keepWired into task-work’s post-mortem follow-up flow.
milestone-newNoextrasOrganizes tasks into milestones; not an execution stage.
milestones-from-fileNoextrasOne-off bulk import from legacy planning docs.
milestone-reviewNoextrasNo wiring evidence either way; keep opt-in.
import-planningNoextrasOnboarding migration, occasional by design.
entities-auditNoextrasThe deterministic CLI op (not this skill) runs inside check.
entities-migrateNoextrasMechanical schema-drift fixer, run occasionally.
migrateNoextrasOne-time-per-upgrade sequencer.
migrate-runtime-stateNoextrasOne-time .claude/ to .sdlc/ mover.
docsNoextrasRegenerates docs artifacts; important but not a loop stage.
docs-sweepNoextrasLarge-scale comment sweep; occasional/audit use.
bug-finderNoextrasWhole-codebase bug sweep; occasional, heavyweight.
api-enhancement-scanNoextrasAPI-surface survey tool; occasional use.
explore-codebaseNoextrasGeneric exploration methodology; thin usage evidence.
capability-mapNoextrasActively dogfooded capability-graph authoring tool.
capability-reviewNoextrasCompanion verification pass to capability-map.
principle-reviewNoextrasGovernance review over principles; occasional.
standard-reviewNoextrasGovernance review over standards; occasional.
standard-newNoextrasEntity-authoring on-ramp for standards.
product-newNoextrasNo cross-references found; entity type exists, skill use unverified.
review-todosNoextrasTODO/FIXME triage; occasional maintenance.
session-cleanupNoextrasInteractive teardown tool; no wiring evidence either way.
project-cleanupNoextrasRepo-wide branch/worktree/task-linkage sweep; occasional.
consolidate-task-prsNoextrasExplicit, occasional cleanup for accumulated single-task PRs.
status-dashboardNoextrasThin dispatcher to the dashboard verb; convenience.
infoNoextrasDiagnostic self-verification tool (“which install won”).
backlog-captureNoextrasFast idea-capture front door; a parallel input path.
backlog-triageNoextrasPeriodic backlog promotion pass.
task-reviewNoextrasPeriodic task-health triage (task-work is the execution stage).
update-skill-docNomove-out-to-repo-scriptsRepo-specific: hardcodes solutions/ontological/skills/<slug>/SKILL.md; no downstream plugin consumer has skills to author at that path.

Verdict counts: keep ≈ 88 ops/groups, extras = 5, remove-or-wire-up = 1, move-out = 0 (revised from the original ≈ 85 to fold in roadmap.{check,create} and config.get-review-policy, three ops added to the module manifest after this table was first drafted, and to drop resolve-touchpoints from the task.{scan-placeholders,...} row below, retired the same way — net +2 rows).

Noun.op(s)VerdictReason
capability.{coverage,create,graph,preview-id,update}keepActively-used capability-mapping workflow.
reference.{create,preview-id}keepSmall, used, no issues.
standard.{create,preview-id,supersede,update}keepFull CRUD lifecycle actually exercised.
term.{create,preview-id}keepThin but used (glossary generation).
milestone.createkeepUsed by milestone-new / milestones-from-file / import-planning.
roadmap.{check,create}keepRoadmap authoring plus the roadmap↔milestone↔task cross-reference validator; mirrors milestone’s own create and entities.audit’s “load corpus, walk cross-references, report findings” shape.
backlog.{create,capture,update}keepUsed by backlog-capture / backlog-triage / review-todos.
backlog.preview-idkeepNo standalone call site (shares derivation with create); cheap to keep for interface consistency.
commit.createkeepLoad-bearing plumbing for the whole commit-message contract.
commit.get-schemakeepSmall, real, self-documenting introspection helper.
config.get-backlog-policykeepReal internal dependency of backlog create.
config.get-spawn-policykeepRead by task-work Step 8.
config.get-review-policykeepMirrors get-spawn-policy/get-backlog-policy: resolves orchestrator.review.command for /sdlc:orchestrate --only review’s Step 2a PR-review dispatch.
config.{get-verbs,set-verbs}keepUsed by find-verbs.
config.scaffoldkeepUsed by setup.
dashboard.{start,stop,list}extrasGenuinely used and general, but auxiliary to the loop; also carries the --help bug noted below.
dev.{history,install,link,off,status,use}keepLegitimate operator/dev tooling for developing the CLI itself; not loop-scoped by design.
docs.generatekeepCentral, CI/pre-commit-gated, heavily wired.
docs.build-subsiteskeepReal but niche; the mechanism is generic even though only this repo exercises it.
entities.auditkeepPart of task-work’s check gate.
entities.validatekeepHeaviest-used op in the group (51+ sites).
entities.migratekeepSchema-drift maintenance.
entities.check-identifierskeepClean general-op / repo-specific-activation split example.
entities.get-schemakeepIntrospection (“the schema IS the contract”).
gate.worktree-scopekeepCI-wired (lefthook pre-commit).
gate.skill-prosekeepCI-wired.
gate.markdown-fixtureskeepWired via sdlc.yaml check verbs and CI.
gate.corpus-invocationkeepWired via sdlc.yaml check verbs.
gate.comment-onlykeepUsed by docs-sweep’s verification pass.
harness.exportkeepDesign-doc-only right now; intentional, not dead.
harness.modelkeepSame design-doc cluster.
harness.install.claudekeepReal bootstrap step, doctor-checked.
lease.{heartbeat,heartbeat-loop}keepKeeps task-work’s/pr-respond’s lease alive.
lease.inspectkeepUsed by task-work/orchestrate.
lease.listkeepSweep/cleanup tooling.
lease.reconcilekeepHeals execution-plane status drift.
lease.releasekeepUsed by task-ensure-ready.
lease.parse-footerkeepParses the PR-body lease-binding footer for pr-respond.
lease.migrateextrasOne-shot cutover tool, dormant by design (not neglect).
lease.op.claimkeepGeneric operation-lease primitive.
lease.task.{acquire,archive,claim,fence,reacquire,transition,update-gates}keepThe task-lifecycle-lease state machine underlying the whole loop.
lease.task.sweepkeepBulk-archive maintenance op.
orchestrate.log-tickkeepOrchestrate’s own per-tick logging primitive.
orchestrate.watchkeepDeterministic pending-work gate for /loop.
plugin.infokeepThe /sdlc:info skill’s whole implementation.
plugin.resolvekeepUsed by the info skill.
plugin.install-permissionskeepSeeds the project Claude-Code allowlist.
pr.classifykeepThe classifier orchestrate dispatches on — but flagged plumbing-only/--advanced despite being the most-used op (help-text inversion, see below).
pr.reviewkeepReal, human-driven review session; outside the automated loop by nature.
pr.surveyextrasBuilt, tested, but not wired into orchestrate or any skill — a planned core-loop piece per the 1.0 plan.
pr.updateextrasSame status as survey; matched pair.
project.setupkeepThe “setup” stage of the core loop.
project.doctorkeepSetup-adjacent.
project.detect-setupkeepUsed by find-verbs.
project.{preflight-worktree,teardown-worktree}keepUsed broadly across worktree-mediated flows.
project.cleanupkeepMaintenance, run on demand.
project.scan.{candidates,comments,todos}keepPlanning-ingestion helpers (import-planning / docs-sweep / review-todos).
quality.detectkeepSetup-adjacent.
quality.runkeepThe single most central op in the CLI — the deterministic check step and CI.
quality.baseline.{capture,diff}keepUsed by task-work’s baseline gating.
quality.baseline.pruneremove or wire itOnly clear orphan: baselines accumulate unbounded under .sdlc/, nothing prunes them.
repo.checkoutkeepWrapped by the generated sdlc-repo-checkout shell function.
repo.{trust,untrust}keeptask-work’s consent gate.
report.{get-schema,render}keepReview-report rendering, “schema is the contract” pattern.
shell.initkeepImplements sdlc-cd/sdlc-at/sdlc-pr-review/sdlc-repo-checkout.
site.buildkeepDeploy-time site build.
verify.changesextrasDocumented as core to the phase gate’s “judge” step, but no skill invokes it yet — the clearest planned-but-unwired gap in the surface.
task.createkeepTask authoring.
task.nextkeepThe dispatch-order selector orchestrate/task-work both use.
task.inflightkeepCategorizes in-flight tasks against per-project limits.
task.probe-statekeepPre-flight worktree/branch/PR/status probe.
task.resolvekeepUsed by close-out/ensure-ready/review.
task.gap-reportkeepDeliberate composite over the scan/parse/check ops below.
task.{scan-placeholders,parse-touchpoints,check-claims}keepReadiness-gate internals, independently callable and composed. (A fourth op, resolve-touchpoints, existed when this table was drafted; it was retired afterward — Files-to-touch became Areas — and task/schema.ts now says so in its own comment. gap-report.ts’s composite was updated cleanly, so this was a doc-accuracy staleness only, not a functional gap.)
task.close-commitkeepThe close-out step.
task.lint-state-originkeepCI-wired commit gate.
task.list-unmergedkeepDedup / PR-branch task-file detection.
task.preview-idkeepUsed by task-new / import-planning / review-todos.
task.updatekeepUsed by task-new / task-auto-define.

Two help-text bugs surfaced by the same audit (see the Fix list): sdlc dashboard --help prints an empty “Registry-generated ops ()” summary even without --advanced, and pr classify is hidden behind --advanced while pr survey/pr update show as primary — the inverse of actual usage.

Verdict counts: keep = 38, extras = 8, move-out-to-repo-scripts (candidate) = 1, remove = 0 (47 total; expanding each (N subkeys)/{...} annotation as N keys, the same convention extras already used — the original count of 43 missed that expansion on two keep rows (pr_review.prompt.{mode,text} and verify.{...}’s 9 keys) and omitted a 47th key, orchestrator.review.command, entirely). Every key in SdlcConfigSchema, including that 47th key, has at least one real reader; no dead config surface was found.

Key (dotted path)VerdictReason
verbskeepThe one place lifecycle shell commands live.
orchestrator.max_implementationskeepHard dispatch cap read by task inflight.
orchestrator.max_awaiting_reviewkeepInformational review-queue ceiling.
orchestrator.review.commandkeepValidated (must contain {pr}) dispatch command for /sdlc:orchestrate --only review’s Step 2a, one PR-review sub-agent per open PR; defaults to the pr-tools plugin’s review command. Load-bearing for the opt-in review phase.
pr_check.author_commentskeepDrives the NEEDS-RESPONSE verdict.
pr_check.ignored_authorskeepBot-noise filter feeding the same classify path.
pr_update.authorkeepScopes pr survey/pr update.
pr_update.include_draftskeepSame survey scope.
pr_update.strategykeepRebase/merge decision for restacking.
pr_update.overrideskeepPer-PR strategy override, first-match.
pr_update.guards.unpushed_localkeepNon-negotiable data-safety guard.
pr_update.guards.reviewedkeepPreference guard, avoids outdating review threads.
pr_update.guards.max_rebase_commitskeepPreference guard, falls back to merge.
pr_update.lockfile_installkeepLockfile-conflict rebuild verb.
pr_update.resolverskeepProject codegen conflict resolution, first-match.
pr_update.verifykeepGates whether verbs.check reruns before push.
task.execution.spawn_from_post_mortem.* (5 subkeys)extrasReal feature, but an optional task-work Step 8 side effect, not the setup-task-PR spine.
backlog.capture.* (3 subkeys)extrasA separate idea-capture flow, not part of the core loop.
lease_authoritykeepRequired for every lease op; task-work’s coordination depends on it.
docs_sitekeepReal, well-used docs-site generation; auxiliary, not core.
plugin_sourcemove-out-to-repo-scripts (candidate)Only meaningful for a checkout that itself hosts SDLC’s own source (today, only sksizer/dev).
pathskeepToken map for repos:/checkout.layout.
reposkeepNeeded for cross-repo pr survey/update, project cleanup.
checkout.layoutkeeprepo checkout destination template.
checkout.protocolkeepClone protocol for repo checkout.
host.defaultkeepSession-hosting fallback for pr review and other interactive ops.
pr_review.enginekeepInteractive review agent, phase-gate step 3.
pr_review.hostkeepPer-feature host override.
pr_review.untrustedkeepFork-trust policy for the review worktree.
pr_review.setupkeepWhether the setup verb runs before the review session.
pr_review.prompt.{mode,text}keepReview-brief composition.
verify.{engine,model,concurrency,blocking,severity_floor,exclude,max_prompt_bytes,max_files_per_job,timeout_ms}keepverify changes = the “judge” step of the phase gate.

The scaffold (lib/config/scaffold.ts) is fully schema-derived — every value, default, and comment projects from SdlcConfigSchema’s own .describe()/.default() — so it cannot drift from the schema by construction. The July 2026 finding that stale .describe() prose named deleted Python scripts is confirmed fixed here (no .py reference remains); a related, narrower staleness in one .describe() string survives and is tracked in the Fix list below (docs_site’s list-ops.ts claim).


99 findings total across 12 shards: 9 blocking, 31 major, 59 minor. All 9 blocking findings and a 65% sample of majors were independently verified with zero false positives (see Verification methodology).

Blocking: 1 (fixed as of the current head — see note). Major: 3. Minor: 4.

File:lineSeverityDescriptionSuggested fix
lib/services/lease/ops/_common.ts:277-278Blocking (fixed)Misconfigured-lease-authority error message pointed users at conventions/python-runtime.md, which doesn’t exist (renamed to typescript-runtime.md).Already fixed as of the current head: an origin/main merge folded into this branch (commit d4065007c/68f344d32, “fix: remove stale reference to nonexistent python-runtime.md convention doc”) before this audit’s own last commit landed. The message now points at lib/services/lease/README.md; git grep python-runtime over solutions/ontological returns nothing.
lib/services/lease/runtime.ts:366-390, migration.ts:154-199, ops/task/claim.ts:88-109MajorThree sites independently hand-spell the ~19-field TaskLifecycleLease initial-claim payload; no canonical constructor exists.Extract a shared buildInitialTaskLeasePayload(opts) used by all three.
lib/services/lease/ops/task/transition.ts:265-355 vs runtime.ts:472-526MajorThe op reimplements transitionLease()’s whole fetch/mutate/CAS algorithm instead of calling it; only the phase-classification Sets are shared.Call transitionLease(...) and layer the op’s extra expiry pre-check on top.
lib/services/lease/reconcile.ts:1396-1526 (loadReconcileState)Major~130-line function mixes ref-diffing, authority fetch, a 4-way ref-namespace categorization loop, and task/PR observation.Split the ref-categorization loop into a categorizeRefs helper.

Minors:

  • lease/heartbeat-service.ts:147 — comment cites a nonexistent lease_heartbeat_loop.ts.
  • lease/guard.ts:34 — CheckNamespaceConflictOptions exported but only used internally.
  • lease/ops/task/sweep.ts:76-81 vs ops/_common.ts:64-73 — two taskIdFromRef functions with different contracts (throw vs. null) share a name; risks a future edit assuming parity.
  • lease/ops/op/claim.ts:117-135 vs ops/task/claim.ts:111-129 — identical validate/build/CAS try-catch skeleton copy-pasted between the two claim handlers.

Blocking: 1. Major: 1. Minor: 2. (The shard’s own header table stated Major: 2; only one finding in the body is actually tagged major — corrected here.)

File:lineSeverityDescriptionSuggested fix
7 test files incl. docs/tests/site_ownership.test.ts:30 and 6 siblingsBlockingComments describe a plugin/... directory tree retired by the repo restructure; segment counts are now wrong too (5 vs. the actual 6).Update all 7 comments to the solutions/ontological/... layout with correct segment counts.
lib/services/docs/generate.ts (852 lines)MajorFile owns 8 distinct concerns (status bucketing, per-section assembly for 8 entity types, glossary/references, rendering, artifact registry, 2 drift-check paths); site/reference.ts already documents the precedent for splitting a file at this size.Split per the site/reference.ts precedent; extract the duplicated titleOf+sort block (lines 472-474, 513-515) into a shared sortByTitle.

Minors:

  • docs/generate.ts:472-474,513-515 — duplicated titleOf+sort block (companion to the major above, independently actionable).
  • design-tokens/project.ts:144-152 — projectSeedSet has zero call sites/tests.

Blocking: 1. Major: 1. Minor: 2. (The shard’s header table stated Major: 2; only one body finding is tagged major — corrected here.)

File:lineSeverityDescriptionSuggested fix
gate/ops/_skill_prose_contract.ts:4BlockingHeader says “14 covered skills”; the registry has 16, and the sibling test pins 16.Update the comment to 16 (or phrase it to avoid future drift).
pr/update/resolvers.ts:38-39MajorResolverKind type is dead (zero importers) and inconsistent with PathPlan.kind ('rerere' vs. 'unclaimed').Delete ResolverKind, or reconcile it with PathPlan['kind'] and wire it in.

Minors:

  • gate/ops/worktree-scope.ts:135 — comment implies a mirrored standalone script that doesn’t exist.
  • pr/ops/survey.ts:436-438 and pr/update/tui.tsx:75-77 — identical hand-rolled pad() reimplements String.prototype.padEnd.

Blocking: 1. Major: 4. Minor: 6.

File:lineSeverityDescriptionSuggested fix
lib/services/dashboard/server.ts:1499-1510,1607BlockingtcpProbe is dead (superseded by dashboardHealthy), kept alive by a void tcpProbe silencer — the exact defect shape the July audit flagged for this file, recurring under a new symbol.Delete tcpProbe and the silencer line.
lib/services/dashboard/project-registry.ts:192-198MajorprojectRegistry() singleton getter and its backing shared variable are fully dead; the real caller uses createProjectRegistry() directly.Delete both, or wire makeApp’s default parameter to use it.
dashboard-service.ts:47-89 vs dashboard-service-main.ts:23-62MajorNear-identical ~40-line CLI arg parsers duplicated across two files.Extract one shared parseDashboardArgs(argv, extraFlags?).
project/ops/scan-candidates.ts:105-280MajorA full hand-rolled .gitignore glob-to-regex compiler plus Python-mtime formatting (~150 lines) lives inline at the op layer, inverting the stated lib/util vs. lib/services layering.Move the gitignore-glob compiler and mtime helpers into lib/util/.
project/ops/setup.ts:139-159 (readLeaseAuthority)MajorHand-rolls what @lib/config’s resolveAuthority already does; dashboard/server.ts in the same shard already calls the canonical one.Replace with resolveAuthority(null, resolvedRoot).

Minors:

  • dashboard/server.ts:293-334 — BROWSABLE_ENTITY_TYPES comment claims sole source of truth, but the desktop app maintains an independent mirrored list with no compile-time link.
  • dashboard/server.ts (several lines) — 7 symbols exported with zero external importers.
  • project/ops/scan-candidates.ts:10-11 — comment claims byte-compatibility with a deleted legacy script.
  • project/ops/setup.ts:207 — ad hoc Python-style boolean formatting duplicates cleanup/index.ts’s unexported pyBool.
  • project/ops/_gitignore.ts:40-59 — two exported helpers used only internally.
  • project/cleanup/index.ts:67-70,561-570 — two exported interfaces with zero importers by name.

Misc services (harness, plugin, host, verify, quality, repo, commit, config, dev, git, report, shell)

Section titled “Misc services (harness, plugin, host, verify, quality, repo, commit, config, dev, git, report, shell)”

Blocking: 1. Major: 4. Minor: 6. (The shard’s own summary stated Major: 5; only 4 findings are actually tagged major in the body — a bookkeeping slip in the source file, corrected here and noted again in Verification methodology.)

File:lineSeverityDescriptionSuggested fix
services/config/verb-list.ts:59-65BlockingSDLC_YAML_HEADER doc comment claims byte-identity with a _SDLC_YAML_HEADER symbol that doesn’t exist; the real sdlc project setup header (configScaffoldYaml) is a different, longer comment.Share one header constant, or correct the comment.
quality/ops/run.ts:352-367 vs quality/ops/baseline/diff.ts:99-116MajorBoth independently implement “compute pre-existing findings” — logic baseline.ts claims to canonically own.Add preExistingFindings(current, baseline) to baseline.ts; call it from both.
quality/ops/run.ts:193-397 (handler)Major~200-line handler does 6+ distinct things, mixing execution with baseline-gating render logic.Extract the baseline-gating block into an applyBaselineGate helper.
verify/ops/changes.ts (whole file)MajorNo test file anywhere covers this op — the riskiest file in the shard (severity-floor gating, exit-code computation, the “every judgement failed” error path, HTML report generation).Add unit/CLI tests for the blocking/non-blocking exit paths and the MODEL_ERROR path.
plugin/info-report.ts:18-25 vs plugin/ops/resolve.ts:23-30MajorBoth declare an identical private loadJson; both hand-parse the same on-disk plugin-registry shape independently.Extract a shared readPluginRegistry/loadJson into plugin/registry.ts.

Minors:

  • config/tests/verbs_ops.test.ts:12 — repeats the same false _SDLC_YAML_HEADER reference.
  • quality/ops/run.ts:337-340 — BaselineEntry interface redeclared inline instead of imported from baseline.ts.
  • host/hosts/{cmux,orca,terminal}.ts — identical 6-line session() block copy-pasted 3 times.
  • harness/ops/install-claude.ts:306-411 — 105-line handler, mildly under-decomposed.
  • repo/ops/{trust,untrust}.ts — identical targetRoot() helper declared in both files.
  • verify/ops/changes.ts (whole file) — mixes CLI rendering, pure helpers, op handler, and HTML-report assembly in one 534-line file.

Blocking: 0. Major: 2. Minor: 6.

File:lineSeverityDescriptionSuggested fix
entities/task/ops/inflight.ts:26,161MajorexistsSync imported then only referenced via void existsSync; the adjacent comment describes a .git-file-or-dir check that is never actually implemented.Implement the described check, or delete the dead import and stale comment.
entities/task/ops/lint-state-origin.ts:58-60MajorUser-facing stderr message hardcodes a dead date-slug doc path; the file was migrated to T-SIHV-....Update the literal string to the current path.

Minors:

  • lint-state-origin.ts:9, _lint_state_origin_core.ts:6,69, its test — stale date-slug wikilink (companion to the major above).
  • entities/task/ops/parse-touchpoints.ts:440 — export type { Section } has no importer.
  • entities/task/claims/paths.ts:177 and claims/quantifiers.ts:125 — unused default exports.
  • entities/task/migrations/errors.ts — MigrationError byte-identical to the capability entity’s version (see also entities: other, below).
  • entities/task/ops/next.ts:72-92 — IMPACT_MISSING = -1 used only via double-negation; confusing sign, correct logic.

Entities: other (backlog, capability, decision, driver, milestone, principle, product, reference, standard, term, corpus)

Section titled “Entities: other (backlog, capability, decision, driver, milestone, principle, product, reference, standard, term, corpus)”

Blocking: 0. Major: 1. Minor: 6.

File:lineSeverityDescriptionSuggested fix
principle/reports/review/schema.ts:30-89 vs standard/reports/review/schema.ts:26-87MajorfindingSeverity/finding/proseIssue/*ReviewReport are ~95% identical between the two files, differing only in field-name prefixes; a structurally different third schema (task/reports/review/schema.ts) was initially miscited as a third copy — see the Verification note below.Extract a shared reviewFindingSchemas(entityNoun) factory in lib/services/report/schema.ts.

Minors:

  • capability/migrations/errors.ts:1-15 — MigrationError duplicated with the task entity’s version (same underlying issue as the task-shard minor above; only one shared fix needed).
  • entities/_common.ts:144-146 — comment cites a nonexistent lib/model/tests/entity.test.ts path (real file is lib/model/entity.test.ts).
  • milestone/schema.ts:30 — MILESTONE_VERSION_PATTERN exported with no importer.
  • principle/schema.ts:25 — PRINCIPLE_CATEGORY_PATTERN exported with no importer.
  • capability/ops/coverage.ts:162-281 — 119-line buildCapabilityCoverage spans 5 phases.
  • capability/ops/graph.ts:93-243 — 150-line buildCapabilityGraph spans 5 phases.

Blocking: 0. Major: 3. Minor: 8.

File:lineSeverityDescriptionSuggested fix
lib/model/index.ts (27 lines)MajorDead barrel — zero importers via from '@lib/model' anywhere in the repo; every real consumer imports deeper paths. This is PR1 item 6 from the July audit, still unfixed and the single biggest gap.Delete the barrel (and cascading dead exports — see minors).
lib/model/ops/migrate.ts:2-3,14-18 and ops/audit.ts:20-23MajorModule docs describe a migrate_entities.ts CLI entry point that forwards to runMigrate; no such file exists anywhere — the logic now lives inline in migrate.ts’s own handler.Rewrite both doc comments to describe the current architecture.
lib/model/ops/validate.ts:18-31,82-89MajorComments say a validate_frontmatter.ts/validate_base.ts shim “keeps its own copy until T-YBKU deletes it” — that task is closed/done and the shim files don’t exist.Rewrite to past tense, or drop the historical framing.

Minors:

  • lib/model/read.ts:189-191 (frontmatterOf) — dead outside the dead barrel above.
  • lib/model/corpus/index.ts:9 — readFrontmatter re-export has no real caller.
  • lib/model/index.ts:1-6 — header cites a nonexistent __init__.py Python source.
  • lib/model/entity.ts:284-305 (hydrateFrontmatter/HydrateResult) — full implementation, no production caller, no self-documenting disclaimer (unlike its sibling scaffold).
  • lib/model/ops/_preview_id.ts:149 — uses localeCompare instead of the codebase’s locale-independent cmpStr convention.
  • lib/model/ops/validate.ts:554-691 — the one op in this directory that inlines its engine directly in the defineOp handler instead of a standalone run*() function.
  • lib/model/ops/migrate.ts:346-484 (runMigrate) — ~140-line multi-responsibility function.
  • lib/model/entity.ts:216-267 (scaffold) — dead in production, but already self-documented as intentional test-only surface; informational only.

Blocking: 4. Major: 7. Minor: 4.

File:lineSeverityDescriptionSuggested fix
lib/config/load.ts:613-623 (resolveProjectRoot)BlockingHand-rolls the exact ancestor-walk loop that lib/util/paths.ts’s findAncestor claims as its “single home,” despite load.ts already importing other @lib/util modules.findAncestor(start, dir => existsSync(join(dir, 'sdlc.yaml'))) ?? resolve(start).
skills/migrate-runtime-state/migrate_runtime_state.ts:64-74BlockingLocal pyResolve is byte-for-byte paths.ts’s realResolve (no walk-up) — but collides in name with paths.ts’s own, differently-behaving pyResolve (which does walk up).Delete the local copy; import realResolve (or pyResolve if walk-up is actually wanted).
lib/util/yaml.ts:1-8Blocking”Every caller imports parse… from here” is false: 6 production files import from npm yaml directly.Migrate the 5 one-line-swap production sites; add a parseDocument/Document re-export for verb-list.ts’s genuinely different need.
lib/config/sdlc_yaml.ts:19-21BlockingCites task T-MBOK as a pending future landing for the yaml chokepoint; T-MBOK is closed/done and the chokepoint already exists.Swap the import to @lib/util/yaml; delete the stale note.
lib/config/merge.ts:18-20MajorPrivate isPlainObject byte-identical to lib/util/guards.ts’s exported isRecord; guards.ts’s own header names lib/config a sanctioned importer.Import isRecord; delete isPlainObject.
skills/task-ensure-ready/ensure_ready_mutate.ts:185-193MajorPrivate nowIsoUtc reimplements rfc3339(nowUtc()), used to stamp readiness_verified_at.import { rfc3339, nowUtc } from '@lib/util/date'.
lib/services/verify/ops/changes.ts:459MajorBypasses todayUtc() with an inline new Date().toISOString().slice(0, 10).date: todayUtc().
lib/util/strings.ts singularize vs lib/util/naming.ts pluralizeMajorIndependent, non-inverse implementations of the same domain; pluralize('class') → 'classes', singularize('classes') → 'classe' (wrong). Currently latent since no entity type name hits the gap.Share an irregular-noun table, or add a round-trip property test.
lib/services/lease/tree.ts:34-42 (nowCommitDate)MajorHand-derives the git commit-date format via regex instead of composing rfc3339, while a sibling file in the same subsystem (runtime.ts:769) already does it the composed way.rfc3339(nowUtc()).replace(/Z$/, '+0000').
4 sites (list-unmerged.ts:227, scan-candidates.ts:400, skill-prose.ts:76, summarize_dedup_telemetry.ts:240)MajorEach hand-rolls the exact cmpStr-shaped ternary comparator instead of importing cmpStr.Import cmpStr from @lib/util/strings at all 4 sites.
lib/config/load.ts:365-372 (docs_site .describe())MajorClaims <dir>/scripts/list-ops.ts resolves beneath docs_site; it actually resolves from the plugin’s own tree, independent of docs_site — and this exact string leaks into every consumer’s generated sdlc.yaml via the scaffold.Drop or rewrite the list-ops.ts clause in the .describe() string.

Minors:

  • lib/util/claude-home.ts — claudeHome() exported but only ever called internally.
  • experiences/system-graph/app/lib/pattern.ts:95 — inline escapeRegExp reimplementation, but outside solutions/ontological’s own dependency graph, so not a violation of its claim.
  • products/system-graph/server/utils/project-root.ts:22-30 — same ancestor-walk pattern as findAncestor, same out-of-package caveat as above.
  • lib/services/harness/ops/install-claude.ts:352 — ad hoc millisecond-precision ISO timestamp, not routed through date.ts (low risk, not byte-compared anywhere).

Blocking: 0. Major: 4. Minor: 6.

File:lineSeverityDescriptionSuggested fix
cli/task_cli/README.md:17-31Major”Layout” block claims index.ts/_common.ts files and build_task_subtree()/dispatch_task() functions that don’t exist anywhere in the repo.Rewrite to reflect the actual shape (README + tests/) and point at entities/task/ops/next.ts / registry_adapter.ts.
cli/backlog_cli/_common.ts:29 and index.ts:61-62MajorBoth say MODEL_ERROR exits with code 8; the actual value (via exitCodeFor) is 16. The “lease owns 2-7” comment is also wrong (lease is 10-13). User-visible via sdlc backlog --help.Correct both to 16; fix or remove the numeric-band claim.
cli/tests/lease_dispatch.test.ts:23,366,372,382,394,438Major5 raw child_process.spawnSync calls, no @sdlc:ignore-spawn-style note, despite the same file already using runCli for other tests.Replace all 5 with runCli/runCapture from @lib/tests/_cli_harness.ts.
cli/backlog_cli/tests/create.test.ts:9,115MajorRaw spawnSync('ls', ...) duplicates an already-imported readdirSync used for the identical purpose 400 lines later in the same file.Replace with the existing readdirSync call.

Minors:

  • cli/registry_adapter.ts:113-120 vs cli/_common.ts:35-42 — byte-identical jsonlSortReplacer/sortedKeysReplacer.
  • cli/sdlc.ts:407-408 — dead re-exports with no importer.
  • cli/registry_adapter.ts:699 — dead exitCodeFor re-export.
  • cli/backlog_cli/{create,capture}.ts, _common.ts, 2 test files — 5 stale “mirrors the Python tier” comments.
  • cli/backlog_cli/README.md:11-22 — layout block disagrees with actual test-file placement.
  • cli/task_cli/tests/dispatch.test.ts and cli/backlog_cli/tests/dispatch.test.ts — duplicated ad hoc Bun.spawn capture helpers instead of the shared _cli_harness.ts.

Blocking: 0. Major: 1. Minor: 8.

File:lineSeverityDescriptionSuggested fix
skills/task-ensure-ready/ensure_ready_mutate.ts:723-963 (applyVerdict)Major~240-line function fuses flag validation, lease discovery, the --commit-on flow, the standalone --commit flow, and the no-commit passthrough.Extract the --commit-on and --commit arms into named helpers, matching the file’s own existing decomposition style.

Minors:

  • skills/migrate-runtime-state/migrate_runtime_state.ts:64-74 — same pyResolve/realResolve collision as the util-config blocking finding B2 above (one shared fix).
  • skills/task-ensure-ready/scan_corpus_assumptions.ts (7 lines) — stale comments citing a nonexistent scan_placeholders.ts.
  • scan_corpus_assumptions.ts:247-282 vs skills/task-work/dedup_search.ts:442-531 — two independent hand-rolled Python-json.dumps-compatible encoders.
  • skills/task-work/dedup_search.ts:513-515 — dead/redundant identical-branch conditional.
  • skills/task-work/summarize_dedup_telemetry.ts:26-28 — rjust duplicated verbatim from lib/services/project/ops/setup.ts:66-68.
  • scripts/compiled/bootstrap.ts:62-110 — unmarked raw spawns (no @sdlc:ignore-spawn) plus an inaccurate “build tooling, not runtime” header claim, though it ships inside the compiled binary.
  • scripts/build-binary.ts:80-85 vs scripts/build-npm-wrapper.ts:103-108 — identical run() helper duplicated between two files that already know about each other.
  • conventions/schema-bump-checklist.md:7-8 — cites nonexistent audit_entities.ts/ migrate_entities.ts scripts instead of the actual sdlc entities audit/migrate CLI ops.

Blocking: 0. Major: 0. Minor: 1.

All 14 packages/ts/<name> workspace dependencies consumed by solutions/ontological are actively imported with no unused packages, no stale commits, and no hand-rolled child_process/gh argv bypassing the command seam.

  • lib/util/git.ts:70-127 (isLinkedWorktree, listWorktreeBasenames) — partially overlaps @sksizer/easy-git’s own worktree primitives (mainCheckout(), worktrees()); the filesystem scan can silently disagree with git’s own registry. Derive from easy-git, or document the git-binary-free rationale explicitly.

Reconciling docs/planning/notes/N-UAG5-2026-07-19-sdlc-simplification-audit.md’s 11-PR stack against the current tree. Counts below are row-based (a companion sub-item with its own status gets its own row; mixed-status rows are counted under their primary/leading status).

Summary: Fixed = 79, Still present = 13, Obsolete = 4 (96 itemized entries total across both ranges — expanding PR8’s 1-4,4a-4e,6-8 consistently with the rest of this table’s ranges gives 12 items, not 8, which moves Fixed from 78 to 79 and the total from 95 to 96).

PRItemDescriptionStatusEvidence
11Delete lib/services/quality/run-checks.ts + dead exportsFixedFile and all named symbols absent.
11aReword ops/run.ts’s “mirrored from the script” commentStill presentops/run.ts:44 still reads it, though the script is gone.
11bFix 3 task files’ stale run-checks.ts touchpoint rowsStill presentT-YF4K/T-BCNP/T-BQRU still cite it.
12Delete lib/util/schema_patterns.ts + testFixedFile and test absent; zero references.
12aBacklog superRefine reject-branch coverageFixedBoth update.test.ts and create.test.ts assert reject cases.
12bNote arrayElement as intentionally orphanedStill presentFunction exists, no such note added.
13Delete verify_prs_against_pr.ts + SKILL.md fixFixedFile/test absent; SKILL.md uses sdlc task close-commit.
14Delete lease/canonical_json_cli.tsFixedFile absent.
14aFix tree.ts header’s “CLI wrapper” rationaleStill presentStill cites a CLI wrapper, not orchestrator/ops/watch.ts.
15Delete cli/task_cli/_common.tsFixedFile absent.
15aFix task_cli/README.md’s stale Layout blockStill presentWorse than anticipated — index.ts also now gone.
16Delete lib/model/index.ts + corpus/index.ts barrelsStill presentBoth barrels still exist — the single biggest unfixed item (see Headline).
21-9, 11, 13Delete dead exports/branches in entity.ts, ops/audit.ts, identifier.ts, config/schema.ts, cli/_common.ts, dashboard/server.ts, registry_adapter.ts, ops/validate.ts, wikilinks.ts/markdown_extract.ts, task ops/* tails, _skill_prose_contract.tsFixedAll confirmed absent/corrected by direct grep.
21aRefresh RF-0004-json-schema-2020-12.md fullyStill present (partial)Notes section says the $ref resolver “was retired,” but the Summary above it still asserts it as present-tense fact; stale apps/sdlc path too.
26atcpProbe current statusStill presentRecurs (see Dashboard + project shard).
26bvoid existsSync in task/ops/inflight.tsStill presentRecurs (see Entities: task shard).
26c,6dvoid parsePath / void inline/void topScoreFixedAll three symbols/silencers gone entirely.
210git/easy.ts dead-export cleanupObsoleteFile no longer exists — superseded by the @sksizer/easy-git extraction.
212Un-export 7 cleanup/index.ts pipeline stagesFixed (2 of 7 named)Confirmed unexported where checked; 7 intended-public exports correctly kept.
212aUn-export 5 more functions + PRInfoObsoleteNone exist anymore — the pipeline was restructured around gatherAndClassify.
214Fix 4 Python-script .describe() referencesFixed (2) / Obsolete (2)orchestrator/lease_authority fixed; quality_checks/worktree_init fields no longer exist (superseded by a unified verbs: field).
31-7Add lib/util primitives (guards.ts, py.ts, escapeRegExp, fs.ts additions, stringField, frontmatter fences, worktreeDir)FixedAll 7 present and tested; py.ts landed as diagnostics.ts instead (equivalent semantics, different name).
41-5Adopt isFile/isDir/escapeRegExp at named sites; prune baseline JSONFixed (large majority)A few named files (append_pr_url.ts, old frontmatter.ts, detect-runners.ts) are obsolete citations — superseded by later restructuring, not unfixed.
51,2,4Adopt rfc3339/posix; delete dashboard/server.ts’s private parseRfc3339FixedConfirmed at all named sites; documented exceptions (lease/tree.ts, lease/runtime.ts) correctly left alone.
53Adopt cmpStr at ~12 sort sitesFixed (11 of 12)One remaining inline comparator at scan-candidates.ts:400 (recurs as util-config M6, above).
61-3,5Adopt typeName/repr/isRecord; collapse v3-to-v4/v4-to-v5 via stampOnlyMigrationFixedAll confirmed; py.ts naming diverged as noted in PR3.
64Adopt pyRepr at 2 sites; leave v2-to-v3.ts’s pyReprStr aloneFixed, with one divergencepyReprStr was folded into the shared repr() anyway — the audit said not to; no evidence of resulting breakage.
66Fold MigrationError (task + capability)Still presentAudit itself marked this optional; recurs in this audit as an entities-task/entities-other minor.
PRItemDescriptionStatusEvidence
71,4,5,6,7Route frontmatter parsing through parseFrontmatterResult/splitFrontmatter; relocate task-specific prs: helpers out of lib/utilFixedAll confirmed at the named sites.
72Adopt fence-preserving helpers at _update.ts+migrate.tsFixed (migrate.ts) / Obsolete (_update.ts)_update.ts moved to a span-preserving editFrontmatterFields engine, superseding the ask.
73Route writePrsFrontmatter through dumpFrontmatter; fix parity bugsObsoleteFunction relocated to entities/task/prs.ts, now uses editFrontmatterFields — sidesteps the whole question.
81-4,4a-4e,6-8Converge on _probe_core.ts helpers, worktreeDir/worktreeDirRel, @lib/util/location’s globMatches, Git instance threading (5 sub-items), scanEntities-based loadTasks, _table_cells.tsFixedAll confirmed at named sites, including the easy-git package extraction the audit anticipated.
85Delete dead makeRunFn/_gitRunner; thread Git at 3 sitesObsoleteAll git-spawning code was extracted wholesale into a new @sksizer/repo-cleaner package.
91-7Promote wikilink/id-pattern factories, requiredWhen, RESULT_PATTERN_BY_STATUS; fix stale headersFixedAll 7 confirmed.
101-4,6a,6b,6cExtract leaseTarget, expiresAt, freshOwnerOrNull; add missing LeaseConflict arm; export OWNER_KIND/OPERATION_STATEFixedAll confirmed; the missing-arm fix (item 4) is a real prior exit-code bug, now covered by a test.
105Single-source lease phase setsFixedruntime.ts exports both sets; transition.ts imports them; the intentionally-separate TRANSITION_PHASES enum correctly remains distinct.
111,2,3,5Replace hand-rolled site.ts frontmatter parsing; extract site/reference.ts; collapse escapeFmString; extract site/write.tsFixedAll confirmed, including the per-skill catch-and-continue behavior the audit prescribed.
114Unify the two ## Purpose extractors via sectionBodyStill presentsectionBody exists but neither extractor uses it; audit itself flagged this as low-value.
116Collapse duplicated recursive .md walk (rglobMd vs listMdFilesRecursive)Still presentBoth still exist independently in audit.ts and site.ts.
117Fold adrSection’s inline bucketing into splitSectionStill presentAudit itself deprioritized this; unfixed as expected.

The most consequential still-present item is PR1 item 6 — the lib/model/index.ts and corpus/index.ts dead barrels — which never landed across two follow-up PR ranges and remains the single largest gap in the reconciliation (see Prune task list, below).

PR3’s premise diverged, but the underlying problem was still fixed. The audit prescribed a new lib/util/py.ts exporting pyTypeName/pyRepr. That file was never created; instead lib/util/diagnostics.ts (with typeName/repr) became the module every prospective call site actually adopted, evidently as part of a broader move away from “Python-port” naming. The duplication problem PR3 targeted — 8 independent shim copies — is fully resolved either way; only the literal file/function name differs from the prescription.


Grouped by category, with the target phase derived from docs/planning/sdlc-1.0-plan.md’s phase list. Pure dead-code/duplication/stale-comment cleanup inside solutions/ontological with no dependency on later-phase work defaults to Phase 13 (the plan defers all audit pruning/refactor execution there, alongside the TUI). Two items complete wiring that Phase 2 itself defines (judge/pr-update workflow steps) and are mapped there instead. No task in this list concerns publishing/npm/marketplace-sdlc mechanics, so none map to Phase 14.

TaskAreasTarget phase
Delete the dead lib/model/index.ts barrel and its cascade (frontmatterOf, corpus/index.ts’s dead readFrontmatter re-export)lib/model/Phase 13
Delete dead code in services: tcpProbe (dashboard/server.ts), projectRegistry() singleton (dashboard/project-registry.ts), the void existsSync lint-silencer in task/ops/inflight.tslib/services/dashboard/, lib/model/entities/task/Phase 13
Remove the long tail of unused/dead small exports (ResolverKind, MILESTONE_VERSION_PATTERN, PRINCIPLE_CATEGORY_PATTERN, projectSeedSet, Section type, task claims/ default exports, CheckNamespaceConflictOptions, claudeHome, hydrateFrontmatter, cli/sdlc.ts’s and registry_adapter.ts’s dead re-exports)lib/model/, lib/services/, cli/Phase 13
Wire or delete quality.baseline.prune — the one clear orphaned CLI op (baselines accumulate unbounded under .sdlc/)lib/services/quality/, skills/project-cleanup/Phase 13
TaskAreasTarget phase
Move the update-skill-doc skill out of the general skill set into repo-level tooling — it hardcodes solutions/ontological/skills/<slug>/SKILL.md, a dev-on-plugin concern no downstream consumer needsskills/update-skill-doc/Phase 3 (the vault-conversion phase already rewires skill-file consumers in one PR)
Move the plugin_source config key (and the gates that key it: skill-prose, corpus-invocation, docs-site) out of SdlcConfigSchema into repo-level tooling — only meaningful for a checkout hosting SDLC’s own sourcelib/config/load.ts, lib/services/gate/Phase 5 (full sdlc.yaml, meta-defined — where config-key scope gets decided)
TaskAreasTarget phase
Consolidate the 3 duplicated lease-payload-mint call sites into buildInitialTaskLeasePayload; make ops/task/transition.ts delegate to transitionLease(); split loadReconcileState into a categorizeRefs helperlib/services/lease/Phase 13
Split docs/generate.ts (852 lines, 8 concerns) per the site/reference.ts precedent; extract the duplicated titleOf+sort block into sortByTitlelib/services/docs/Phase 13
Fix the util/config “single home” violations as one sweep: resolveProjectRoot → findAncestor; delete the misnamed local pyResolve (migrate-runtime-state, also flagged in skills-scripts); migrate the remaining raw yaml-package imports onto @lib/util/yaml; config/merge.ts’s isPlainObject → isRecord; nowIsoUtc → rfc3339(nowUtc()); verify/changes.ts’s inline ISO-date → todayUtc(); lease/tree.ts’s nowCommitDate → composed rfc3339; the 4 inline cmpStr-shaped comparators → cmpStr; the singularize/pluralize non-inverse splitlib/config/, lib/util/, lib/services/lease/, lib/services/verify/, lib/model/entities/task/, lib/services/project/, lib/services/gate/, skills/task-work/, skills/migrate-runtime-state/Phase 13
Factor the triplicated session() helper in host/hosts/{cmux,orca,terminal}.ts into one shared functionlib/services/host/Phase 13
Move the hand-rolled .gitignore glob compiler and Python-mtime formatter out of project/ops/scan-candidates.ts into lib/util/lib/services/project/, lib/util/Phase 13
Replace project/ops/setup.ts’s hand-rolled readLeaseAuthority with @lib/config’s resolveAuthority; extract a shared parseDashboardArgs for dashboard-service.ts/dashboard-service-main.tslib/services/project/, lib/services/dashboard/Phase 13
Extract a shared plugin/registry.ts (readPluginRegistry/loadJson) for info-report.ts’s and resolve.ts’s duplicated JSON-load and registry-parsing logiclib/services/plugin/Phase 13
Dedupe the “pre-existing findings” computation between quality/ops/run.ts and baseline/diff.ts into baseline.ts; split run.ts’s 200-line handler; add the missing test for verify/ops/changes.ts and consider splitting its render/report concerns outlib/services/quality/, lib/services/verify/Phase 13
Hoist the duplicated MigrationError class (capability + task entities) to one shared home; extract a shared reviewFindingSchemas(entityNoun) factory for the ~95%-duplicated principle/standard review-report schemaslib/model/entities/, lib/services/report/Phase 13
Split the oversized functions flagged across shards: applyVerdict (task-ensure-ready, 240 lines), buildCapabilityCoverage/buildCapabilityGraph (capability ops), runMigrate/runValidateFrontmatter (model/ops)skills/task-ensure-ready/, lib/model/entities/capability/, lib/model/ops/Phase 13
Consolidate small duplicated helpers: a shared pyJsonDumps for the two Python-JSON encoders (scan_corpus_assumptions.ts, dedup_search.ts); promote rjust/pad duplicates to lib/util/strings.ts (or use padEnd); dedupe the run() build helper in build-binary.ts/build-npm-wrapper.ts; add @sdlc:ignore-spawn markers and swap touch spawns for writeFileSync in scripts/compiled/bootstrap.tsskills/, lib/util/, scripts/Phase 13
Replace the raw child_process.spawnSync command-seam violations in cli/tests/lease_dispatch.test.ts and cli/backlog_cli/tests/create.test.ts; dedupe the ad hoc Bun.spawn test capture helpers onto _cli_harness.tscli/tests/, cli/task_cli/, cli/backlog_cli/Phase 13
lib/util/git.ts’s worktree-detection helpers — derive from @sksizer/easy-git’s mainCheckoutFrom/worktrees() instead of an independent filesystem scan, or document the divergencelib/util/Phase 13
Wire sdlc verify changes into the judge workflow step — the op exists and is documented as core to the phase gate, but nothing invokes it yetlib/services/verify/, sdlc.yaml workflowsPhase 2
Wire pr survey/pr update into orchestrate’s merges loop (built, tested, described in the plan’s execution model, but currently unwired) — or drop them from the plan if the design changeslib/services/pr/, lib/services/orchestrator/Phase 2
TaskAreasTarget phase
Fix the dead-doc-link and false claim comments that are user- or config-facing: lease’s python-runtime.md dead link (already fixed as of the current head — see the Lease + orchestrator finding above); _skill_prose_contract.ts’s “14 skills” header; verb-list.ts’s false _SDLC_YAML_HEADER claim; the stale T-MBOK note in config/sdlc_yaml.ts; the stale docs_site .describe() claim about list-ops.ts (leaks into every consumer’s scaffolded sdlc.yaml)lib/services/gate/, lib/services/config/, lib/config/Phase 13
Fix the 7 stale plugin/-tree path comments (with wrong segment counts) in the docs test fileslib/services/docs/tests/Phase 13
Fix the stale migrate_entities.ts/validate_frontmatter.ts shim comments describing removed forwarding shims as still-pendinglib/model/ops/Phase 13
Fix the stale date-slug wikilink and hardcoded dead path in lint-state-origin.ts and its 2 sibling fileslib/model/entities/task/Phase 13
Fix the stale CLI docs cluster: task_cli/backlog_cli READMEs referencing deleted files and a test-placement mismatch; the backlog_cli exit-code doc (8 → 16; “lease owns 2-7” → 10-13)cli/task_cli/, cli/backlog_cli/Phase 13
Sweep the remaining stale “mirrors the Python tier” / deleted-file comments: backlog_cli’s 5 “mirrors …py” comments, scan_corpus_assumptions.ts’s scan_placeholders.ts references, schema-bump-checklist.md’s audit_entities.ts/migrate_entities.ts, lease/tree.ts’s stale “CLI wrapper” headercli/backlog_cli/, skills/task-ensure-ready/, conventions/, lib/services/lease/Phase 13
Close out the remaining PR1/PR2 stale-comment leftovers from the July audit: quality/ops/run.ts:44, the 3 task files still citing run-checks.ts, zod_introspect.ts’s missing orphan note, RF-0004’s Summary/Notes contradictionlib/services/quality/, docs/planning/tasks/, docs/planning/decisions/Phase 13
Fix the two CLI help-generation bugs: sdlc dashboard --help’s empty op-list summary; pr classify’s --advanced-hidden status vs. pr survey/update’s primary visibility (inverted from actual usage)cli/, lib/services/pr/Phase 13

29 tasks total: 4 Prune, 2 Move-out, 15 Refactor, 8 Fix.


All 9 blocking findings across the 12 code-quality shards were independently re-checked against the current tree (all 9 confirmed, 0 false positives). A ~65% sample of major findings (20 of a recounted 31 total, spanning 11 of the 12 shards — the 12th, workspace-deps, has zero majors) was independently re-checked the same way: 19 confirmed outright, and 1 confirmed with a caveat — the entities-other principle/standard schema-duplication finding is real and correctly rated Major, but its supporting claim that a third near-identical copy exists at task/reports/review/schema.ts (“3x, not 2x”) is factually wrong; that file is a structurally unrelated whole-backlog report schema. The finding’s severity is unaffected since the 2x duplication alone justifies it. Combined, 29 of 29 sampled blocking/major findings held up (100%), with the one sub-claim above downgraded from “3x” to “2x.” Minor-severity findings (59 total) were not independently sampled.

Two minor QA notes surfaced during verification, neither disqualifying: p4-quality-misc-services.md’s own summary line stated “Major: 5” while only 4 findings are actually tagged major in its body (corrected in this document’s Misc services subsection), and a similar one-off discrepancy was found and corrected for the docs-designtokens and gate-pr shards’ self-reported major counts against their own bodies. These are bookkeeping slips in the raw shard files, not defects in the underlying code findings.


← Back to Notes