Skip to content

fix(seed): give the Acme AI governance workshop one schedule - #1687

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-1660-acme-workshop-one-schedule
Sep 6, 2026
Merged

fix(seed): give the Acme AI governance workshop one schedule#1687
os-steve merged 1 commit into
mainfrom
claude/issue-1660-acme-workshop-one-schedule

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #1660

One Acme workshop was seeded three different ways, and the task to book it was due a day after the meeting it asked someone to book.

What the three records said

record file said resolved to
crm_opportunity Acme Platform Upgrade next_step src/data/sales.seed.ts "the week of close_date - 14d" close_date = daysFromNow(30)daysFromNow(16)
crm_event Acme — AI agent governance workshop src/data/service.seed.ts status: 'planned', daysAgo: -6 daysFromNow(6)
crm_task Acme — schedule AI governance workshop src/data/service.seed.ts status: 'not_started', due_date: daysFromNow(7) daysFromNow(7) — a day after the workshop

The card attributed this to sales.seed.ts; both contradicting records are in service.seed.ts. Confirmed on origin/main and reflected in the file list.

Which record is canonical, and why — the event

Not a preference. Two things were measured:

1. The event is the only record another record derives from. The attendee builder (service.seed.ts) dates the invitation:

invited_date: celDaysAgo(Math.max(spec.daysAgo + (spec.invitedDaysBefore ?? 3), 0)),

For this row that is max(-6 + 9, 0) = daysAgo(3). So invitedDaysBefore: 9 means nine days before the event, and the invitation went out three days before the demo boots — a genuine past date, not the clamp floor. The card inferred the invite had gone out; this is the measurement behind it.

2. Acme has already answered it. The event's sole attendee is john.smith@acme.example.com with response: 'tentative'. A reply only exists if there was an invite. That is an act that has happened and been answered — it outranks two dates nobody has acted on.

By contrast next_step had no anchor of its own (its value was entirely parasitic on close_date, which #1646 just made load-bearing for the account description, and which this PR does not touch), and the task's due date was an authored number nothing else read.

What changed

  • The task is completed, not re-dated. Sending the invitation is the act of booking the workshop, so the task finished the day that happened: status: 'completed', completed_date and due_date both daysAgo(3), with is_completed: true / progress_percent: 100 mirrored the way the seed book already mirrors what task_completion would stamp (Send welcome package to Stark Medical is the existing precedent, and completed_date_required is an error-severity validation, so the stamp is mandatory). Re-dating would have kept the contradiction and only moved it.
  • next_step carries no date at all — absolute or relative. It states only what stays true however the event is scheduled (booked, invitation out) and leads with the work still genuinely open, the revised proposal, which the seed book already tracks as its own not_started task. The Math.max(…, 0) clamp means a planned event's invitation is never in the future, so "the invitation is out" cannot go stale either.
  • The event is untouched. So is close_date. No new gate (AGENTS.md:431 — Acme's seeded account description states a renewal horizon that matches no seeded record #1646's ruling already declined a guard for exactly this shape).

The story a reader now gets, opening the three records in any order: the workshop was booked three days ago, Acme has tentatively accepted, it happens in six days, and the only thing still owed on the deal is the proposal.

Seed guards — re-run, no movement

test/seed-consistency.test.ts, test/seed-validation-warnings.test.ts and test/activity-seed-coverage.test.ts: 3 files, 60 tests, all passed. Neither pinned set moved.

activity-seed-coverage was the one at real risk — it walks t.status === 'completed' || t.is_completed === true into bubbleTargets(), so a newly-completed task bubbles last_activity_date onto its account. Acme Corporation is already last_activity_date: celtoday()`` from a held event two days ago, so both directions of that guard ("keeps held interactions away from the quiet accounts" and "authors today() on every account a seeded activity bubbles to") are satisfied unchanged.

Movement this does cause

Two counts move by one, both intended, neither pinned by any test:

  • Tasks Completed tile (activity.dashboard.ts, filter: { is_completed: true }): 1 → 2
  • My Priority Tasks view (task.view.ts, status in [not_started, in_progress]priority in [high, urgent]): 4 → 3 rows, still non-empty (Follow up with Acme on proposal, Acme — close out login-issues ticket before SLA, Prepare contract for Wayne Enterprises)

Nothing else counts not_started tasks: the only other consumers are hooks/flows that write the status and the overdue_tasks view, which filters is_completed = false and so excludes a completed task regardless of its due date.

Token ratchet: zero cost. check-source-token-ratchet.mjs declares EXCLUDED = ['src/translations', 'src/data'] — seed data is outside the ratchet entirely by ruling. Measured rather than assumed: reverting both files to the merge-base and re-running gives a byte-identical reading (~85,032 / ~37,963 / ~137,336), restore proven by blob-hash equality against HEAD.

Verification

pnpm verify fully green — exit 0 across all eight stages:

✓ Validation passed (1842ms)          tsc --noEmit clean          objectstack lint
✓ i18n lint gate: 0 `i18n/missing-*` issues
✓ source hygiene clean                ✓ source token ratchet clean
✓ Build complete (2077ms)
Test Files  161 passed (161)          Tests  3414 passed | 1 skipped (3415)

Note for #1661

The Acme contract card reads the two opportunities this PR touches. Nothing here changes an opportunity's identity, amount, stage or close_date — only next_step prose on Acme Platform Upgrade, which no longer dates the workshop. #1661 can treat the workshop's date as owned solely by the crm_event row.

🤖 Generated with Claude Code

https://claude.ai/code/session_018xtjdpZFjgWh4Ad9Wcx68J


Generated by Claude Code

The workshop was seeded three different ways. The opportunity's `next_step`
placed it "the week of close_date - 14d" (close_date is daysFromNow(30), so
daysFromNow(16)); the `crm_event` row books it at daysFromNow(6); and the
`crm_task` to schedule it was `not_started` and due daysFromNow(7) — a day
after the meeting it asked someone to book.

The event is now the single place the date is authored. It is the record with
a real instant in the world (start, 90 minutes, location, attendee) and the
only one another record derives from: the attendee builder dates the
invitation daysAgo(max(daysAgo + invitedDaysBefore, 0)) = daysAgo(3), so the
invite went out three days before boot and john.smith@acme.example.com has
already answered `tentative`.

Because sending that invitation IS the act of booking the workshop, the task
is completed rather than re-dated — an open "schedule it" task beside a
booked-and-invited meeting is the contradiction itself. It carries
completed_date and due_date of daysAgo(3) plus the is_completed /
progress_percent stamps the seed book already mirrors for a completed task.

`next_step` now carries no date at all, absolute or relative: it states only
what stays true however the event is scheduled (booked, invitation out) and
leads with the work still open, the revised proposal. The event and the
opportunity's close_date are untouched.

Co-authored-by: Claude
@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 6, 2026 10:35am UTC

Request Review

@github-actions github-actions Bot added the metadata Declarative metadata — schema, security posture, UI surfaces label Sep 6, 2026
@os-steve
os-steve marked this pull request as ready for review September 6, 2026 10:38
@os-steve
os-steve added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 65e4968 Sep 6, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The Acme AI governance workshop is scheduled three different ways across three seeded records, and the task to book it is due a day after the event

2 participants