diff --git a/docs/hygiene-history/ticks/2026/05/16/0727Z.md b/docs/hygiene-history/ticks/2026/05/16/0727Z.md new file mode 100644 index 000000000..db1609378 --- /dev/null +++ b/docs/hygiene-history/ticks/2026/05/16/0727Z.md @@ -0,0 +1,81 @@ +# Tick 2026-05-16T07:27Z — Otto-CLI + +Twenty-seventh tick of the resume-session series. Rate at +**1132/5000** (cost-aware tier; 1 PR/tick max). Audited B-0509 — +**second 2nd-FP-class verification in a row**. NOT drift; leave +open. Documenting the empirical FP-rate pattern for the audit tool. + +## Refresh result + +| Surface | State | +|---|---| +| Cron sentinel | Alive (`bd1c7739`) | +| Rate limit (GraphQL) | **1132/5000** (cost-aware tier) | +| `origin/main` | Advanced — peer landed PRs #3790 (B-0557 slice 3 chdir) + #3796 (Lior shadow log) | + +## Audit: B-0509 — 2nd FP class confirmed + +[B-0509](../../../../../backlog/P1/B-0509-b0448-slice3-install-ts-cloud-schedule-extension-2026-05-14.md) (`B-0448 slice 3 — Extend tools/routines/install.ts to detect + surface cloud-schedule.json`). Path flagged: `tools/routines/install.ts`. + +**Per-acceptance grep** (zero gh): + +```bash +grep -E 'cloud.schedule|cloud-schedule' tools/routines/install.ts +# (no matches) +``` + +Acceptance items 1-4 specifically reference `readCloudSchedule` / +`cloudSchedule` field / "Cloud Routine next-step guidance" — none of +which exist in the current `install.ts`. The file exists for +**B-0448 slice 1** (original install scaffolding); the B-0509-specific +cloud-schedule extension was **never shipped**. + +**Conclusion**: **2nd FP class** (same as B-0418 last tick). NOT +drift; do NOT close. Leave row open as accurately reflecting +unimplemented work. + +## Empirical FP-rate observation + +Two consecutive 2nd-FP-class verifications (B-0418 + B-0509) on +candidates flagged by the audit tool. The pattern: + +| Row | Primary artifact path | Actual ship target | Acceptance miss | +|---|---|---|---| +| B-0418 | `tools/dashboard/generate-metrics.ts` | B-0414 | `amplification_ratio_today` field absent | +| B-0509 | `tools/routines/install.ts` | B-0448 slice 1 | `cloud-schedule` references absent | + +In both cases, the path is a **shared tool** that was originally +shipped for a DIFFERENT row. The audit tool's single-artifact- +existence check can't distinguish. + +**Hypothesis for future-tool-improvement** (peer Otto's B-0557 lane): +add a "feature-grep" sub-check that scans the artifact for +acceptance-named identifiers. If the named API/field/method +doesn't appear in the artifact, demote the candidate from +drift-candidate to FP. + +## Drift-audit progress tally + +After this tick: + +| Class | Count | Examples | +|---|---|---| +| 1 (Pure drift, closed) | 9 | B-0506/B-0530/B-0535/B-0494/B-0159 + 4 peer | +| 2 (Partial, Status-annotated) | 4 | B-0517/B-0537/B-0532/B-0533 | +| 3 (Multi-slice, children open, verified) | 1 | B-0440 | +| 4 (Multi-slice, all children closed, closed) | 1 | B-0159 | +| FP (2nd FP class verified) | **2** | B-0418, **B-0509 (this tick)** | +| **Total triaged** | **17 of ~38** | | + +## Sentinel + close + +`CronList`: `bd1c7739` alive. + +## Visibility signal + +- B-0509 verified as 2nd FP class (no edit) +- FP-rate pattern noted: shared-tool paths are FP-prone +- Hypothesis filed for peer's audit-tool-improvement lane +- Sentinel `bd1c7739` alive +- Rate 1132/5000 (cost-aware) +- ~21 audit candidates remaining diff --git a/tools/hygiene/audit-backlog-status-drift.test.ts b/tools/hygiene/audit-backlog-status-drift.test.ts index dc7c28725..7e0e194b9 100644 --- a/tools/hygiene/audit-backlog-status-drift.test.ts +++ b/tools/hygiene/audit-backlog-status-drift.test.ts @@ -177,6 +177,40 @@ Add \`tools/scope-target.ts\`. expect(paths).toEqual(["tools/x.ts"]); }); + test("MIXED_BULLET: deliverable BEFORE inline cross-ref token is extracted", () => { + // B-0557 slice 4: mixed bullets where a path appears before a + // cross-ref token should still extract the path. The previous behaviour + // skipped the WHOLE line when any cross-ref keyword matched, dropping + // the deliverable along with the citation. + const body = `## Acceptance + +- Add \`tools/deliverable.ts\` per [B-0123] convention +- Wire \`tools/foo.ts\` (see also \`tools/sibling.ts\` for shape) +`; + const paths = extractPrimaryArtifacts(body); + expect(paths).toContain("tools/deliverable.ts"); + expect(paths).toContain("tools/foo.ts"); + // The post-cross-ref paths are siblings, NOT deliverables. + expect(paths).not.toContain("tools/sibling.ts"); + }); + + test("MIXED_BULLET: pure cross-ref bullets still skip (regression check)", () => { + // Sanity: bullets that LEAD with a cross-ref keyword still produce no + // extraction — the pre-cutoff segment is just the bullet marker. + const body = `## Acceptance + +- New \`tools/primary.ts\` +- Composes with \`.claude/rules/bar.md\` +- See also \`tools/legacy.ts\` for prior art +- Per \`tools/older.ts\` convention +`; + const paths = extractPrimaryArtifacts(body); + expect(paths).toEqual(["tools/primary.ts"]); + expect(paths).not.toContain(".claude/rules/bar.md"); + expect(paths).not.toContain("tools/legacy.ts"); + expect(paths).not.toContain("tools/older.ts"); + }); + test("Empirical case from B-0553: composes_with paths NOT in primary sections must be skipped", () => { const body = `--- id: B-0116 diff --git a/tools/hygiene/audit-backlog-status-drift.ts b/tools/hygiene/audit-backlog-status-drift.ts index 75aaf06bc..a768298c5 100644 --- a/tools/hygiene/audit-backlog-status-drift.ts +++ b/tools/hygiene/audit-backlog-status-drift.ts @@ -166,12 +166,21 @@ export function extractPrimaryArtifacts(body: string): string[] { const inPrimarySection = sectionMode === "primary"; if (!inPrimarySection) continue; - // Skip inline cross-reference lines (e.g. "Composes with `tools/x.ts`" - // bullets inside an Acceptance sub-section — these are siblings, not - // deliverables). - if (INLINE_CROSSREF_PATTERNS.some((re) => re.test(line))) continue; + // Mixed-bullet handling per B-0557 slice 4: extract paths from the + // segment BEFORE the first inline cross-reference keyword. Pure + // cross-ref bullets ("Composes with X") naturally produce an empty + // pre-cutoff segment; mixed bullets ("Add `tools/foo.ts` per [X]") + // extract the deliverable while ignoring the citation. + let cutoffIndex = line.length; + for (const re of INLINE_CROSSREF_PATTERNS) { + const m = line.match(re); + if (m && typeof m.index === "number" && m.index < cutoffIndex) { + cutoffIndex = m.index; + } + } + const extractableSegment = line.slice(0, cutoffIndex); - for (const match of line.matchAll(PATH_REGEX)) { + for (const match of extractableSegment.matchAll(PATH_REGEX)) { const candidate = match[0]; // Skip backlog-row cross-references (these are siblings, not deliverables). if (candidate.startsWith("docs/backlog/")) continue;