yadflow 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/README.md +65 -22
  3. package/bin/yad.mjs +27 -1
  4. package/cli/docs.mjs +298 -0
  5. package/cli/doctor.mjs +1 -0
  6. package/cli/manifest.mjs +23 -2
  7. package/cli/ship.mjs +37 -0
  8. package/docs/index.html +44 -13
  9. package/package.json +2 -2
  10. package/skills/sdlc/config.yaml +26 -2
  11. package/skills/sdlc/install.sh +1 -1
  12. package/skills/sdlc/module-help.csv +11 -4
  13. package/skills/yad-checks/references/check-gates.md +58 -2
  14. package/skills/yad-checks/templates/checks/commit-message.sh +82 -0
  15. package/skills/yad-checks/templates/github/yad-checks.yml +27 -0
  16. package/skills/yad-checks/templates/github/yad-hub-checks.yml +36 -0
  17. package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +20 -0
  18. package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +39 -0
  19. package/skills/yad-commit/SKILL.md +66 -0
  20. package/skills/yad-connect-docs/SKILL.md +132 -0
  21. package/skills/yad-connect-docs/references/docs-registry.md +74 -0
  22. package/skills/yad-docs/SKILL.md +159 -0
  23. package/skills/yad-docs/references/data-mapping.md +75 -0
  24. package/skills/yad-docs/references/theme-map.md +69 -0
  25. package/skills/yad-docs/templates/app/README.md +31 -0
  26. package/skills/yad-docs/templates/app/eslint.config.js +23 -0
  27. package/skills/yad-docs/templates/app/index.html +17 -0
  28. package/skills/yad-docs/templates/app/package-lock.json +4030 -0
  29. package/skills/yad-docs/templates/app/package.json +35 -0
  30. package/skills/yad-docs/templates/app/public/favicon.svg +28 -0
  31. package/skills/yad-docs/templates/app/public/logo.svg +39 -0
  32. package/skills/yad-docs/templates/app/public/vite.svg +1 -0
  33. package/skills/yad-docs/templates/app/src/App.tsx +98 -0
  34. package/skills/yad-docs/templates/app/src/components/Auth/LoginPage.tsx +101 -0
  35. package/skills/yad-docs/templates/app/src/components/Canvas/AnimatedMessage.tsx +101 -0
  36. package/skills/yad-docs/templates/app/src/components/Canvas/ConnectionLine.tsx +90 -0
  37. package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +216 -0
  38. package/skills/yad-docs/templates/app/src/components/Canvas/SystemComponent.tsx +153 -0
  39. package/skills/yad-docs/templates/app/src/components/Controls/PlaybackBar.tsx +284 -0
  40. package/skills/yad-docs/templates/app/src/components/Controls/StepDetail.tsx +167 -0
  41. package/skills/yad-docs/templates/app/src/components/DetailPanel/HandlerLogicSnippet.tsx +41 -0
  42. package/skills/yad-docs/templates/app/src/components/DetailPanel/RequestPayloadPreview.tsx +46 -0
  43. package/skills/yad-docs/templates/app/src/components/DetailPanel/RightPanel.tsx +88 -0
  44. package/skills/yad-docs/templates/app/src/components/DetailPanel/StatusCard.tsx +76 -0
  45. package/skills/yad-docs/templates/app/src/components/DetailPanel/TriggerEventCard.tsx +45 -0
  46. package/skills/yad-docs/templates/app/src/components/DocLayout/DocPageShell.tsx +80 -0
  47. package/skills/yad-docs/templates/app/src/components/DocLayout/DocSectionCard.tsx +55 -0
  48. package/skills/yad-docs/templates/app/src/components/DocLayout/DocTableOfContents.tsx +79 -0
  49. package/skills/yad-docs/templates/app/src/components/DocLayout/RoleCard.tsx +67 -0
  50. package/skills/yad-docs/templates/app/src/components/DocSections/ApiReferenceSection.tsx +108 -0
  51. package/skills/yad-docs/templates/app/src/components/DocSections/CancelabilitySection.tsx +73 -0
  52. package/skills/yad-docs/templates/app/src/components/DocSections/CriticalRunbookSection.tsx +177 -0
  53. package/skills/yad-docs/templates/app/src/components/DocSections/DataMigrationSection.tsx +102 -0
  54. package/skills/yad-docs/templates/app/src/components/DocSections/DbSchemaSection.tsx +98 -0
  55. package/skills/yad-docs/templates/app/src/components/DocSections/DeploymentGuideSection.tsx +104 -0
  56. package/skills/yad-docs/templates/app/src/components/DocSections/DriverIntegrationSection.tsx +127 -0
  57. package/skills/yad-docs/templates/app/src/components/DocSections/ExecutiveSummarySection.tsx +69 -0
  58. package/skills/yad-docs/templates/app/src/components/DocSections/FlowOverviewSection.tsx +73 -0
  59. package/skills/yad-docs/templates/app/src/components/DocSections/FlowPathsChecklistSection.tsx +96 -0
  60. package/skills/yad-docs/templates/app/src/components/DocSections/MiddlewareChainSection.tsx +107 -0
  61. package/skills/yad-docs/templates/app/src/components/DocSections/MonitoringAlertingSection.tsx +106 -0
  62. package/skills/yad-docs/templates/app/src/components/DocSections/NotificationLocalizationSection.tsx +102 -0
  63. package/skills/yad-docs/templates/app/src/components/DocSections/PMRoadmapSection.tsx +133 -0
  64. package/skills/yad-docs/templates/app/src/components/DocSections/PerformanceTestingSection.tsx +91 -0
  65. package/skills/yad-docs/templates/app/src/components/DocSections/RiderIntegrationSection.tsx +99 -0
  66. package/skills/yad-docs/templates/app/src/components/DocSections/SecuritySection.tsx +74 -0
  67. package/skills/yad-docs/templates/app/src/components/DocSections/StatusMachineSection.tsx +90 -0
  68. package/skills/yad-docs/templates/app/src/components/DocSections/TestPlanSection.tsx +163 -0
  69. package/skills/yad-docs/templates/app/src/components/Logs/SystemLogsTerminal.tsx +126 -0
  70. package/skills/yad-docs/templates/app/src/components/Navigation/TopNavBar.tsx +90 -0
  71. package/skills/yad-docs/templates/app/src/components/Reference/BullMQJobsList.tsx +60 -0
  72. package/skills/yad-docs/templates/app/src/components/Reference/DecisionTreeView.tsx +49 -0
  73. package/skills/yad-docs/templates/app/src/components/Reference/DeeplinkActionsChips.tsx +69 -0
  74. package/skills/yad-docs/templates/app/src/components/Reference/DriverUIStatesTable.tsx +61 -0
  75. package/skills/yad-docs/templates/app/src/components/Reference/FeatureFlagMatrix.tsx +73 -0
  76. package/skills/yad-docs/templates/app/src/components/Reference/RiderUIStatesTable.tsx +61 -0
  77. package/skills/yad-docs/templates/app/src/components/Reference/RulesLegendPanel.tsx +217 -0
  78. package/skills/yad-docs/templates/app/src/components/Reference/StakeholderToggle.tsx +41 -0
  79. package/skills/yad-docs/templates/app/src/components/Reference/TroubleshootingSection.tsx +93 -0
  80. package/skills/yad-docs/templates/app/src/components/Sidebar/PathSelector.tsx +148 -0
  81. package/skills/yad-docs/templates/app/src/components/Sidebar/SidebarFooter.tsx +40 -0
  82. package/skills/yad-docs/templates/app/src/components/Sidebar/StepList.tsx +234 -0
  83. package/skills/yad-docs/templates/app/src/components/shared/Badge.tsx +28 -0
  84. package/skills/yad-docs/templates/app/src/components/shared/CommandPalette.tsx +213 -0
  85. package/skills/yad-docs/templates/app/src/components/shared/Icon.tsx +21 -0
  86. package/skills/yad-docs/templates/app/src/components/shared/Tooltip.tsx +42 -0
  87. package/skills/yad-docs/templates/app/src/data/components.ts +74 -0
  88. package/skills/yad-docs/templates/app/src/data/docSections.ts +231 -0
  89. package/skills/yad-docs/templates/app/src/data/paths.ts +2319 -0
  90. package/skills/yad-docs/templates/app/src/data/referenceData.ts +392 -0
  91. package/skills/yad-docs/templates/app/src/data/roles.ts +145 -0
  92. package/skills/yad-docs/templates/app/src/data/types.ts +79 -0
  93. package/skills/yad-docs/templates/app/src/hooks/useAnimationQueue.ts +41 -0
  94. package/skills/yad-docs/templates/app/src/hooks/usePlayback.ts +100 -0
  95. package/skills/yad-docs/templates/app/src/hooks/useStakeholderFilter.ts +10 -0
  96. package/skills/yad-docs/templates/app/src/index.css +121 -0
  97. package/skills/yad-docs/templates/app/src/main.tsx +13 -0
  98. package/skills/yad-docs/templates/app/src/pages/RoleSelectPage.tsx +34 -0
  99. package/skills/yad-docs/templates/app/src/pages/StakeholderDocPage.tsx +98 -0
  100. package/skills/yad-docs/templates/app/src/pages/SubPathDetailPage.tsx +282 -0
  101. package/skills/yad-docs/templates/app/src/store/useAuthStore.ts +42 -0
  102. package/skills/yad-docs/templates/app/src/store/useFlowStore.ts +197 -0
  103. package/skills/yad-docs/templates/app/src/utils/iconMap.ts +46 -0
  104. package/skills/yad-docs/templates/app/tsconfig.app.json +28 -0
  105. package/skills/yad-docs/templates/app/tsconfig.json +7 -0
  106. package/skills/yad-docs/templates/app/tsconfig.node.json +26 -0
  107. package/skills/yad-docs/templates/app/vite.config.ts +10 -0
  108. package/skills/yad-docs-overview/SKILL.md +129 -0
  109. package/skills/yad-docs-overview/references/pipeline-model.md +102 -0
  110. package/skills/yad-docs-sync/SKILL.md +99 -0
  111. package/skills/yad-docs-sync/references/staleness.md +81 -0
  112. package/skills/yad-engineer-review/SKILL.md +86 -0
  113. package/skills/{yad-ship → yad-engineer-review}/references/ship-and-record.md +2 -2
  114. package/skills/{yad-ship → yad-engineer-review}/templates/.coderabbit.yaml +1 -1
  115. package/skills/yad-epic/references/state-schema.md +1 -1
  116. package/skills/yad-implement/SKILL.md +1 -1
  117. package/skills/yad-implement/references/implement-conventions.md +1 -1
  118. package/skills/yad-open-pr/SKILL.md +72 -0
  119. package/skills/yad-pr-template/templates/checks/pr-template.sh +62 -0
  120. package/skills/yad-pr-template/templates/checks/pr-title.sh +51 -0
  121. package/skills/yad-run/SKILL.md +2 -2
  122. package/skills/yad-run/references/run-loop.md +4 -4
  123. package/skills/yad-ship/SKILL.md +44 -66
  124. package/skills/yad-spec/SKILL.md +1 -1
