feat: add generalized onboarding system graph - #153
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e280c410b2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "PR-4c of the 2026-08 graph-consolidation audit's thin-domain rebalancing (the last of the three): domain.machine's own routeWhen names 'evals' as one of its six maintenance pillars, alongside versioning, graph integrity, source freshness, package parity, and runtime synchronization — but unlike the other pillars, nothing dispatchable owned it. The LaunchBench scenario suite and the agent-behavior eval suite both ran only as steps inside npm run audit, with no workflow node a maintainer session could point at directly. Added workflow.machine.eval-suite-execution-maintainer (catalog/workflows/maintenance.ts), gated on check:agent-evals.", | ||
| "launchbench could not be named in the new workflow's gates: catalog/gates.ts's discoverGates() only picks up check:/validate:/render:/catalog:-prefixed npm scripts, and launchbench is deliberately named for the aggregate harness it runs as its own serial audit step, not a narrow check. evals:behavioral (live-agent runs) is excluded from gates for an unrelated reason — cost and run-to-run variance make it unfit as a merge gate. Both are named in the workflow's trigger text instead, with the reason for each exclusion kept distinct rather than conflated.", | ||
| "Re-rendered the catalog (57 to 58 workflows; domain.machine workflows are excluded from the dispatchable/founder-facing projections by catalog/bridge.ts's toCatalogInput(), same as domain.process/orchestration, so this workflow appears in catalog/generated/catalog.json but not routing.md/spine.md). Updated two hardcoded workflow-count assertions in verification/fixtures/catalog.fixtures.ts (57 to 58 total; 14 to 15 excluded system/machine-domain workflows) that would otherwise have gone stale silently." | ||
| "Replaced the coarse onboarding doctrine with a generalized ONB-00 through ONB-22 nested graph. The graph now traces the running system, fans out current guidance, competitor review, authorized Onbo Hub, internal B2C, provider and policy, and 60fps evidence, joins decisions before design, and continues through first value, activation, state, analytics, complete screen and control design, visual proof, Compound Engineering planning, hard cutover, and zero-legacy verification.", |
There was a problem hiding this comment.
Publish a new engine version for this graph
This replaces the release notes while leaving version at the parent's 0.103.0 and updatedAt at 2026-08-07. Because check-skill-version.ts compares only the semantic versions, an installed copy from before this commit will compare equal to this source and pass freshness even though it lacks the onboarding graph, validator, and role changes. Bump the root, lockfile, runtime-package, and skill manifest versions together so existing installations are detected as stale.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
| registerProvidersAndSecrets, | ||
| registerStore, | ||
| registerDesign, | ||
| registerOnboarding, |
There was a problem hiding this comment.
Wire the onboarding gate into the runnable audit
This registers fixtures for the new validator but not the validator itself. I checked both package manifests and tooling/lib/audit-plan.ts: neither exposes or executes check-onboarding-graph.ts, so npm run audit, installed-runtime audits, and the documented agent command never validate an actual business workspace. A project can therefore mark onboarding done with missing graph nodes or legacy code while the standard audit remains green; add a package script in both layouts and an audit-plan step.
Useful? React with 👍 / 👎.
| ## Emotional Card Timing | ||
| Every screen has one dominant action and a stable semantic ID. | ||
|
|
||
| | Screen ID | Purpose, evidence, exact copy | Actions | States | Motion | Analytics | Accessibility and localization | Design proof | |
There was a problem hiding this comment.
Preserve the Copy-column contract in the new inventory
When a launched business completes this template, check:app-copy cannot recognize the new screen table: copyColumnCells() only accepts a table whose third header begins with Copy, while this table puts “exact copy” in the second column. Once lanes.onboarding.status becomes done, the standard audit emits app_copy.onboarding_copy_table_missing even if every screen and deck string was authored, blocking completion. Keep a compatible Copy column or update the parser and its fixtures together.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
| const headings = [...markdown.matchAll(/^##\s+(.+)$/gm)].map((match) => match[1]?.trim()).filter(Boolean) as string[]; | ||
| const sectionList = headings.map((heading) => `<li>${escapeHtml(heading)}</li>`).join("\n"); |
There was a problem hiding this comment.
Render the onboarding contract instead of only its headings
For every generated product/onboarding.html, this path discards the Markdown body and retains only the level-two heading names. The resulting page contains none of the graph rows, evidence, screen/control behavior, analytics, paywall, or cutover details and does not even link to the source, despite product/onboarding.html being shipped as the rendered onboarding contract. Anyone reviewing the HTML sees a table of contents rather than the artifact; render the source content, or at minimum embed a faithful searchable source view.
Useful? React with 👍 / 👎.
| ); | ||
| } | ||
|
|
||
| if (artifact) { |
There was a problem hiding this comment.
Honor deferred onboarding before validating the artifact
When lanes.onboarding.status is deferred or not_needed, skip suppresses only the missing-lane and missing-file checks; any retained ONBOARDING.md still enters this block and receives mandatory-section, node, phrase, and policy errors. Existing businesses that explicitly defer onboarding but retain their older onboarding document therefore cannot run this validator successfully. Guard the artifact checks with !skip so an approved lane deferral actually skips the gate.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c2495fdbc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| reportAndExit("Onboarding system graph check", issues); | ||
|
|
||
| function hasHeading(text: string, heading: string): boolean { | ||
| return new RegExp(`^##\s+${escapeRegex(heading)}\s*$`, "mi").test(text); |
There was a problem hiding this comment.
Preserve backslashes in the dynamic regexes
For every normal ONBOARDING.md, JavaScript consumes the single \s escapes before RegExp sees them, so this pattern becomes ^##s+...s*$ and reports every required heading as absent; the new baseline fixture expects exit 0, so LaunchBench and audit:ci remain red. The row matcher at line 258 and word-boundary matcher at line 198 have the same single-backslash defect, so preserve the regex escapes consistently.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
|
|
||
| if (laneStatus === "done") { | ||
| const liveText = stripFencedBlocks(text); | ||
| const placeholders = [/\bnot_started\b/i, /\bTODO\b/i, /\bTBD\b/i, /\bplaceholder\b/i, /\bRecord\b/i]; |
There was a problem hiding this comment.
Limit placeholder detection to template fields
When lanes.onboarding.status is done, the case-insensitive Record pattern scans the entire artifact rather than known placeholder cells. Ordinary completed prose—including the shipped description Canonical execution record—therefore triggers onboarding_graph.placeholder_complete even after all actual placeholders and graph statuses are filled, so otherwise valid onboarding work cannot pass without deleting legitimate wording.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c763d0700
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ## Ownership and dispatch | ||
|
|
||
| Load `analytics-attribution.md` before locking onboarding event names, attribution-source options, paywall variants, or the dashboard plan. Onboarding should implement the approved analytics catalog, not invent events while building screens. | ||
| `workflow.experience.onboarding-conversion` owns the nested graph. The orchestrator is the single writer for `product/ONBOARDING.md`, `product/onboarding.html`, state, canonical IDs, pricing, provider mutations, cutover, and final readiness. |
There was a problem hiding this comment.
Encode the nested graph in catalog definitions
When this workflow runs through the durable engine, core/engine/compile.ts creates run nodes only from catalog.workflows, but the commit adds ONB-00 through ONB-22 only to Markdown and templates while leaving catalog/workflows/product-experience.ts unchanged. The engine therefore still compiles one coarse onboarding node, so the documented dependencies, checkpoints, retries, and serialized resource/provider work cannot be enforced or resumed; add a typed nested execution contract or catalog nodes and regenerate the catalog projections.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00758f8a89
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * durable engine can schedule, checkpoint, retry, resume, and verify the nested graph. Only | ||
| * ONB-22 writes the canonical onboarding artifacts, preserving the catalog's single-writer rule. | ||
| */ | ||
| const onboardingGraphWorkflows = [ |
There was a problem hiding this comment.
Commit the regenerated catalog projections
Adding this 22-node workflow list raises the authored catalog from 58 to 80 workflows, but catalog/generated/catalog.json still contains 58 and verification/fixtures/catalog.fixtures.ts still asserts 58. Consequently the standard catalog:render-routing -- --check/fixture audit fails, and consumers of the generated catalog cannot see any onboarding nodes; regenerate and commit the projections and update the catalog fixture with the definition change.
AGENTS.md reference: AGENTS.md:L50-L50
Useful? React with 👍 / 👎.
| const lock = readJson("package-lock.json"); | ||
| lock.version = "0.104.0"; | ||
| if (lock.packages?.[""]) lock.packages[""].version = "0.104.0"; | ||
| writeJson("package-lock.json", lock); |
There was a problem hiding this comment.
Update the runtime lock before checking package parity
When this finalizer runs, it changes skill/b2c-mobile-business-launch/package.json to 0.104.0 but updates only the repository-root lockfile; the runtime lock at skill/b2c-mobile-business-launch/package-lock.json remains 0.103.0. The later check:package-parity step explicitly compares that runtime lock against the runtime package, so the job exits before committing or pushing any intended integration. Fresh evidence beyond the earlier version finding is this newly added finalizer's guaranteed failing parity sequence.
AGENTS.md reference: AGENTS.md:L50-L50
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| function stripFencedBlocks(text: string): string { |
There was a problem hiding this comment.
Reject renamed placeholders before accepting completion
When a workspace marks onboarding done after replacing not_started with done and changing every Record placeholder to an arbitrary word such as Completed, this matcher reports no placeholders even though none of the evidence, policy, design, analytics, or cutover cells were actually filled. The new completed fixture performs exactly those two global replacements and expects success, so an untouched template can produce a false launch-ready result; validate completed cells structurally rather than recognizing only the literal Record prefix.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33561664ee
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Analytics uses one machine-readable schema and typed clients. Distinguish client interaction, backend-confirmed product outcome, provider-confirmed monetization, and derived metrics. One business outcome has one authoritative emitter. Define event IDs, identity stitching, offline queueing, ordering, deduplication, replay, webhook idempotency, experiment exposure, privacy, and expected event-sequence tests. Analytics failure never blocks first value. | ||
|
|
||
| **Paid intro offers as a free-trial alternative.** The 2026 report flags a structural shift: paid intro offers (e.g. `$0.99` for the first month/week, then auto-renewing to full price) are increasingly replacing free trials because they create commitment, reduce trial abuse, improve early cash flow, and often convert at higher quality. Context to calibrate against, not copy blindly: only ~9.3% of apps currently use promotional offers, yet ~30% of new subscribers (median) enter through an intro discount — and reliance is inverted by scale (hobby-tier apps often run 65–99% of new subs through intro offers, while top performers rely on them for ~0–10%). Treat a low-priced paid intro as one candidate alongside a free trial in the plan-mix hypothesis, disclose the renewal price/terms clearly (see `paywall-pricing-and-experiments.md` §2), and avoid building a business that *depends* on permanent heavy discounting. This is a founder-approved pricing decision (`revenue-monetization.md` §2). | ||
| Earn review eligibility after real value and engagement. Request through native platform APIs outside first-run onboarding at a later natural success. No custom star screen, sentiment gate, incentive, or happy-user routing. Record only observable eligibility, suppression, request attempt, and API return facts. |
There was a problem hiding this comment.
Align the remaining review-prompt doctrine
When an onboarding run also loads the current emotional-design or lifecycle guidance, this new rule conflicts with knowledge/experience/emotional-design-system.md:283-287, knowledge/experience/push-notification-lifecycle.md:26-29, knowledge/experience/consumer-product-design-agency.md:139-141, and knowledge/growth/influencer-sponsorship-engine.md:195-200, which still require or endorse a review request immediately after first value inside onboarding. An agent can therefore implement the obsolete timing while leaving this canonical phrase in the artifact, allowing the phrase-based validator to pass even though the implementation violates the new behavior and eval; update those routed references with this contract.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3da7f36c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "The artifact must cover purchase, restore, handoff, identity, nonblocking analytics, unsupported-client, and observability behavior.", | ||
| ); | ||
|
|
||
| if (laneStatus === "done") { |
There was a problem hiding this comment.
Validate completion before accepting ONB-22
When ONB-22 invokes check:onboarding-graph, the onboarding lane can still be not_started or partial, because the engine accepts the workflow only after its gate passes. This guard therefore skips every placeholder and node-completion check; onboarding.fixtures.ts even asserts that the untouched shipped template exits successfully. Fresh evidence beyond the earlier placeholder finding is this runtime ordering: the validator is ONB-22's only gate, so the engine can accept the final execution-and-cutover node while all 23 rows remain not_started; make the workflow gate explicitly require completion rather than deriving strictness from lane state.
Useful? React with 👍 / 👎.
| laneIds: ["onboarding"], | ||
| phaseIds: ["phase.2"], | ||
| dependencies: ["workflow.experience.onboarding-system.onb-16-journey-graph"], | ||
| outputPaths: ["product/onboarding/graph/ONB-18-visual-design-prototype.md"], |
There was a problem hiding this comment.
Track the actual design artifact for ONB-18
When the durable engine runs ONB-18, its only declared result is this Markdown packet and the node has neither a gate nor a dependency on the Design Room workflow. The engine can consequently accept ONB-18 and unblock ONB-20 without producing the high-fidelity design or interactive prototype promised by the node; the final validator only inspects wording in ONBOARDING.md, not the referenced artifact's existence. Declare the real rendered/design-state outputs or depend on and verify the workflow that produces them.
Useful? React with 👍 / 👎.
What changed
ONB-00throughONB-22execution contract.Why
Formation needs onboarding work to execute as a source-backed, cross-functional system spanning acquisition, first value, activation, monetization, identity, analytics, lifecycle, implementation, cutover, and legacy removal, rather than as a loose screen sequence.
Validation required before merge