This document defines the concrete file, page, registry, and handoff contracts used by the outcome-first workflow. Use it when deciding what to build and where to inject it.
1. Required Build Plan Shape
Every implementation plan must include:
type OutcomeType =
| 'design-system-component'
| 'gallery-documentation-page'
| 'appflow-screen'
| 'static-design-library-page'
| 'token-foundation-change'
| 'icon-change'
| 'documentation-rule-change'
interface BuildPlan {
outcomeType: OutcomeType
userGoal: string
reuseDecision: 'reuse-existing' | 'extend-existing' | 'create-new' | 'assemble-only'
filesToRead: string[]
filesToChange: string[]
registryUpdates: string[]
routePath?: string
validationCommands: string[]
approvalRequired: boolean
}
The plan must be approved before implementation when it adds components, tokens, routes, registry entries, Code Connect mappings, persisted workflow state, or new workflow rules.
2. Workflow State And Resume Contract
Workflow artifacts are chat-native by default. Agents must not assume prior session state exists unless it is visible in the current conversation or re-confirmed by the user.
Lifecycle:
WorkflowRunStatestarts at intake and is updated at each phase.BuildPlanis produced before implementation and approved when required.AgenticImplementationPlanexpands the approved plan into file targets and injection points.PatchSetsummarizes files changed after implementation.ValidationApprovalLogorBlockedValidationReportcloses the run.
Resume rule:
- If a task resumes after interruption, re-state
WorkflowRunState, prior approval status, loop count, files already changed, and the next intended action. - If prior approval is not visible in the current context, ask the user to confirm before continuing implementation.
- Persisted local state is optional. If introduced for automation, it must live under git-ignored
.spring/and must not replace docs, code, or the final handoff as source of truth.
Current decision: do not create .spring/ state files for normal Cursor workflows. Add .spring/workflow-state.json and .spring/validation-log.json only when a real automated workflow runner needs cross-session recovery.
3. File Placement Matrix
| Outcome | Implementation file | Injection point | Validation |
|---|---|---|---|
| Reusable component | packages/spring-ds-react/src/components/<category>/<ComponentName>.tsx | packages/spring-ds-react/src/index.ts | npm run lint, npm run build |
| Component Code Connect | Package-side *.figma.tsx for reusable component mappings | figma.config.json parse surface | npm run code-connect:parse |
| Component gallery page | apps/design-library/src/gallery/pages/components/<category>/<ComponentName>Page.tsx | route shell + libraryNav.ts | npm run build |
| Gallery doc page | apps/design-library/src/gallery/pages/ | route shell + libraryNav.ts | npm run build |
| AppFlow screen | apps/design-library/src/gallery/page/appflow/screens/AppFlow<Name>Screen.tsx | personalLoanFlow.ts | npm run build, targeted manual QA when flow behavior changes |
| Static page | apps/design-library/src/gallery/pages/ or a named gallery subfolder | route shell + libraryNav.ts | npm run build |
| Token change | packages/spring-ds-react/src/tokens/design-tokens.mjs | generated token artifacts | npm run tokens:sync |
| Icon change | packages/spring-ds-react/src/icons/ | icon barrels and gallery manifest if needed | npm run icons:sync, then build when consumed |
| Docs/rules | docs/ or .cursor/rules/ | docs indexes | link and stale-reference review |
4. Component Injection Contract
Use this contract when an outcome creates or changes reusable UI.
Required checks:
- Inspect
packages/spring-ds-react/src/index.tsfor existing exports. - Inspect the likely category folder under
packages/spring-ds-react/src/components/. - Inspect nearby gallery pages under
apps/design-library/src/gallery/pages/components/. - Confirm whether the request needs Code Connect.
Required injection:
- Export public components and types from
packages/spring-ds-react/src/index.ts. - Keep package components presentation-focused and token-based.
- If a gallery page is included, import the component from
@spring/ds-react. - If navigation is included, update
apps/design-library/src/gallery/navigation/libraryNav.ts.
Do not:
- Add raw hex colors or arbitrary pixel values.
- Create a component only for one gallery page unless the plan explicitly approves a reusable primitive.
- Put gallery documentation logic inside the package component.
5. Gallery Page Contract
Use this contract for documentation pages and static library pages.
Required structure:
import SomeGalleryPage from '@/gallery/pages/.../SomeGalleryPage'
export default SomeGalleryPage
Rules:
- Route shells under
apps/design-library/src/app/library/should stay thin. - Page implementations belong under
apps/design-library/src/gallery/. - Live pages may be added to
libraryNav.ts. - Placeholder-only pages must stay out of navigation.
- Internal links should use Next.js primitives when implemented inside app code.
Required validation:
- Route path resolves to the intended gallery implementation.
- Navigation path matches the route.
npm run build.
6. AppFlow Screen Contract
Use this contract for personal loan flow screens.
Required screen export:
export function ExampleStep() {
return (
// Presentational step body only.
)
}
Required registry fields in personalLoanFlow.ts:
orderslugtitleshortLabelpathphasesummarypreviewKindstatusprogressBodysourcePath
Rules:
- Use the existing AppFlow shell for chrome, route framing, progress placement, and preview behavior.
- Screen files should not perform production data fetching, persistence, analytics, or routing side effects.
- Use existing Spring DS components for inputs, selectors, buttons, progress, and modal patterns.
- When a new reusable primitive is needed, route through the component contract first.
Required validation:
- The screen is imported into
personalLoanFlow.ts. - The step registry has a stable slug and source path.
- The route resolves under
/library/page/appflow/personal-loan/<slug>. - Run
npm run build; run targeted manual QA for flow or route behavior changes.
7. Token Change Contract
Use this contract when the design input cannot be mapped to existing tokens.
Required fields in a token gap report:
interface TokenGapReport {
requestedValue: string
visualRole: 'color' | 'spacing' | 'radius' | 'shadow' | 'typography' | 'other'
nearestExistingToken?: string
proposedTokenName?: string
affectedOutcomes: OutcomeType[]
requiresUserApproval: true
}
Rules:
- Prefer nearest existing semantic tokens.
- Add token values only after approval.
- Run
npm run tokens:syncafter source token changes. - Commit generated token artifacts only when they intentionally change.
- If a dev server is running, restart it after token sync before trusting the preview.
- Before production build verification for token changes, clear
apps/design-library/.nextso generated CSS is read fresh.
Validation sequence:
npm run tokens:sync
rm -rf apps/design-library/.next
npm run build
Run npm run lint as well when consuming component or gallery files changed.
8. Code Connect Contract
Use Code Connect when the outcome maps a reusable Figma component to code.
Decision tree:
New Code Connect mapping?
├─ Component is under packages/spring-ds-react/src/components/inputs/
│ └─ Place beside component: packages/.../inputs/<Name>.figma.tsx
├─ Existing gallery-side legacy pattern?
│ └─ Keep in gallery: navigations, overlays, SpringSearchBar
└─ New non-input reusable component?
└─ Default to package-side beside the component
Rules:
- Add package-side
*.figma.tsxwhen mapping new reusable package components. - Package-side placement is mandatory for input components under
packages/spring-ds-react/src/components/inputs/. - Keep gallery-side
*.figma.tsxonly for existing legacy patterns: navigations, overlays, andSpringSearchBar. - Run
npm run code-connect:parsewhenever*.figma.tsxchanges. - Do not add Code Connect files for one-off AppFlow screens unless the plan explicitly defines a reusable Figma component mapping.
Longer-term cleanup: migrate legacy gallery-side Code Connect mappings beside their package components when the team is ready to remove the split.
9. Handoff Artifacts
WorkflowRunState
interface WorkflowRunState {
outcomeType: OutcomeType
currentPhase: 'intake' | 'investigation' | 'planning' | 'implementation' | 'validation' | 'handoff' | 'blocked'
userApproval: 'not-needed' | 'needed' | 'approved' | 'changes-requested'
loopCount: number
filesChanged?: string[]
nextAction?: string
}
AgenticImplementationPlan
interface AgenticImplementationPlan {
outcomeType: OutcomeType
summary: string
reuseDecision: BuildPlan['reuseDecision']
fileMap: {
read: string[]
create: string[]
update: string[]
}
injectionPoints: string[]
validationCommands: string[]
risks: string[]
}
PatchSet
interface PatchSet {
outcomeType: OutcomeType
filesChanged: string[]
routePath?: string
exportsUpdated: string[]
registriesUpdated: string[]
generatedArtifacts: string[]
}
ValidationApprovalLog
interface ValidationApprovalLog {
commandsRun: string[]
passed: boolean
skippedCommands: Array<{ command: string; reason: string }>
dirtyTreeCaveats: string[]
remainingRisks: string[]
}
BlockedValidationReport
interface BlockedValidationReport {
failedCommand: string
errorSummary: string
filesInvolved: string[]
attempts: number
whatWasTried: string[]
recommendedUserDecision: string
}
10. Quick Investigation Checklist
Before implementation, answer these questions:
- What is the outcome type?
- Which existing component, page, token, or AppFlow step is closest?
- Which exact files need to be read?
- Which exact files need to be created or updated?
- Which registry, route, export, nav, Code Connect, or token generated artifact must be injected?
- Which validation commands prove the outcome?
- Does the user need to approve a new component, token, route, or structural deviation?