Repository navigation
Description
Summary
validateProjectConfigs (pm-stack/aggregator/src/project-config.ts:659) is the registry's only guardrail — "strict in tests, never throws at render" — but two of its checks are looser than the code that consumes the values, so a registry entry can pass validation clean and still break or misrender a /program page:
- Refs the validator accepts,
parseRef/refUrlthrow on. The validator'sREF_PATTERN(project-config.ts:641) is/^[^/\s]+\/[^#\s]+#\d+$/. The canonical parser (model.ts:452-456) is/^([\w.-]+\/[\w.-]+)#(\d+)$/— exactly one slash,[\w.-]segments. Refs such asa/b/c#12,a$/b#12, anda+b/c#3pass validation with zero errors, butparseRefthrowsnot a repo-qualified refand so doesrefUrl. Config tracked refs are rendered throughrefUrl(render.ts:5459, project detail page) and resolved through the shared ref set (allProjectRefs, project-config.ts:843), so one such entry turns a green registry test into a render-time throw. openIssuesAsOfis shape-only. The check at project-config.ts:696 is/^\d{4}-\d{2}-\d{2}$/, so2026-02-30,2026-13-01,2026-00-00, and2026-04-31all pass. The value is rendered verbatim as the snapshot's date (render.ts:5462: "Open issues (GitHub search, <openIssuesAsOf>)"), so an impossible date ships as the stated provenance of the count. The same package already has the real-calendar helper for exactly this —isCalendarDate(derive.ts:75), used byrowDate/ymdLabel— the validator just doesn't use it.
Evidence (verified this run, main e764f4e)
Laptop probe ~/git/fleet/probe-2026-11-01-laneB-projcfg/probe.ts, importing the real validateProjectConfigs, parseRef, and refUrl from the laptop checkout (project-config.ts sha256 acd7cbe0…, model.ts sha256 f987be93…, both matching sandbox main e764f4e):
asOf 2026-02-30: errors=[]
asOf 2026-13-01: errors=[]
asOf 2026-00-00: errors=[]
asOf 2026-04-31: errors=[]
asOf control 2026-02-28: []
ref a/b/c#12: validationErrors=[] parseRef=THROW: not a repo-qualified ref: a/b/c#12 refUrl=THROW
ref a$/b#12: validationErrors=[] parseRef=THROW: not a repo-qualified ref: a$/b#12 refUrl=THROW
ref a+b/c#3: validationErrors=[] parseRef=THROW: not a repo-qualified ref: a+b/c#3 refUrl=THROW
ref developing-today/code#1: validationErrors=[] parseRef=ok refUrl=https://github.com/developing-today/code/issues/1
Why it matters
The registry is edited by hand as the documented way to add a project ("Adding a project is a config change here"). The validator plus its test (validateProjectConfigs(PROJECT_CONFIGS) must equal [], test/program.test.ts:171) are the whole safety net for those edits. A check that disagrees with the consumer gives false confidence in both directions the fleet has already been bitten by: #2485 is the same failure shape one layer down (bad refs pass a gate, refUrl throws at render), filed for feed data; this is the static-registry instance of it.
Acceptance criteria
validateProjectConfigsrejects any ref thatparseRef(model.ts) would reject — ideally by sharing one pattern/parser instead of a second hand-rolled regex — including extra path segments and characters outside[\w.-]in either segment.openIssuesAsOfvalidation requires a real calendar date (month 01-12, day valid for the month/year, leap years correct), reusingisCalendarDatefrom derive.ts or an equivalent check;2026-02-30,2026-13-01,2026-00-00,2026-04-31produce errors,2026-02-28and2024-02-29do not.- Regression tests in test/program.test.ts alongside the existing "validation catches duplicates and malformed entries" cases; the shipped
PROJECT_CONFIGSstill validate to[]. - No render-path changes needed: this is the validator agreeing with its consumers.
Related: #2485 (feed taskRefs, same throw-at-render shape, different gate and data path).
Activity
developing-today commentedon Nov 1, 2026
CODE-1522
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
18 remaining items
Merge pull request #4538 from developing-today/queue/6229-3766-projec…
developing-today commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/low). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 4, 2026
🤖 Agent note · done
parseRefthrows on and impossibleopenIssuesAsOfdates.pm-stack/aggregator/src/project-config.ts:641still carried the looseREF_PATTERN = /^[^/\s]+\/[^#\s]+#\d+$/and:696the shape-only/^\d{4}-\d{2}-\d{2}$/date check, whileparseRef(model.ts) requires/^([\w.-]+\/[\w.-]+)#(\d+)$/andisCalendarDate(derive.ts:75) already existed unused by the validator. The canonical fix, PR fix(aggregator): align project config validation (#3766) #4538 (branchqueue/6229-3766-project-config-ref-validation, from task 6229), was already open: I verified its diff against every acceptance criterion —checkRefsnow callsparseRefitself,openIssuesAsOfadditionally requiresisIsoDate, and regression tests covera/b/c#12,a$/b#12,a+b/c#3,2026-02-30,2026-13-01,2026-00-00,2026-04-31,2026-02-29(invalid) and2024-02-29(valid). Checks green (metered-provider guard SUCCESS, CodeRabbit NEUTRAL), no Codex review findings, mergeable CLEAN — merged 2026-11-03T15:56:52Z, merge sha eef89b9; issue aggregator(project-config): registry validator accepts refs parseRef throws on and impossible openIssuesAsOf dates — a 'valid' config can break /program at render #3766 closed by the merge. Task 8287 completes as fixed_merged; no competing PR or follow-up task created.