@@ -32,6 +32,33 @@ jobs:
32
32
  with: { node-version: "20" }
33
33
  - run: bash checks/build-test-lint.sh
34
34
 
35
+ # Pattern gates: commit subject + PR title + PR body all follow the convention (profile: code).
36
+ commit-message:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ with: { fetch-depth: 0 }
41
+ - run: bash checks/commit-message.sh --profile code "origin/${{ github.base_ref }}"
42
+
43
+ # Pass the title via env (never interpolate untrusted ${{ }} into a run line — injection-safe).
44
+ pr-title:
45
+ runs-on: ubuntu-latest
46
+ env:
47
+ PR_TITLE: ${{ github.event.pull_request.title }}
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+ - run: bash checks/pr-title.sh --profile code "$PR_TITLE"
51
+
52
+ pr-template:
53
+ runs-on: ubuntu-latest
54
+ env:
55
+ PR_BODY: ${{ github.event.pull_request.body }}
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+ - run: |
59
+ body="$(mktemp)"; printf '%s' "$PR_BODY" > "$body"
60
+ bash checks/pr-template.sh --profile code "$body"
61
+
35
62
  # No unverified commits from unverified users: platform-Verified signature + allowlisted author.
36
63
  verified-commits:
37
64
  runs-on: ubuntu-latest
@@ -0,0 +1,36 @@
1
+ # yad-managed: yad-checks
2
+ # Pattern gates for the PRODUCT HUB: every PR (including the front-half review/EP-* PRs) must follow
3
+ # the hub conventions — Conventional-Commits commit subjects, a `review: <artifact> (EP-<slug>)` PR
4
+ # title, and a PR body that uses the hub artifact-review template. They run with `--profile hub`.
5
+ # Standalone workflow so it never collides with the code-repo yad-checks workflow.
6
+ name: yad-hub-checks
7
+ on:
8
+ pull_request:
9
+ branches: ["**"]
10
+
11
+ jobs:
12
+ commit-message:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with: { fetch-depth: 0 }
17
+ - run: bash checks/commit-message.sh --profile hub "origin/${{ github.base_ref }}"
18
+
19
+ # Pass the title via env (never interpolate untrusted ${{ }} into a run line — injection-safe).
20
+ pr-title:
21
+ runs-on: ubuntu-latest
22
+ env:
23
+ PR_TITLE: ${{ github.event.pull_request.title }}
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - run: bash checks/pr-title.sh --profile hub "$PR_TITLE"
27
+
28
+ pr-template:
29
+ runs-on: ubuntu-latest
30
+ env:
31
+ PR_BODY: ${{ github.event.pull_request.body }}
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - run: |
35
+ body="$(mktemp)"; printf '%s' "$PR_BODY" > "$body"
36
+ bash checks/pr-template.sh --profile hub "$body"
@@ -45,6 +45,26 @@ yad-build-test-lint:
45
45
  script:
