@shanyucoder/flowgrid 0.1.11 → 0.1.13
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.
- package/adapters/shared/resolve-hub-id.mjs +5 -1
- package/dist/docs/mcp/tools.js +59 -6
- package/dist/docs/mcp/tools.js.map +1 -1
- package/dist/docs/scan/screen-to-flows.d.ts +3 -0
- package/dist/docs/scan/screen-to-flows.js +18 -0
- package/dist/docs/scan/screen-to-flows.js.map +1 -0
- package/engines/docs/lib/render-bundle-markdown.mjs +19 -0
- package/engines/docs/lib/render-design-markdown.mjs +56 -0
- package/engines/docs/lib/screen-to-flows-index.mjs +121 -0
- package/engines/docs/vitepress/surfaces-nav.mjs +7 -0
- package/engines/spec/lib/audit-bundle-gaps.mjs +15 -3
- package/engines/spec/lib/audit-interaction-cases.mjs +186 -0
- package/engines/spec/lib/bundle-ir.mjs +7 -0
- package/engines/spec/lib/bundle-schema.mjs +1 -0
- package/engines/spec/lib/interaction-cases.mjs +46 -0
- package/engines/spec/split-bundle.mjs +1 -1
- package/harness/be/adapters/dotnet-integration/skills/framework-rules-be/SKILL.md +2 -2
- package/harness/be/adapters/fastapi/skills/framework-rules-be/SKILL.md +3 -3
- package/harness/be/adapters/laravel/skills/framework-rules-be/SKILL.md +3 -3
- package/harness/be/skills/api/SKILL.md +4 -4
- package/harness/be/skills/api-unit/SKILL.md +4 -4
- package/harness/be/skills/audit-api/SKILL.md +3 -3
- package/harness/be/skills/grill-api-unit/SKILL.md +2 -2
- package/harness/common/rules/artifactgraph.mdc +2 -2
- package/harness/common/rules/cross-repo-index.mdc +2 -2
- package/harness/common/rules/platform-code-size.mdc +5 -5
- package/harness/common/rules/team-flow-harness-state.mdc +4 -4
- package/harness/common/skills/business-impact-review/SKILL.md +1 -1
- package/harness/common/skills/configure-repo-maps/SKILL.md +1 -1
- package/harness/common/skills/docs-mark/SKILL.md +4 -4
- package/harness/docs/extracts/agent-design-context.md +136 -0
- package/harness/docs/extracts/extract-registry.docs.json +9 -3
- package/harness/docs/extracts/ir-read-only.md +42 -0
- package/harness/docs/rules/agent-compliance.mdc +5 -1
- package/harness/docs/rules/docs-hub.mdc +6 -6
- package/harness/docs/rules/flowgrid-process.mdc +5 -5
- package/harness/docs/rules/team-flow-grill.mdc +1 -1
- package/harness/docs/rules/team-flow-spec.mdc +5 -5
- package/harness/docs/skills/adopt/SKILL.md +1 -1
- package/harness/docs/skills/api/SKILL.md +2 -2
- package/harness/docs/skills/api-spec/SKILL.md +4 -0
- package/harness/docs/skills/build-templates/SKILL.md +1 -1
- package/harness/docs/skills/call-external/SKILL.md +1 -1
- package/harness/docs/skills/cross-entity-service/SKILL.md +1 -1
- package/harness/docs/skills/db-erd/SKILL.md +2 -2
- package/harness/docs/skills/grill/SKILL.md +1 -1
- package/harness/docs/skills/grill-api-spec/SKILL.md +3 -3
- package/harness/docs/skills/grill-bqa/SKILL.md +2 -2
- package/harness/docs/skills/grill-dev/SKILL.md +31 -13
- package/harness/docs/skills/grill-docs/SKILL.md +2 -2
- package/harness/docs/skills/grill-hub-prd/SKILL.md +1 -1
- package/harness/docs/skills/openapi/SKILL.md +3 -3
- package/harness/docs/skills/risk-register/SKILL.md +8 -8
- package/harness/docs/skills/spec/SKILL.md +20 -12
- package/harness/docs/skills/update-spec/SKILL.md +17 -7
- package/harness/docs/skills/user-flow/SKILL.md +4 -2
- package/harness/fe/adapters/dotnet-line/skills/framework-rules/SKILL.md +2 -2
- package/harness/fe/adapters/nextjs/skills/framework-rules/SKILL.md +2 -2
- package/harness/fe/adapters/nuxt4/skills/framework-rules/SKILL.md +2 -2
- package/harness/fe/rules/cross-repo-index-routing.mdc +1 -1
- package/harness/fe/rules/flowgrid-test-optional-accelerators.mdc +3 -3
- package/harness/fe/rules/team-flow-prototype.mdc +13 -13
- package/harness/fe/rules/team-flow-unit.mdc +6 -6
- package/harness/fe/skills/grill-prototype/SKILL.md +2 -2
- package/harness/fe/skills/grill-test/SKILL.md +1 -1
- package/harness/fe/skills/grill-unit/SKILL.md +2 -2
- package/harness/fe/skills/grill-wire/SKILL.md +1 -1
- package/harness/fe/skills/model/SKILL.md +4 -4
- package/harness/fe/skills/prototype/SKILL.md +23 -11
- package/harness/fe/skills/test/SKILL.md +3 -3
- package/harness/fe/skills/unit/SKILL.md +4 -4
- package/harness/fe/skills/wire/SKILL.md +5 -5
- package/harness/shared/rules/flowgrid-code-optional-integrations.mdc +7 -7
- package/harness/tests/rules/cross-repo-index-routing.mdc +1 -1
- package/harness/tests/rules/flowgrid-test-optional-accelerators.mdc +3 -3
- package/harness/tests/rules/plans-docs-first.mdc +5 -5
- package/harness/tests/skills/grill-testcase/SKILL.md +4 -4
- package/harness/tests/skills/scenario/SKILL.md +3 -3
- package/harness/tests/skills/testcase/SKILL.md +2 -2
- package/package.json +1 -1
- package/templates/shared/bundle-authoring.md +13 -6
- package/templates/shared/default-layout.ejs +47 -2
- package/templates/shared/feature.bundle.yaml +29 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-step audit for bundle interactionCases (invoked only from audit-bundle-gaps on *.bundle.yaml).
|
|
3
|
+
* See harness/docs/extracts/agent-design-context.md — do not run against ir/spec or ir/design.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
function countMutationActions(design) {
|
|
7
|
+
const actions = design?.actions
|
|
8
|
+
if (!Array.isArray(actions)) return 0
|
|
9
|
+
return actions.filter((a) => a && (a.executionContract || a.apiRef)).length
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function interactionCasesComplexityTriggers(bundle) {
|
|
13
|
+
const design = bundle?.design ?? {}
|
|
14
|
+
const statuses = design?.stateMatrix?.recordStatuses
|
|
15
|
+
const statusCount = Array.isArray(statuses) ? statuses.length : 0
|
|
16
|
+
const mutations = countMutationActions(design)
|
|
17
|
+
const scenarios = bundle?.userStories?.scenarios
|
|
18
|
+
const scenarioCount = Array.isArray(scenarios) ? scenarios.length : 0
|
|
19
|
+
const listOnly =
|
|
20
|
+
design?.codegen?.profile === 'list' ||
|
|
21
|
+
String(bundle?.gen?.codegen?.profile || '') === 'list'
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
complex:
|
|
25
|
+
statusCount >= 3 ||
|
|
26
|
+
mutations >= 2 ||
|
|
27
|
+
(!listOnly && scenarioCount >= 4) ||
|
|
28
|
+
Boolean(design?.stateMatrix?.behaviors?.length >= 3),
|
|
29
|
+
statusCount,
|
|
30
|
+
mutations,
|
|
31
|
+
scenarioCount,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {Record<string, unknown>} bundle parsed bundle YAML
|
|
37
|
+
* @param {{ addGap: Function, addConfirm: Function, addWarning: Function }} hooks
|
|
38
|
+
*/
|
|
39
|
+
export function auditInteractionCases(bundle, hooks) {
|
|
40
|
+
const { addGap, addConfirm, addWarning } = hooks
|
|
41
|
+
const ic = bundle?.interactionCases
|
|
42
|
+
const { complex, statusCount, mutations } = interactionCasesComplexityTriggers(bundle)
|
|
43
|
+
|
|
44
|
+
if (ic == null) {
|
|
45
|
+
if (!complex) return
|
|
46
|
+
addConfirm(
|
|
47
|
+
'CONFIRM_INTERACTION_CASES_POLICY',
|
|
48
|
+
'interactionCases',
|
|
49
|
+
'Screen has complex state/actions — declare interactionCases (IC-* + sequenceDiagram)?',
|
|
50
|
+
[
|
|
51
|
+
'(Recommended) Yes — set interactionCases.policy: required and items[]',
|
|
52
|
+
'No — simple screen (set interactionCases.policy: skip + skipReason)',
|
|
53
|
+
'Other — note in qa/',
|
|
54
|
+
],
|
|
55
|
+
0,
|
|
56
|
+
)
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const policy = ic.policy
|
|
61
|
+
if (policy === 'skip') {
|
|
62
|
+
if (!String(ic.skipReason || '').trim()) {
|
|
63
|
+
addWarning(
|
|
64
|
+
'INTERACTION_CASES_SKIP_NO_REASON',
|
|
65
|
+
'interactionCases.skipReason',
|
|
66
|
+
'interactionCases.policy is skip but skipReason is empty.',
|
|
67
|
+
'Declare skipReason explaining why L2 sequences are not needed.',
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const items = Array.isArray(ic.items) ? ic.items : []
|
|
74
|
+
|
|
75
|
+
if (policy === 'required' && items.length === 0) {
|
|
76
|
+
addGap(
|
|
77
|
+
'INTERACTION_CASES_ITEMS_MISSING',
|
|
78
|
+
'critical',
|
|
79
|
+
'interactionCases.items',
|
|
80
|
+
'interactionCases.policy is required but items[] is empty.',
|
|
81
|
+
'Add at least one IC-* item with description and sequenceDiagram.',
|
|
82
|
+
)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (items.length === 0) return
|
|
87
|
+
|
|
88
|
+
const actionIds = new Set(
|
|
89
|
+
(bundle?.design?.actions || [])
|
|
90
|
+
.map((a) => a?.id)
|
|
91
|
+
.filter(Boolean),
|
|
92
|
+
)
|
|
93
|
+
const statuses = new Set(bundle?.design?.stateMatrix?.recordStatuses || [])
|
|
94
|
+
|
|
95
|
+
for (let i = 0; i < items.length; i++) {
|
|
96
|
+
const item = items[i]
|
|
97
|
+
const base = `interactionCases.items[${i}]`
|
|
98
|
+
if (!item?.id) {
|
|
99
|
+
addGap(
|
|
100
|
+
'INTERACTION_CASES_MISSING_ID',
|
|
101
|
+
'critical',
|
|
102
|
+
`${base}.id`,
|
|
103
|
+
'Interaction case missing id (use IC-*).',
|
|
104
|
+
'Declare id: IC-SUBMIT-HAPPY',
|
|
105
|
+
)
|
|
106
|
+
} else if (!/^IC-[A-Z0-9][A-Z0-9-]*$/i.test(String(item.id))) {
|
|
107
|
+
addWarning(
|
|
108
|
+
'INTERACTION_CASES_ID_FORMAT',
|
|
109
|
+
`${base}.id`,
|
|
110
|
+
`Interaction case id "${item.id}" should match IC-* pattern.`,
|
|
111
|
+
'Rename to IC-<DOMAIN>-<CASE> (e.g. IC-SUBMIT-409).',
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
if (!String(item?.title || '').trim()) {
|
|
115
|
+
addGap(
|
|
116
|
+
'INTERACTION_CASES_MISSING_TITLE',
|
|
117
|
+
'critical',
|
|
118
|
+
`${base}.title`,
|
|
119
|
+
'Interaction case missing title.',
|
|
120
|
+
'Add short title for reviewers and agents.',
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
if (!String(item?.description || '').trim()) {
|
|
124
|
+
addGap(
|
|
125
|
+
'INTERACTION_CASES_MISSING_DESCRIPTION',
|
|
126
|
+
'critical',
|
|
127
|
+
`${base}.description`,
|
|
128
|
+
'Interaction case missing description (user case prose).',
|
|
129
|
+
'Describe user steps and expected UI/API feedback.',
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
const seq = String(item?.sequenceDiagram || '')
|
|
133
|
+
if (!seq.includes('sequenceDiagram')) {
|
|
134
|
+
addGap(
|
|
135
|
+
'INTERACTION_CASES_MISSING_SEQUENCE',
|
|
136
|
+
'critical',
|
|
137
|
+
`${base}.sequenceDiagram`,
|
|
138
|
+
'Interaction case missing Mermaid sequenceDiagram.',
|
|
139
|
+
'Add sequenceDiagram with alt/else for error paths when applicable.',
|
|
140
|
+
)
|
|
141
|
+
} else if (!/alt\s+/i.test(seq) && complex) {
|
|
142
|
+
addWarning(
|
|
143
|
+
'INTERACTION_CASES_NO_ALT',
|
|
144
|
+
`${base}.sequenceDiagram`,
|
|
145
|
+
'Sequence diagram has no alt/else block — recommend at least one error branch.',
|
|
146
|
+
'Model validation, 409, or timeout with alt/else.',
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
const actionId = item?.links?.actionId
|
|
150
|
+
if (actionId && actionIds.size && !actionIds.has(actionId)) {
|
|
151
|
+
addWarning(
|
|
152
|
+
'INTERACTION_CASES_UNKNOWN_ACTION',
|
|
153
|
+
`${base}.links.actionId`,
|
|
154
|
+
`links.actionId "${actionId}" not found in design.actions.`,
|
|
155
|
+
'Align with an existing action id or add the action.',
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
const st = item?.links?.recordStatus
|
|
159
|
+
if (st && statuses.size && !statuses.has(st)) {
|
|
160
|
+
addWarning(
|
|
161
|
+
'INTERACTION_CASES_UNKNOWN_STATUS',
|
|
162
|
+
`${base}.links.recordStatus`,
|
|
163
|
+
`links.recordStatus "${st}" not in stateMatrix.recordStatuses.`,
|
|
164
|
+
`Use one of: ${[...statuses].join(', ')}`,
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (policy === 'required' && mutations >= 2 && items.length < mutations) {
|
|
170
|
+
addWarning(
|
|
171
|
+
'INTERACTION_CASES_FEW_ITEMS',
|
|
172
|
+
'interactionCases.items',
|
|
173
|
+
`Only ${items.length} interaction case(s) for ${mutations} mutation action(s).`,
|
|
174
|
+
'Consider one IC-* per critical mutation path (happy + conflict).',
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (complex && !policy) {
|
|
179
|
+
addWarning(
|
|
180
|
+
'INTERACTION_CASES_POLICY_UNSET',
|
|
181
|
+
'interactionCases.policy',
|
|
182
|
+
'interactionCases present but policy not set to required or skip.',
|
|
183
|
+
'Set policy: required or policy: skip with skipReason.',
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import { applyOpenQaField } from './open-qa.mjs'
|
|
21
21
|
import { applyDesignApiFrom01 } from './hydrate-design-api.mjs'
|
|
22
22
|
import { isPlaceholderLegacy, projectBusinessPage } from './project-business-layout.mjs'
|
|
23
|
+
import { applyInteractionCasesToIr } from './interaction-cases.mjs'
|
|
23
24
|
|
|
24
25
|
export function bundlePageId(bundle) {
|
|
25
26
|
const v = bundle?.['page-id'] ?? bundle?.pageId ?? bundle?.id
|
|
@@ -39,6 +40,12 @@ export function buildIrFromBundle(bundle) {
|
|
|
39
40
|
const pageId = bundlePageId(bundle)
|
|
40
41
|
const legacy = { id: pageId, ...(bundle.legacy ?? {}) }
|
|
41
42
|
const design = buildDesignIr(bundle, designSpec, gen)
|
|
43
|
+
if (bundle.interactionCases != null) {
|
|
44
|
+
delete spec.interactionCases
|
|
45
|
+
applyInteractionCasesToIr(spec, design, bundle.interactionCases)
|
|
46
|
+
} else if (spec.interactionCases) {
|
|
47
|
+
delete spec.interactionCases
|
|
48
|
+
}
|
|
42
49
|
|
|
43
50
|
return { spec, legacy, design, designSpec, gen }
|
|
44
51
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split bundle interactionCases → ir/spec (prose) + ir/design (sequenceDiagram only).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {unknown} interactionCases
|
|
7
|
+
* @returns {{ specPart: object|null, designPart: object|null }}
|
|
8
|
+
*/
|
|
9
|
+
export function partitionInteractionCasesForIr(interactionCases) {
|
|
10
|
+
if (!interactionCases || typeof interactionCases !== 'object') {
|
|
11
|
+
return { specPart: null, designPart: null }
|
|
12
|
+
}
|
|
13
|
+
const { policy, skipReason, items } = interactionCases
|
|
14
|
+
const specPart = {
|
|
15
|
+
...(policy != null ? { policy } : {}),
|
|
16
|
+
...(skipReason != null && String(skipReason).trim() ? { skipReason } : {}),
|
|
17
|
+
items: Array.isArray(items)
|
|
18
|
+
? items.map((item) => {
|
|
19
|
+
if (!item || typeof item !== 'object') return item
|
|
20
|
+
const { id, title, description, links } = item
|
|
21
|
+
return { id, title, description, links }
|
|
22
|
+
})
|
|
23
|
+
: [],
|
|
24
|
+
}
|
|
25
|
+
const designItems = Array.isArray(items)
|
|
26
|
+
? items
|
|
27
|
+
.filter((item) => item && typeof item === 'object' && item.sequenceDiagram)
|
|
28
|
+
.map(({ id, sequenceDiagram }) => ({ id, sequenceDiagram }))
|
|
29
|
+
: []
|
|
30
|
+
const designPart = designItems.length ? { items: designItems } : null
|
|
31
|
+
return { specPart, designPart }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {Record<string, unknown>} spec
|
|
36
|
+
* @param {Record<string, unknown>} design
|
|
37
|
+
* @param {unknown} interactionCases from bundle
|
|
38
|
+
*/
|
|
39
|
+
export function applyInteractionCasesToIr(spec, design, interactionCases) {
|
|
40
|
+
const { specPart, designPart } = partitionInteractionCasesForIr(interactionCases)
|
|
41
|
+
if (!specPart && !designPart) return
|
|
42
|
+
if (specPart && (specPart.policy || specPart.skipReason || specPart.items?.length)) {
|
|
43
|
+
spec.interactionCases = specPart
|
|
44
|
+
}
|
|
45
|
+
if (designPart) design.interactionCases = designPart
|
|
46
|
+
}
|
|
@@ -34,7 +34,7 @@ async function main() {
|
|
|
34
34
|
const mdRel = mdOut ? path.relative(process.cwd(), mdOut) : null
|
|
35
35
|
const genDir = mdOut ? path.dirname(mdOut) : null
|
|
36
36
|
const extra = genDir
|
|
37
|
-
? ['data-model.md', 'api.md']
|
|
37
|
+
? ['data-model.md', 'api.md', 'design.md']
|
|
38
38
|
.filter((name) => fs.existsSync(path.join(genDir, name)))
|
|
39
39
|
.map((name) => path.relative(process.cwd(), path.join(genDir, name)))
|
|
40
40
|
: []
|
|
@@ -8,9 +8,9 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
**Owner:** Platform DNA (`--type=be|monolith --be-adapter=dotnet-integration`)
|
|
10
10
|
|
|
11
|
-
.NET integration host ·
|
|
11
|
+
.NET integration host · code repo grill/gen first when applicable.
|
|
12
12
|
|
|
13
|
-
## Gen
|
|
13
|
+
## Gen first (code)
|
|
14
14
|
|
|
15
15
|
1. Prefer codegen / existing templates before free-form scaffolding
|
|
16
16
|
2. AI fills gaps only — do not duplicate generated surfaces
|
|
@@ -8,11 +8,11 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
**Owner:** Platform DNA (`--type=be|monolith --be-adapter=fastapi`)
|
|
10
10
|
|
|
11
|
-
FastAPI · modular packages ·
|
|
11
|
+
FastAPI · modular packages · code repo grill/gen first.
|
|
12
12
|
|
|
13
|
-
## Gen
|
|
13
|
+
## Gen first (code)
|
|
14
14
|
|
|
15
|
-
1.
|
|
15
|
+
1. code repo `gen` / repo shim from IR already grilled
|
|
16
16
|
2. AI only fills `#needs-*` / gaps not yet in `registries/`
|
|
17
17
|
3. Do not hand-write boilerplate codegen already covers
|
|
18
18
|
|
|
@@ -8,11 +8,11 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
**Owner:** Platform DNA (`--type=be|monolith --be-adapter=laravel`)
|
|
10
10
|
|
|
11
|
-
Laravel · `nwidart/laravel-modules` (modules-v1) ·
|
|
11
|
+
Laravel · `nwidart/laravel-modules` (modules-v1) · code repo grill/gen first.
|
|
12
12
|
|
|
13
|
-
## Gen
|
|
13
|
+
## Gen first (code)
|
|
14
14
|
|
|
15
|
-
1.
|
|
15
|
+
1. code repo `gen` / repo shim from IR already grilled
|
|
16
16
|
2. AI only fills `#needs-*` / gaps not yet in registries
|
|
17
17
|
3. Do not hand-write module scaffolding codegen already covers
|
|
18
18
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api
|
|
3
|
-
description: /api — backend API generation through
|
|
3
|
+
description: /api — backend API generation through BE code repo adapters.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# /api — Backend API
|
|
8
8
|
|
|
9
|
-
**Owner:**
|
|
9
|
+
**Owner:** code repo (`--type=be`)
|
|
10
10
|
**Adapters:** `fastapi` · `laravel` · `dotnet-integration` · `nestjs`
|
|
11
11
|
|
|
12
12
|
## Generate
|
|
@@ -52,7 +52,7 @@ FE models (not this skill): `flowgrid contract-gen:dry -- --spec /path/to/ir/des
|
|
|
52
52
|
|
|
53
53
|
## Route
|
|
54
54
|
|
|
55
|
-
Architecture/C4 →
|
|
55
|
+
Architecture/C4 → docs hub (`FLOWGRID_DOCS_ROOT`); IR via explicit `--spec` /
|
|
56
56
|
`FLOWGRID_DOCS_ROOT` when configured — never ArtifactGraph as the docs
|
|
57
57
|
bridge. This-repo conventions → local CodeGraph if present; other repo X →
|
|
58
58
|
only Platform DNA-wired `codegraph-<key>`. ArtifactGraph = local allowlist
|
|
@@ -87,7 +87,7 @@ warns and uses entity-local CRUD defaults.
|
|
|
87
87
|
|
|
88
88
|
```text
|
|
89
89
|
if ArtifactGraph available: allowlist/recommend API generation
|
|
90
|
-
else: execute
|
|
90
|
+
else: execute code repo adapter directly
|
|
91
91
|
|
|
92
92
|
if CodeGraph available for this checkout (`codegraph-<key>`): inspect existing module conventions/callers
|
|
93
93
|
else: targeted repository search — never a workspace-parent graph
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api-unit
|
|
3
|
-
description: /unit — backend API unit test generation via
|
|
3
|
+
description: /unit — backend API unit test generation via BE code repo adapters.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# /unit — Backend API Unit Tests
|
|
8
8
|
|
|
9
|
-
**Owner:**
|
|
9
|
+
**Owner:** code repo (`--type=be`)
|
|
10
10
|
**Adapters:** `fastapi` · `laravel` · `nestjs`
|
|
11
11
|
|
|
12
12
|
> `dotnet-integration` emits test source during its primary API pass; it has no
|
|
@@ -48,7 +48,7 @@ Requires a prior `01-backend-spec.yaml` under the docs hub API folder.
|
|
|
48
48
|
|
|
49
49
|
## Route
|
|
50
50
|
|
|
51
|
-
Architecture/C4 →
|
|
51
|
+
Architecture/C4 → docs hub (`FLOWGRID_DOCS_ROOT`); spec via explicit `--spec` /
|
|
52
52
|
`FLOWGRID_DOCS_ROOT` when configured — never ArtifactGraph as the docs
|
|
53
53
|
bridge. This-repo conventions → local CodeGraph if present; other repo X →
|
|
54
54
|
only Platform DNA-wired `codegraph-<key>`. ArtifactGraph = local allowlist
|
|
@@ -64,7 +64,7 @@ hints only.
|
|
|
64
64
|
|
|
65
65
|
```text
|
|
66
66
|
if ArtifactGraph available: allowlist/recommend API unit generation
|
|
67
|
-
else: execute
|
|
67
|
+
else: execute code repo adapter directly
|
|
68
68
|
|
|
69
69
|
if CodeGraph available for this checkout (`codegraph-<key>`): inspect existing test conventions
|
|
70
70
|
else: targeted repository search — never a workspace-parent graph
|
|
@@ -8,7 +8,7 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
Run after `npm run codegen:api:dry` / `flowgrid api-gen:dry` and after implementation.
|
|
10
10
|
|
|
11
|
-
**Owner:**
|
|
11
|
+
**Owner:** code repo (`--type=be`). Docs hub is **read-only**.
|
|
12
12
|
|
|
13
13
|
## Target / ID Resolution Rule
|
|
14
14
|
|
|
@@ -36,7 +36,7 @@ Check:
|
|
|
36
36
|
- Writes are transaction-safe; async retries are idempotent.
|
|
37
37
|
- Generated placeholders are replaced before ship.
|
|
38
38
|
|
|
39
|
-
**CLI (
|
|
39
|
+
**CLI (quantitative):** `flowgrid audit api` on `01`; when portal bundle exists → `flowgrid audit fe-be` on sibling `*.bundle.yaml`.
|
|
40
40
|
|
|
41
41
|
## Accelerators (optional)
|
|
42
42
|
|
|
@@ -47,7 +47,7 @@ else: scoped contract-to-code comparison
|
|
|
47
47
|
if codegraph-<repo-key> for this checkout: callers/routes/jobs/listeners
|
|
48
48
|
else: targeted repository search
|
|
49
49
|
|
|
50
|
-
architecture IDs / C4 →
|
|
50
|
+
architecture IDs / C4 → docs hub (FLOWGRID_DOCS_ROOT), never CodeGraph
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Missing accelerators never block the audit. Complete each scoped model or
|
|
@@ -6,7 +6,7 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# /grill-unit
|
|
8
8
|
|
|
9
|
-
**Owner:**
|
|
9
|
+
**Owner:** code repo · audit gate before BE unit test generation.
|
|
10
10
|
|
|
11
11
|
Run after `npm run codegen:api:unit:dry` / `flowgrid api-unit-gen:dry` and
|
|
12
12
|
before committing generated test code.
|
|
@@ -50,7 +50,7 @@ else: scoped spec-to-test comparison
|
|
|
50
50
|
if codegraph-<repo-key> for this checkout: callers/routes/existing test patterns
|
|
51
51
|
else: targeted repository search
|
|
52
52
|
|
|
53
|
-
architecture IDs / C4 →
|
|
53
|
+
architecture IDs / C4 → docs hub (FLOWGRID_DOCS_ROOT), never CodeGraph
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Missing accelerators never block the grill. Complete each scoped model or
|
|
@@ -14,9 +14,9 @@ alwaysApply: false
|
|
|
14
14
|
|
|
15
15
|
## Cross-repo routing
|
|
16
16
|
|
|
17
|
-
- Architecture ID / C4 →
|
|
17
|
+
- Architecture ID / C4 → docs hub (`FLOWGRID_DOCS_ROOT`), not CodeGraph and not
|
|
18
18
|
ArtifactGraph.
|
|
19
|
-
- IR / registry / generation →
|
|
19
|
+
- IR / registry / generation → code repo / tests hub pointers
|
|
20
20
|
(`FLOWGRID_DOCS_ROOT`, `FLOWGRID_DOCS_ROOT`, `FLOWGRID_TESTS_DOC`).
|
|
21
21
|
- Symbol / call-graph of repo X → `codegraph-<key>` MCP for checkout X.
|
|
22
22
|
- ArtifactGraph is local-only: never follow those pointers, never read repo
|
|
@@ -9,13 +9,13 @@ Do not merge every repository into a single workspace graph (the parent folder
|
|
|
9
9
|
must never be indexed). "Cross-repo" means a skill/rule knows how to reach the
|
|
10
10
|
**correct per-repo index**, one repository at a time.
|
|
11
11
|
|
|
12
|
-
**Owner:** Platform DNA. FlowGrid harness rules (
|
|
12
|
+
**Owner:** Platform DNA. FlowGrid harness rules (docs hub, process hub, …) install this same
|
|
13
13
|
filename only when DNA is absent, so a destination never carries duplicate
|
|
14
14
|
`alwaysApply` routing rules under different names.
|
|
15
15
|
|
|
16
16
|
Route by intent:
|
|
17
17
|
|
|
18
|
-
- Need an architecture ID or C4 path ->
|
|
18
|
+
- Need an architecture ID or C4 path -> docs hub MCP (`FLOWGRID_DOCS_ROOT`). Never
|
|
19
19
|
CodeGraph for architecture Markdown.
|
|
20
20
|
- Need IR / registry / generation -> the pointer kit
|
|
21
21
|
(`FLOWGRID_DOCS_ROOT`, `FLOWGRID_DOCS_ROOT`, `FLOWGRID_TESTS_DOC`).
|
|
@@ -8,17 +8,17 @@ alwaysApply: false
|
|
|
8
8
|
|
|
9
9
|
Soft limits — split in the same PR when exceeded.
|
|
10
10
|
|
|
11
|
-
|
|
|
11
|
+
| Exceeds ~200 lines/file | Split | Suggest Tag DSL (`/docs-mark`) |
|
|
12
12
|
|---------------------|------|------------------------------|
|
|
13
|
-
| Page `.vue` | Composable + sub-component | `#needs-component: sub-{name}:MoXxx`
|
|
13
|
+
| Page `.vue` | Composable + sub-component | `#needs-component: sub-{name}:MoXxx` or `#common-ui` |
|
|
14
14
|
| Composable | `useXxxForm`, `useXxxList`, … | `#common-ui` / `#needs-ui` |
|
|
15
|
-
| Service / store | File
|
|
15
|
+
| Service / store | File per aggregate; complex action → service | `#cross-service` / `#cross-entity-service` / `#needs-service` |
|
|
16
16
|
| E2E spec | Page Object + helper | `#e2e-test` bundle split |
|
|
17
17
|
|
|
18
|
-
|
|
|
18
|
+
| Exceeds ~20 lines/function | Split | Suggest Tag DSL (`/docs-mark`) |
|
|
19
19
|
|------------------------|------|------------------------------|
|
|
20
20
|
| Submit handler | `buildPayload`, `validateBeforeSubmit`, `handleApiError` | `#needs-service` / local helper |
|
|
21
21
|
| Map/transform | Pure helpers / computed | `#derived-data` |
|
|
22
22
|
|
|
23
23
|
No padding files with blank lines. Component split: `platform-component-split.mdc`.
|
|
24
|
-
|
|
24
|
+
When a file or function hits an exceed threshold, the agent should proactively propose the matching tag (via `/docs-mark`) and update the registry (`registries/design.registry.json` or `registries/common.registry.json`) for reuse later.
|
|
@@ -6,7 +6,7 @@ alwaysApply: false
|
|
|
6
6
|
|
|
7
7
|
# Harness State
|
|
8
8
|
|
|
9
|
-
- `feature_list.json` — scope
|
|
10
|
-
- `progress.md` — handoff
|
|
11
|
-
- `registries/page-lifecycle.registry.json` + `base-docs/platform/toolchain/PAGE-LIFECYCLE.md` — stage
|
|
12
|
-
-
|
|
9
|
+
- `feature_list.json` — scope; do not mark done without verification
|
|
10
|
+
- `progress.md` — handoff for the next session
|
|
11
|
+
- `registries/page-lifecycle.registry.json` + `base-docs/platform/toolchain/PAGE-LIFECYCLE.md` — highest stage per route; `portal:gen` / `portal:remove` / `portal:lifecycle sync` update automatically
|
|
12
|
+
- When a public command updates phase, record clearly: command, files changed, verify run or not, remaining blockers.
|
|
@@ -90,7 +90,7 @@ if CodeGraph available: changed symbols + callers + call graph — for repo X us
|
|
|
90
90
|
open repo's index; unindexed repo → report `cd <root> && codegraph init`
|
|
91
91
|
else: targeted repository search/read
|
|
92
92
|
|
|
93
|
-
if
|
|
93
|
+
if docs hub available: map process steps to CMP/CTR/FLOW docs via FLOWGRID_DOCS_ROOT
|
|
94
94
|
(never CodeGraph for architecture Markdown)
|
|
95
95
|
else: repository conventions/search
|
|
96
96
|
|
|
@@ -55,6 +55,6 @@ legacy ERP at D:\legacy\erp, key legacy-erp
|
|
|
55
55
|
## After Write
|
|
56
56
|
|
|
57
57
|
1. Compare with `.flowgrid/config.json` (init SSOT): `flowgrid repo-maps check`.
|
|
58
|
-
2. If paths conflict with init/harness MCP: `flowgrid repo-maps align` (member
|
|
58
|
+
2. If paths conflict with init/harness MCP: `flowgrid repo-maps align` (member confirms each hub `docs` / `tests`).
|
|
59
59
|
3. One-way refresh from config: `flowgrid repo-maps sync --from-config` then `flowgrid harness sync`.
|
|
60
60
|
4. Optional CodeGraph: `platform-dna codegraph:wire` · `codegraph init` per checkout.
|
|
@@ -31,13 +31,13 @@ fallbacks.
|
|
|
31
31
|
| UI | `registries/design.registry.json` | `#needs-component:` `#needs-ui:` `#shell:` |
|
|
32
32
|
| Logic | `registries/common.registry.json` | `#common:*` `#needs-common:*` |
|
|
33
33
|
|
|
34
|
-
Executable registry validation is **
|
|
34
|
+
Executable registry validation is **FE code repo** (or product scripts on the
|
|
35
35
|
FE checkout). On docs hub:
|
|
36
36
|
|
|
37
37
|
```text
|
|
38
38
|
if ArtifactGraph available:
|
|
39
39
|
artifactgraph_allowlist_check(registryValidate|commonRegistry)
|
|
40
|
-
artifactgraph_recommend_command → hand off to
|
|
40
|
+
artifactgraph_recommend_command → hand off to FE code repo
|
|
41
41
|
else:
|
|
42
42
|
note pending FE registry validate; do not invent local shell fallbacks
|
|
43
43
|
```
|
|
@@ -58,8 +58,8 @@ else:
|
|
|
58
58
|
|
|
59
59
|
## Handoff
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
when that lane is available. Missing
|
|
61
|
+
FE code repo / product: `flowgrid gen:dry` (or repo shim) after marks change,
|
|
62
|
+
when that lane is available. Missing code repo is a pending handoff, not a
|
|
63
63
|
docs failure.
|
|
64
64
|
|
|
65
65
|
## Compatibility
|