All docs

Docs

Agentic Workflow Contracts

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:

  1. WorkflowRunState starts at intake and is updated at each phase.
  2. BuildPlan is produced before implementation and approved when required.
  3. AgenticImplementationPlan expands the approved plan into file targets and injection points.
  4. PatchSet summarizes files changed after implementation.
  5. ValidationApprovalLog or BlockedValidationReport closes 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

OutcomeImplementation fileInjection pointValidation
Reusable componentpackages/spring-ds-react/src/components/<category>/<ComponentName>.tsxpackages/spring-ds-react/src/index.tsnpm run lint, npm run build
Component Code ConnectPackage-side *.figma.tsx for reusable component mappingsfigma.config.json parse surfacenpm run code-connect:parse
Component gallery pageapps/design-library/src/gallery/pages/components/<category>/<ComponentName>Page.tsxroute shell + libraryNav.tsnpm run build
Gallery doc pageapps/design-library/src/gallery/pages/route shell + libraryNav.tsnpm run build
AppFlow screenapps/design-library/src/gallery/page/appflow/screens/AppFlow<Name>Screen.tsxpersonalLoanFlow.tsnpm run build, targeted manual QA when flow behavior changes
Static pageapps/design-library/src/gallery/pages/ or a named gallery subfolderroute shell + libraryNav.tsnpm run build
Token changepackages/spring-ds-react/src/tokens/design-tokens.mjsgenerated token artifactsnpm run tokens:sync
Icon changepackages/spring-ds-react/src/icons/icon barrels and gallery manifest if needednpm run icons:sync, then build when consumed
Docs/rulesdocs/ or .cursor/rules/docs indexeslink and stale-reference review

4. Component Injection Contract

Use this contract when an outcome creates or changes reusable UI.

Required checks:

  1. Inspect packages/spring-ds-react/src/index.ts for existing exports.
  2. Inspect the likely category folder under packages/spring-ds-react/src/components/.
  3. Inspect nearby gallery pages under apps/design-library/src/gallery/pages/components/.
  4. 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:

  • order
  • slug
  • title
  • shortLabel
  • path
  • phase
  • summary
  • previewKind
  • status
  • progress
  • Body
  • sourcePath

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:sync after 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/.next so 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.tsx when 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.tsx only for existing legacy patterns: navigations, overlays, and SpringSearchBar.
  • Run npm run code-connect:parse whenever *.figma.tsx changes.
  • 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?