46
46
  - bash checks/build-test-lint.sh
47
47
 
48
+ # Pattern gates: commit subject + MR title + MR body all follow the convention (profile: code).
49
+ yad-commit-message:
50
+ extends: .sdlc_mr_only
51
+ needs: []
52
+ script:
53
+ - bash checks/commit-message.sh --profile code "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
54
+
55
+ yad-pr-title:
56
+ extends: .sdlc_mr_only
57
+ needs: []
58
+ script:
59
+ - bash checks/pr-title.sh --profile code "$CI_MERGE_REQUEST_TITLE"
60
+
61
+ yad-pr-template:
62
+ extends: .sdlc_mr_only
63
+ needs: []
64
+ script:
65
+ - body="$(mktemp)"; printf '%s' "$CI_MERGE_REQUEST_DESCRIPTION" > "$body"
66
+ - bash checks/pr-template.sh --profile code "$body"
67
+
48
68
  # No unverified commits from unverified users: platform-Verified signature + allowlisted author.
49
69
  # Needs a CI/CD variable GITLAB_TOKEN (or SDLC_API_TOKEN) with read_api scope — CI_JOB_TOKEN cannot
50
70
  # read the commit-signature API. Without it the job FAILS closed with guidance.
@@ -0,0 +1,39 @@
1
+ # yad-managed-include: yad-checks
2
+ # Pattern gates for the PRODUCT HUB, as an INCLUDABLE fragment. Pulled into the hub's root
3
+ # .gitlab-ci.yml via:
4
+ # include:
5
+ # - local: '.gitlab/ci/yad-hub-checks.yml'
6
+ # Every MR (including the front-half review/EP-* MRs) must follow the hub conventions — a
7
+ # Conventional-Commits commit subject, a `review: <artifact> (EP-<slug>)` MR title, and an MR body
8
+ # that uses the hub artifact-review template. They run with `--profile hub`.
9
+ # Job names are yad-hub-prefixed so they coexist with any code-repo fragment in one pipeline; jobs use
10
+ # `needs: []` and no `stage:` so a foreign `stages:` list can neither break nor reorder them.
11
+ default:
12
+ image: node:20
13
+ tags: [$YAD_RUNNER_TAGS]
14
+
15
+ .yad_hub_mr_only:
16
+ rules:
17
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
18
+
19
+ variables:
20
+ GIT_DEPTH: "0" # full history so the commit gate can diff against the target branch
21
+
22
+ yad-hub-commit-message:
23
+ extends: .yad_hub_mr_only
24
+ needs: []
25
+ script:
26
+ - bash checks/commit-message.sh --profile hub "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
27
+
28
+ yad-hub-pr-title:
29
+ extends: .yad_hub_mr_only
30
+ needs: []
31
+ script:
32
+ - bash checks/pr-title.sh --profile hub "$CI_MERGE_REQUEST_TITLE"
33
+
34
+ yad-hub-pr-template:
35
+ extends: .yad_hub_mr_only
36
+ needs: []
37
+ script:
38
+ - body="$(mktemp)"; printf '%s' "$CI_MERGE_REQUEST_DESCRIPTION" > "$body"
39
+ - bash checks/pr-template.sh --profile hub "$body"
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: yad-commit
3
+ description: 'Build-half helper of the gated SDLC. Commit ONE staged atomic change by the conventions — a Conventional-Commits subject, the fixed trailer block (Task → Contract-Change → Co-Authored-By), and an atomic-file guard (≤3 files). The human git author OWNS the commit; an assisting AI is recorded only as a Co-Authored-By footer, chosen per-commit with --ai (claude|copilot|cursor|coderabbit|none — default none, human-only). Drives the zero-dependency `yad commit` CLI; never auto-advances. Use when the user says "commit this", "commit by convention", or "make an atomic commit".'
4
+ ---
5
+
6
+ # SDLC — Commit by Convention (build-half helper)
7
+
8
+ **Goal:** Turn ONE staged atomic change into a single commit that satisfies the project conventions
9
+ (`CONTRIBUTING.md` / `config.yaml` `build`): a Conventional-Commits subject, the fixed trailer order
10
+ `Task → Contract-Change → Co-Authored-By`, and the atomic-file guard. This is the standalone commit
11
+ step — the same engine `yad-implement` and `yad-ship` use. It **never auto-advances**; it just commits.
12
+
13
+ ## Conventions
14
+
15
+ - Run **inside the repo holding the staged change** — a code repo under
16
+ `{project-root}/demo-repos/<repo>/`, or the product hub itself. Use absolute paths.
17
+ - **Stage first.** Only the staged (`git add`) atomic change is committed. The guard refuses more than
18
+ `ATOMIC_FILE_LIMIT` (3) staged files unless `--force` — split the change instead.
19
+ - **Subject** — `<type>: <lowercase imperative description, no trailing period>`; types are
20
+ `feat|fix|docs|refactor|test|perf|build|ci|chore|revert`; proper nouns/acronyms keep their case.
21
+ - **Task trailer** — required on a code repo (anchors the `spec-link` + `commit-message` gates). Given
22
+ with `--task`, else derived from the branch (`feat/<story>-<task>-…`). Hub commits are not
23
+ task-scoped, so the trailer is optional there.
24
+ - **Contract-Change trailer** — `--contract-change` only when the diff touches the locked contract
25
+ surface; it routes the change back to the architecture gate.
26
+ - **AI co-author footer** — `--ai <id>` records the assisting tool as a `Co-Authored-By` trailer. The
27
+ human is always the author; `--ai none` (the default) is an explicit human-only commit.
28
+
29
+ ## Inputs
30
+
31
+ - `type` — Conventional-Commits type (required).
32
+ - `message` — the subject text (required), `-m "<subject>"`.
33
+ - `ai` — co-author footer: `claude|copilot|cursor|coderabbit|none` (default `none`).
34
+ - `task` — Task trailer (optional; derived from the branch when omitted).
35
+ - `contractChange` — flag; mark the contract surface touched.
36
+
37
+ ## On Activation
38
+
39
+ ### Step 1 — Confirm the atomic stage
40
+ Confirm the change is staged and stays within the file boundary (≤3 files where possible). If more is
41
+ staged, split it into separate commits rather than passing `--force`.
42
+
43
+ ### Step 2 — Commit by convention
44
+ Run the CLI from the repo root:
45
+ ```
46
+ yad commit --type <type> -m "<subject>" [--ai <id>] [--task <id>] [--contract-change] [--dry-run]
47
+ ```
48
+ Use `--dry-run` first to preview the exact message (subject + trailer block) without committing. The
49
+ CLI validates the type, rejects a trailing period, and emits the trailers in the fixed order.
50
+
51
+ ### Step 3 — Stop (no auto-advance)
52
+ Report what was committed (files + Task). If `--contract-change` was set, note that it routes back to
53
+ the architecture gate. To also open the PR/MR in the same step, use `yad-ship`.
54
+
55
+ ## Hard rules
56
+
57
+ - **One staged atomic change = one commit.** Never bundle; never exceed the file boundary silently.
58
+ - **The human author owns the commit.** The AI is only a `Co-Authored-By` footer, chosen per-commit.
59
+ - **Trailer order is fixed:** `Task → Contract-Change → Co-Authored-By`.
60
+ - **Never widen the contract here.** A contract touch is flagged (`--contract-change`), not hidden.
61
+
62
+ ## Reference
63
+ - Branch/commit conventions + the file-boundary rule: `../yad-implement/references/implement-conventions.md`.
64
+ - The full convention text: `CONTRIBUTING.md`; the config: `skills/sdlc/config.yaml` `build`.
65
+ - The gate that enforces the subject pattern: `../yad-checks/references/check-gates.md` (`commit-message`).
66
+ - Open the PR/MR after committing: `../yad-open-pr/SKILL.md`; both at once: `../yad-ship/SKILL.md`.
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: yad-connect-docs
3
+ description: 'Connects a docs/Pages publishing target to the product hub so the interactive-docs steps can build and deploy the generated SPA — not just commit its source. Registers the target into the project-wide .sdlc/docs.json (GitHub Pages / GitLab Pages / build-only), auto-detecting the platform from .sdlc/hub.json and resolving the Vite base path, with local-user auth and no stored tokens. Detects whether gh/glab is present and degrades to build-only when absent. Run at setup or any time the publish target changes. Reusable, idempotent, refreshable. Use when the user says "connect docs", "connect Pages", "refresh the docs connection", or "list the docs connection".'
4
+ ---
5
+
6
+ # SDLC — Connect a Docs/Pages Target (make the docs steps publishable)
7
+
8
+ **Goal:** Let the interactive-docs steps (`yad-docs` per epic, `yad-docs-overview` project-wide)
9
+ **build and deploy** the generated React/Vite SPA to a real URL — a GitHub Pages or GitLab Pages site —
10
+ instead of only committing its source. This skill **connects** a publishing target to the product hub
11
+ and records *how* to reach it (the platform, the publish scope, the base path) — never a credential.
12
+
13
+ This is **setup/maintenance**, not a gated front state — it never touches `.sdlc/state.json` or any
14
+ epic's approvals. It only writes the project-wide docs registry. `yad-docs` / `yad-docs-overview`
15
+ consume it: when a target is connected, they theme + generate the site and drive `yad docs deploy`;
16
+ when nothing is connected (`target: "none"`), they still generate and **npm-build** the site but stop
17
+ at a local `dist/` — build-only, no publish, exactly as before.
18
+
19
+ ## Conventions
20
+
21
+ - `{project-root}` resolves from the project working directory (the **product hub**).
22
+ - The target is **GitHub-Pages-first but pluggable** — a *publish adapter*, mirroring the GitHub/GitLab
23
+ platform adapter the hub already uses. `github-pages` and `gitlab-pages` are the providers; `none` →
24
+ build-only (deliberate, no error).
25
+ - The platform CLI (`gh` / `glab`) is a **subprocess**, used read/deploy-only via the user's own auth —
26
+ never installed by this skill, never given a token. Absent ⇒ degrade to build-only (`source:
27
+ "unavailable"`).
28
+ - Registry: `{project-root}/.sdlc/docs.json` (project-wide, shared across all epics + the overview —
29
+ NOT per-epic), the sibling of `.sdlc/hub.json`, `.sdlc/repos.json`, and `.sdlc/design.json`.
30
+ - Per-epic / overview build manifests (`docs-build.json`) are written later by `yad-docs` /
31
+ `yad-docs-overview`, not here. This skill describes the *connection*; it does not build.
32
+ - Speak in the configured `communication_language`; write documents in `document_output_language`.
33
+
34
+ ## Inputs
35
+
36
+ - `action` — `connect` (default) | `refresh` | `list` | `disconnect`.
37
+ - `target` — `github-pages` | `gitlab-pages` | `none`. Default **auto-detected** from `.sdlc/hub.json`
38
+ `platform` (github → `github-pages`, gitlab → `gitlab-pages`, null/no hub → `none`).
39
+ - `scope` — `hub` (default) | `<repo-name>` | `dedicated`. Where the Pages site is published from (the
40
+ hub repo, one connected code repo, or a dedicated docs repo).
41
+ - `public` — `true` (default) | `false`. Whether the published site is public.
42
+ - `base_path` — optional explicit override of the Vite `base` (otherwise resolved, Step 2).
43
+
44
+ ## On Activation
45
+
46
+ ### Step 1 — Resolve the target + detect the platform (the publish adapter)
47
+ Determine the `target`. If not given, read `{project-root}/.sdlc/hub.json` `platform` and map it the same
48
+ way the hub bridge maps repos: `github` → `github-pages`, `gitlab` → `gitlab-pages`, `null`/no hub →
49
+ `none` (deliberate build-only). Reject a `target` value outside the three providers (fall back to the
50
+ detected default with a warning, the way `registerRepo` falls back on an unknown platform).
51
+
52
+ Then **probe the platform CLI** in the user's own session — `gh --version` / `gh auth status` for
53
+ GitHub, `glab --version` / `glab auth status` for GitLab. Record `source`:
54
+ - CLI present + authenticated → `source: "gh"` | `"glab"` (deploy can publish via the platform).
55
+ - CLI absent or unauthenticated → `source: "unavailable"` — record it and report that `yad-docs` will
56
+ **build-only** (npm build to a local `dist/`, no publish) until the CLI is available. No error — the
57
+ publish is purely additive, exactly like the `gh`/`glab` review bridge degrading.
58
+
59
+ **Auth is the local user's own** (`gh`/`glab`/git already on this device). The skill **stores no
60
+ tokens**; everything in the registry is a plain reference. Do **not** install a CLI as part of this step.
61
+
62
+ ### Step 2 — Decide the publish scope + resolve the base path
63
+ Resolve `scope` → `publishRepo`:
64
+ - `hub` (default) → publish from the hub repo (read its name from `hub.json` `git_url`).
65
+ - `<repo-name>` → publish from that connected code repo (must exist in `.sdlc/repos.json`).
66
+ - `dedicated` → a dedicated docs repo the user names (recorded as `publishRepo`).
67
+
68
+ Resolve `basePath` (the Vite `base`) per the table in `references/docs-registry.md`:
69
+ - **GitHub *project* Pages** (a repo that is not `<user>.github.io`) serve under `/<repo>/` → `basePath =
70
+ "/<repo>/"`. Per-epic sites nest under `/<repo>/epics/EP-<slug>/`; the overview under `/<repo>/`.
71
+ - **GitHub user/org Pages** (`<user>.github.io`) and **GitLab Pages** serve at the domain root → `basePath
72
+ = "/"`.
73
+ - An explicit `base_path` input always wins (recorded verbatim, normalized to a leading + trailing `/`).
74
+
75
+ ### Step 3 — Record the connection in the registry (idempotent)
76
+ Upsert into `{project-root}/.sdlc/docs.json` (create the file + parent `.sdlc/` if absent):
77
+
78
+ ```json
79
+ {
80
+ "target": "github-pages",
81
+ "scope": "hub",
82
+ "publishRepo": "<repo or hub name>",
83
+ "basePath": "/<repo>/",
84
+ "public": true,
85
+ "auth": "user",
86
+ "connectedAt": "<YYYY-MM-DD>",
87
+ "lastSyncedAt": "<YYYY-MM-DD>",
88
+ "source": "gh"
89
+ }
90
+ ```
91
+
92
+ - `target: "none"` records a deliberate build-only project: `{ "target": "none", "scope": "hub",
93
+ "publishRepo": null, "basePath": "/", "source": "unavailable", ... }`.
94
+ - `connect` is **idempotent** — re-running it overwrites the single connection in place (a project has
95
+ one docs target at a time; switching targets is just another `connect`).
96
+
97
+ ### Step 4 — Report (never auto-advance)
98
+ Report the connected `target`, its `scope`/`publishRepo`, the resolved `basePath`, whether the platform
99
+ CLI is available (or that the docs steps will degrade to **build-only**), and that **`yad-docs` /
100
+ `yad-docs-overview` will now build + deploy here**. Nothing auto-advances; this is setup. **Do not build
101
+ the site here — `yad-docs` builds.**
102
+
103
+ ## Other actions
104
+
105
+ - **`refresh`** — re-detect the platform CLI and re-resolve the base path (after the user authenticates a
106
+ session, renames the publish repo, or switches `scope`), updating `lastSyncedAt`. Same machinery as
107
+ `connect`. Re-detection may flip `source` between `gh`/`glab` and `unavailable` — report the change.
108
+ - **`list`** — print the current connection: `target`, `scope`/`publishRepo`, `basePath`, `public`, and a
109
+ **available/unavailable** flag for the platform CLI (best-effort, the user's own session). No target
110
+ connected ⇒ "build-only".
111
+ - **`disconnect`** — remove the registry file (or set `target: "none"`). The platform's own Pages site is
112
+ **never touched** — only the hub's record of it.
113
+
114
+ ## Hard rules
115
+
116
+ - **Local-user auth only; store no tokens.** Connect through the user's own `gh`/`glab`/git; never embed a
117
+ PAT or any credential in the registry. Everything recorded is a plain reference.
118
+ - **Degrade gracefully.** No target / no platform CLI → the docs steps **build-only** (local `dist/`) with
119
+ no error. Publishing is additive, never a blocker — the same discipline as the `gh`/`glab` review bridge.
120
+ - **Setup, not a gate.** Never touch `.sdlc/state.json`, approvals, or the contract lock from here.
121
+ - **Idempotent + refreshable.** `connect`/`refresh` are safe to re-run; a project carries one docs
122
+ connection at a time.
123
+ - **Describe the connection; do not build here.** This skill records *how to reach* the target.
124
+ `yad-docs` / `yad-docs-overview` generate, build, and deploy the site.
125
+
126
+ ## Reference
127
+ - Registry schema, the base-path resolution table, and the freshness/degrade rules:
128
+ `references/docs-registry.md`.
129
+ - The connect pattern this mirrors (design tool): `../yad-connect-design/SKILL.md`.
130
+ - The connect pattern this mirrors (code repos + hub detection): `../yad-connect-repos/SKILL.md`.
131
+ - The consumers — how `yad-docs` / `yad-docs-overview` build + deploy: `../yad-docs/SKILL.md`,
132
+ `../yad-docs-overview/SKILL.md`.
@@ -0,0 +1,74 @@
1
+ # `.sdlc/docs.json` — the docs/Pages registry
2
+
3
+ Project-wide, shared across every epic's docs site **and** the project overview site (NOT per-epic).
4
+ The sibling of `.sdlc/hub.json`, `.sdlc/repos.json`, and `.sdlc/design.json`. Written by
5
+ `yad-connect-docs`; read by `yad-docs`, `yad-docs-overview`, `yad-docs-sync`, and the `yad docs` CLI.
6
+ Holds **no credentials** — every field is a plain reference. Auth is always the local user's own
7
+ `gh`/`glab`/git session.
8
+
9
+ ## Schema
10
+
11
+ ```json
12
+ {
13
+ "target": "github-pages | gitlab-pages | none",
14
+ "scope": "hub | <repo-name> | dedicated",
15
+ "publishRepo": "<repo or hub name>",
16
+ "basePath": "/<repo>/",
17
+ "public": true,
18
+ "auth": "user",
19
+ "connectedAt": "<YYYY-MM-DD>",
20
+ "lastSyncedAt": "<YYYY-MM-DD>",
21
+ "source": "gh | glab | unavailable"
22
+ }
23
+ ```
24
+
25
+ | Field | Meaning |
26
+ |-------|---------|
27
+ | `target` | The publish adapter. `none` = deliberate build-only (no publish, no error). |
28
+ | `scope` | Where the Pages site publishes from: the `hub` repo, one connected `<repo-name>`, or a `dedicated` docs repo. |
29
+ | `publishRepo` | The concrete repo name resolved from `scope`. `null` when `target: "none"`. |
30
+ | `basePath` | The Vite `base` substituted into each generated site (resolution table below). Normalized to a leading + trailing `/`. |
31
+ | `public` | Whether the published site is public. |
32
+ | `auth` | Always `"user"` — local-user / platform-CLI session. No token is ever stored. |
33
+ | `connectedAt` / `lastSyncedAt` | ISO dates the connection was first written / last re-detected. |
34
+ | `source` | `gh`/`glab` when the platform CLI is present + authenticated (publish works); `unavailable` when absent (build-only). |
35
+
36
+ `target: "none"` records `{ "target": "none", "publishRepo": null, "basePath": "/", "source":
37
+ "unavailable", ... }`.
38
+
39
+ ## Platform auto-detection (from `.sdlc/hub.json`)
40
+
41
+ When `target` is not given, map the hub's `platform` the same way `yad-connect-repos` maps a repo host:
42
+
43
+ | `hub.json` `platform` | default `target` |
44
+ |-----------------------|------------------|
45
+ | `github` | `github-pages` |
46
+ | `gitlab` | `gitlab-pages` |
47
+ | `null` / no hub.json | `none` (build-only) |
48
+
49
+ ## Base-path resolution table
50
+
51
+ GitHub serves *project* Pages under a `/<repo>/` prefix, so Vite's `base` must match or every asset 404s.
52
+ User/org Pages and GitLab Pages serve at the domain root.
53
+
54
+ | Target + repo kind | `basePath` | Per-epic site URL | Overview site URL |
55
+ |--------------------|------------|-------------------|-------------------|
56
+ | GitHub **project** Pages (repo ≠ `<user>.github.io`) | `/<repo>/` | `/<repo>/epics/EP-<slug>/` | `/<repo>/` |
57
+ | GitHub **user/org** Pages (`<user>.github.io`) | `/` | `/epics/EP-<slug>/` | `/` |
58
+ | GitLab Pages | `/` | `/epics/EP-<slug>/` | `/` |
59
+ | explicit `base_path` input | as given (normalized) | nests `epics/EP-<slug>/` under it | the given base |
60
+
61
+ An explicit `base_path` input always wins. `yad-docs` substitutes `basePath` into the shell's Vite
62
+ config; per-epic sites append `epics/EP-<slug>/` so they nest under the overview without colliding.
63
+
64
+ ## Freshness + degrade rules
65
+
66
+ - **Freshness** here is connection-level, not content-level: `lastSyncedAt` reflects the last `refresh`.
67
+ *Site* staleness (artifacts/repos moved, shell upgraded) is tracked separately in each site's
68
+ `docs-build.json` and reconciled by `yad-docs-sync` — not here.
69
+ - **`list`** flags the platform CLI **available/unavailable** by probing `gh auth status` / `glab auth
70
+ status` in the user's own session (best-effort). A flip to `unavailable` means the docs steps
71
+ degrade to build-only until the CLI is back.
72
+ - **Degrade is silent + non-blocking.** No target / no CLI ⇒ `yad-docs` still generates + npm-builds the
73
+ site to a local `dist/`; only the publish step is skipped. The same discipline as the design-tool MCP
74
+ and the `gh`/`glab` review bridge being absent.
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: yad-docs
3
+ description: 'Generates the per-epic interactive documentation site — a vendored React/Vite/Tailwind SPA with an animated flow canvas and role-based stakeholder doc pages — from the epic''s approved artifacts (epic, architecture, the locked contract, UI design, stories, code-context, test cases). Themes it from the design tokens, wires the docs.json base path, and drives `yad docs build/deploy` to publish to Pages (or build-only when no target). This is an OUTPUT ENRICHMENT, never a gated front state: it never mutates state.json steps, approvals, or the contract lock. Use when the user says "generate the docs site", "build the interactive docs", or "deploy the epic docs".'
4
+ ---
5
+
6
+ # SDLC — Author the Interactive Docs Site (per-epic, output enrichment)
7
+
8
+ **Goal:** Turn an epic's approved artifacts into a **living, interactive documentation site** — a
9
+ vendored React 19 + Vite 7 + Tailwind v4 SPA with an animated **flow canvas** (system components on a
10
+ canvas, animated messages, playback, a system-logs terminal, a right detail panel) and **role-based
11
+ stakeholder doc pages** (each lens → a set of doc sections). The shell is generic; the **content** is
12
+ generated entirely into `src/data/*.ts` and the theme into `src/index.css`.
13
+
14
+ This is an **output enrichment**, exactly like `design-links.json` / `test-links.json` — **NOT a gated
15
+ front state.** It **never** mutates `.sdlc/state.json` `steps[]`, `approvals.json`, or
16
+ `contract-lock.json`, and it never adds a `state.json` step. It reads the *approved* shape and renders
17
+ it; it never decides approval. When a docs target is connected (`yad-connect-docs` → `.sdlc/docs.json`)
18
+ the site is built + deployed; when none is, it is npm-built to a local `dist/` (build-only).
19
+
20
+ ## Conventions
21
+
22
+ - `{project-root}` resolves from the project working directory (the **product hub**).
23
+ - Artifacts live under `{project-root}/epics/EP-<slug>/`. The generated site lives at
24
+ `epics/EP-<slug>/docs-site/`; its `dist/` and `node_modules/` are gitignored, the generated **source
25
+ is committed**.
26
+ - The shell template is `skills/yad-docs/templates/app/` — copied **verbatim**, never modified in place.
27
+ Generated data must satisfy the types in `src/data/types.ts`.
28
+ - The docs target is recorded in `{project-root}/.sdlc/docs.json` (`yad-connect-docs`). The per-epic
29
+ build manifest (the staleness baseline) is `epics/EP-<slug>/.sdlc/docs-build.json`.
30
+ - The actual data-file **generation** (reading artifacts → writing `src/data/*.ts`, theming
31
+ `index.css`) is the **AI step** inside this skill; the `yad docs` CLI only does the npm build +
32
+ platform deploy + staleness hashing.
33
+ - Speak in the configured `communication_language`; write documents in `document_output_language`.
34
+
35
+ ## Inputs
36
+
37
+ - `epic` — `EP-<slug>` (ask if not provided).
38
+ - `action` — `generate` (default) | `refresh` | `deploy`.
39
+ - `login_gate` — `true` | `false` (default `false`). When on, the generated site gates behind a local
40
+ login screen (`useAuthStore`); default off (public docs).
41
+
42
+ ## On Activation
43
+
44
+ ### Step 1 — Resolve the epic + check the *shape* is approved (NOT the gate)
45
+ Resolve `EP-<slug>`. Read `.sdlc/state.json`. Require **at least** that the epic exists and its
46
+ `epic-review` step has `status == "done"` (so the docs never describe an *unapproved* shape) — but do
47
+ **NOT** require any specific `currentStep`. Docs are an enrichment that runs over whatever is approved
48
+ so far. **Never touch `approvals.json` or `contract-lock.json`.** If `epic-review` has not passed, stop
49
+ and point the user at the gate (`yad-review-gate`); do not render an unapproved epic.
50
+
51
+ ### Step 1b — Open the authoring branch
52
+ Open the `docs/EP-<slug>` authoring branch per the shared procedure
53
+ (`../yad-epic/references/state-schema.md` → "Authoring branches"): git-safe (skip with a note if
54
+ `{project-root}` is not a git work tree), check out the branch if it exists, else create it from the
55
+ hub's default branch. Generate and commit the site source on it.
56
+
57
+ ### Step 2 — Read the inputs (the data sources)
58
+ Load each artifact and note what it feeds (full table in `references/data-mapping.md`):
59
+
60
+ - `epic.md` → **ExecutiveSummary** + **PMRoadmap** sections.
61
+ - `architecture.md` → **system components** (`components.ts`) + **flow paths** + the **Deployment** and
62
+ **Security** doc sections.
63
+ - `contract.md` `CONTRACT-SURFACE` → **ApiReference** / **StatusMachine** / **DbSchema** — the
64
+ **authoritative** API source. The docs **cannot drift** from the locked contract; render the surface
65
+ exactly as locked (cross-check `contract-lock.json`'s hash matches, but never modify it).
66
+ - `ui-design.md` + `DESIGN.md` + `.sdlc/design-links.json` → flow-path **UI states**, the `index.css`
67
+ **theme**, and a **Screens** section (linking the design-tool frames when present).
68
+ - `stories/*.md` → **one FlowPath each** (acceptance criteria → animated `FlowStep` messages +
69
+ `sideEffects`).
70
+ - `.sdlc/repos.json` + `.sdlc/code-context/<repo>/code-map.md` (for each repo in `epic.repos`) → real
71
+ module/endpoint names that **enrich** the components. **Staleness:** if a repo's current HEAD ≠ its
72
+ registry `syncedHead`, **warn** and stamp `code-context: stale` in the manifest — suggest `yad repo
73
+ refresh <repo>` (a human decision); **never auto-refresh**.
74
+ - `test-cases.md` + `.sdlc/test-links.json` → the **TestPlan** section.
75
+
76
+ Greenfield-safe: any absent input (no design tool, no test cases, no repos) degrades that section to
77
+ empty/omitted with a note — never invent content.
78
+
79
+ ### Step 3 — Generate the site into `epics/EP-<slug>/docs-site/`
80
+ Copy the shell from `templates/app/` **verbatim**, then:
81
+
82
+ 1. **Generate `src/data/*.ts` deterministically** — `paths.ts`, `components.ts`, `roles.ts`,
83
+ `docSections.ts`, `referenceData.ts` (mapping in `references/data-mapping.md`). Sort by **stable
84
+ IDs** (story `S0N`, repo name, endpoint `method+path`), use a **fixed key order**, and write **NO
85
+ timestamps inside the data files** — so regenerating an unchanged input yields a byte-identical file
86
+ (the staleness hash depends on it). Data must satisfy `src/data/types.ts`
87
+ (`FlowPath`/`FlowStep`/`AnimatedMessage`/`SystemComponent`/`StakeholderView`, etc.).
88
+ 2. **Derive stakeholder roles** (`roles.ts`) from the hub roster roles (`.sdlc/hub.json`) ∩ the yadflow
89
+ lens set (analyst / pm / architect / ux / dev / tester / reviewer / engineer) ∩ the stories' `repos:`
90
+ tags — each role → its relevant doc `sectionIds` + `relevantPathIds` (`references/data-mapping.md`).
91
+ 3. **Theme the `:root` block of `src/index.css`** from the design tokens, by the 4-tier priority in
92
+ `references/theme-map.md`: **DESIGN.md → design.json/design-links.json palette → code-map tokens →
93
+ default theme** (stamp `theme: default` in the manifest when it falls through to the shell default).
94
+ Keep fonts Space Grotesk + Noto Sans and the `.glass-panel`/`.flow-grid`/`.code-block` utilities.
95
+ 4. **Substitute the Vite base** from `.sdlc/docs.json` `basePath` (per-epic sites nest under
96
+ `/<repo>/epics/EP-<slug>/`). Read `docs.json` for the base path + target; if absent, default base
97
+ `/` and treat as build-only.
98
+ 5. **Set the login-gate flag** (`login_gate`, default off).
99
+
100
+ ### Step 4 — Write the build manifest (the staleness baseline)
101
+ Write `epics/EP-<slug>/.sdlc/docs-build.json` — the baseline `yad-docs-sync` compares against:
102
+
103
+ ```json
104
+ {
105
+ "builtAt": "<YYYY-MM-DD>",
106
+ "theme": "design.json | DESIGN.md | default",
107
+ "artifactHash": "<sha256 of epic.md + architecture.md + contract.md CONTRACT-SURFACE + ui-design.md + each story>",
108
+ "repoHeads": { "<repo>": "<HEAD sha>" },
109
+ "deployUrl": "<url or null>",
110
+ "templateVersion": "<shell template version>"
111
+ }
112
+ ```
113
+
114
+ Do **NOT** add a `state.json` step — docs are an enrichment, exactly like `design-links.json`.
115
+ Optionally record a `docs:` line in a `DOCS.md` index under the epic.
116
+
117
+ ### Step 5 — Build / deploy (`action`)
118
+ - `action: generate` (default) — generate the source + manifest; stop. The CLI may npm-build to verify,
119
+ but no publish.
120
+ - `action: deploy` — drive **`yad docs deploy --epic <id>`**: it npm-builds the site (`npm ci && npm run
121
+ build` as a subprocess, like `yad-spec` shelling `npx repomix`), ensures the Pages CI workflow is
122
+ present, and reports the deploy URL (publish happens via CI). **Degrades** to the local `dist/` path
123
+ when no platform CLI / `target: "none"` (build-only).
124
+
125
+ ### Step 6 — Stop. Report (NEVER auto-advance)
126
+ Report: the site path (`epics/EP-<slug>/docs-site/`), the data files produced, the **theme source** (or
127
+ the default-theme degrade), the **deploy URL** or "build-only", and the **staleness baseline**
128
+ (`docs-build.json`). **NEVER auto-advance, NEVER record approval — this is not a gate.** Note any
129
+ `code-context: stale` warning so the human can refresh the repo cache.
130
+
131
+ ## Hard rules
132
+
133
+ - **Output enrichment, never a gate.** This skill **MUST NEVER** mutate `.sdlc/state.json` `steps[]`,
134
+ `approvals.json`, or `contract-lock.json`, and never adds a state step — exactly how `yad-ui` writes
135
+ `design-links.json` without changing the locked step shape.
136
+ - **Docs cannot drift from the locked contract.** The contract surface is the authoritative API source;
137
+ render it as locked. Never edit `contract-lock.json` or the contract here.
138
+ - **Deterministic generation.** Stable-ID sort, fixed key order, no timestamps inside `src/data/*.ts` —
139
+ so an unchanged input regenerates byte-identically and the staleness hash is meaningful.
140
+ - **Never auto-refresh a stale repo.** HEAD ≠ `syncedHead` ⇒ warn + stamp `code-context: stale`; the
141
+ refresh is a human decision (`yad repo refresh`).
142
+ - **Degrade gracefully.** No docs target → build-only (local `dist/`). No design tokens → default theme.
143
+ Absent inputs → omitted sections. No error — the site is additive.
144
+ - **Copy the shell verbatim.** Generate only `src/data/*.ts`, the `:root` of `index.css`, and the Vite
145
+ base. Never hand-edit `templates/app/`.
146
+
147
+ ## Reference
148
+ - The deterministic DESIGN-token → CSS-custom-property mapping + 4-tier priority + default fallback:
149
+ `references/theme-map.md`.
150
+ - The full artifact → data-structure table, determinism rules, and role derivation:
151
+ `references/data-mapping.md`.
152
+ - The connected docs target + base-path resolution: `../yad-connect-docs/SKILL.md`.
153
+ - The design tokens this themes from: `../yad-connect-design/SKILL.md`.
154
+ - The code-context the data enriches: `../yad-connect-repos/SKILL.md`.
155
+ - The authoring pattern (front-state author that writes link artifacts without gating):
156
+ `../yad-ui/SKILL.md`.
157
+ - State schema + the "Authoring branches" procedure: `../yad-epic/references/state-schema.md`.
158
+ - The project overview site + the staleness/CI reconciler: `../yad-docs-overview/SKILL.md`,
159
+ `../yad-docs-sync/SKILL.md`.
@@ -0,0 +1,75 @@
1
+ # Data mapping — artifacts → `src/data/*.ts`
2
+
3
+ `yad-docs` copies the shell verbatim and **generates** the five data modules under `src/data/`. The
4
+ shell renders whatever these export, as long as it satisfies `src/data/types.ts`
5
+ (`FlowPath` / `FlowStep` / `AnimatedMessage` / `SystemComponent` / `StakeholderView` / `RoleConfig` /
6
+ `DocSectionConfig`). The generation is the AI step; it must be **deterministic** (rules at the bottom).
7
+
8
+ ## Artifact → data-structure table
9
+
10
+ | Generated file | Exports | Fed by (artifact) | What maps |
11
+ |----------------|---------|-------------------|-----------|
12
+ | `components.ts` | `COMPONENTS: SystemComponent[]` | `architecture.md` system components + `code-map.md` module/endpoint names | each durable component → `{ id, label, icon, color, position, description }`; canvas `position` laid out deterministically; real module names from the code-map enrich `label`/`description`. |
13
+ | `paths.ts` | `FLOW_PATHS: FlowPath[]` | `stories/*.md` (one FlowPath each) + `architecture.md` flows | each story → one `FlowPath` (`id`, `label`, `icon`, `color`, `category`, `steps[]`); each acceptance criterion → a `FlowStep` whose `messages: AnimatedMessage[]` animate the request/response/event/job and whose `sideEffects` record jobs/notifications/pubsub. UI states (from `ui-design.md`) annotate each step. |
14
+ | `roles.ts` | `ROLES: RoleConfig[]` | hub roster (`.sdlc/hub.json`) + the yadflow lens set + stories' `repos:` tags | each stakeholder lens → `{ slug, label, shortLabel, icon, color, description, sectionIds, relevantPathIds }` (role derivation below). |
15
+ | `docSections.ts` | `DOC_SECTIONS: DocSectionConfig[]` | `epic.md`, `architecture.md`, `contract.md`, `ui-design.md`, `test-cases.md` | the ordered doc-section registry (`{ id, title, icon, iconColor, component }`); each section id is referenced from `roles.ts`. |
16
+ | `referenceData.ts` | the reference tables/payloads the doc-section components render | `contract.md` CONTRACT-SURFACE (authoritative) + `architecture.md` + `test-cases.md` | API reference rows, the status machine, the DB schema, feature flags, error codes, the test plan — the structured data behind the doc sections. |
17
+
18
+ ## Section sources (the doc sections + their artifact)
19
+
20
+ | Doc section(s) | Artifact source |
21
+ |----------------|-----------------|
22
+ | ExecutiveSummary, PMRoadmap | `epic.md` |
23
+ | FlowOverview, system components, Deployment, Security | `architecture.md` |
24
+ | **ApiReference, StatusMachine, DbSchema** | `contract.md` **CONTRACT-SURFACE — authoritative, must not drift from `contract-lock.json`** |
25
+ | Rider/Driver/role UI states, Screens, the theme | `ui-design.md` + `DESIGN.md` + `design-links.json` |
26
+ | TestPlan, FlowPathsChecklist, ErrorCodes | `test-cases.md` + `test-links.json` |
27
+
28
+ Any absent input degrades its section to empty/omitted (greenfield-safe); never invent content. The
29
+ contract is rendered exactly as locked — the docs are a *view* of the locked surface, never a re-author.
30
+
31
+ ## Role derivation (`roles.ts`)
32
+
33
+ A stakeholder role is generated for each lens that is **both** present in the hub roster **and** relevant
34
+ to this epic:
35
+
36
+ 1. Start from the **yadflow lens set**: `analyst`, `pm`, `architect`, `ux`, `dev`, `tester`, `reviewer`,
37
+ `engineer`.
38
+ 2. Intersect with the **hub roster** roles (`.sdlc/hub.json` `roster[].roles`) — only emit lenses the
39
+ team actually has (an unmapped lens is dropped, never invented).
40
+ 3. For the `dev`/`engineer` lenses, **fan out per `repos:` tag** present across the epic's stories (e.g.
41
+ a `backend` dev role and a `mobile` dev role), so each repo audience gets its own integration view —
42
+ mirroring the reference site's per-app dev roles.
43
+ 4. Each role maps to its relevant `sectionIds` (which doc sections it should see) + `relevantPathIds`
44
+ (which FlowPaths/stories touch it). Keep these stable: derive `relevantPathIds` from the stories
45
+ tagged with that role's repo, sorted by story id.
46
+
47
+ ## Determinism rules (load-bearing — the data feeds `artifactHash`)
48
+
49
+ - **Sort by stable IDs:** stories by `S0N`, repos by name, endpoints by `method + path`, roles by lens
50
+ order above. Never sort by anything time- or order-of-discovery-dependent.
51
+ - **Fixed key order** in every emitted object (match the `types.ts` field order).
52
+ - **No timestamps inside `src/data/*.ts`.** Build/deploy times live only in `docs-build.json`.
53
+ - Colors/icons assigned to paths/components/roles come from the theme + a **fixed** lens→icon/color map
54
+ (Material Symbols names), not randomly — so regenerating an unchanged input yields a byte-identical
55
+ file, and the staleness hash only moves when an *artifact* actually moves.
56
+ - IDs are derived from the source IDs (story id → `FlowPath.id`, repo/module name → component `id`), never
57
+ freshly minted, so links stay stable across regenerations.
58
+
59
+ ## The DocSection components are NOT purely data-driven — regenerate their content too
60
+
61
+ The vendored shell ships the reference app's `src/components/DocSections/*.tsx` **with hardcoded
62
+ booking-domain content inline** (e.g. `ApiReferenceSection.tsx` declares a literal `ENDPOINTS`
63
+ array). They are NOT yet wired to read everything from `referenceData.ts`. So generation has two
64
+ parts, both the AI step:
65
+
66
+ 1. **Data files** — write `src/data/{paths,components,roles,docSections,referenceData}.ts` from the
67
+ artifacts (the table above).
68
+ 2. **Section content** — for every section a role references, replace the inline constants inside the
69
+ matching `DocSections/<Name>Section.tsx` with this epic's content (or refactor the section to read
70
+ its rows from `referenceData.ts`). A section left with the reference's booking content is a bug —
71
+ the docs would describe the wrong system. The contract surface is the authoritative source for the
72
+ API/StatusMachine/DbSchema sections.
73
+
74
+ Keep both deterministic (sorted, fixed key order, no timestamps) so the build manifest hash only moves
75
+ when an artifact actually moves.