create-byan-agent 2.19.2 → 2.20.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.
- package/CHANGELOG.md +148 -0
- package/README.md +4 -4
- package/install/src/byan-v2/generation/templates/default-agent.md +1 -1
- package/install/templates/.claude/CLAUDE.md +1 -1
- package/install/templates/.claude/hooks/fd-phase-guard.js +2 -2
- package/install/templates/.claude/hooks/mantra-validate.js +16 -8
- package/install/templates/.claude/hooks/strict-scope-guard.js +25 -7
- package/install/templates/.claude/rules/native-workflows.md +32 -0
- package/install/templates/.claude/skills/byan-byan/SKILL.md +5 -5
- package/install/templates/.claude/skills/byan-mantra-audit/SKILL.md +53 -0
- package/install/templates/.claude/skills/byan-merise-agile/SKILL.md +2 -2
- package/install/templates/.claude/skills/byan-native-dev-story/SKILL.md +83 -0
- package/install/templates/.claude/workflows/INDEX.md +35 -0
- package/install/templates/.claude/workflows/check-implementation-readiness.js +280 -0
- package/install/templates/.claude/workflows/code-review.js +179 -0
- package/install/templates/.claude/workflows/create-excalidraw-dataflow.js +214 -0
- package/install/templates/.claude/workflows/create-excalidraw-diagram.js +188 -0
- package/install/templates/.claude/workflows/create-excalidraw-flowchart.js +225 -0
- package/install/templates/.claude/workflows/create-excalidraw-wireframe.js +192 -0
- package/install/templates/.claude/workflows/create-story.js +216 -0
- package/install/templates/.claude/workflows/dev-story.js +100 -0
- package/install/templates/.claude/workflows/document-project.js +455 -0
- package/install/templates/.claude/workflows/qa-automate.js +169 -0
- package/install/templates/.claude/workflows/quick-dev.js +273 -0
- package/install/templates/.claude/workflows/sprint-planning.js +261 -0
- package/install/templates/.claude/workflows/testarch-atdd.js +287 -0
- package/install/templates/.claude/workflows/testarch-automate.js +229 -0
- package/install/templates/.claude/workflows/testarch-ci.js +184 -0
- package/install/templates/.claude/workflows/testarch-framework.js +267 -0
- package/install/templates/.claude/workflows/testarch-nfr.js +316 -0
- package/install/templates/.claude/workflows/testarch-test-design.js +293 -0
- package/install/templates/.claude/workflows/testarch-test-review.js +321 -0
- package/install/templates/.claude/workflows/testarch-trace.js +316 -0
- package/install/templates/.githooks/pre-commit +49 -15
- package/install/templates/_byan/config.yaml +15 -5
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-build-workflows.js +20 -0
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-lint-workflows.js +57 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/native-loop.js +39 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-generator.js +149 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +113 -0
- package/install/templates/_byan/workflow/simple/byan/feature-workflow.md +14 -11
- package/install/templates/docs/native-workflows-contract.md +84 -0
- package/package.json +2 -2
- package/src/byan-v2/data/agent-scopes.json +46 -0
- package/src/byan-v2/data/mantras.json +194 -8
- package/src/byan-v2/generation/mantra-audit.js +147 -0
- package/src/byan-v2/generation/mantra-validator.js +56 -6
- package/src/byan-v2/generation/scope-resolver.js +102 -0
- package/src/byan-v2/generation/templates/default-agent.md +1 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'create-excalidraw-wireframe',
|
|
3
|
+
description: 'Native port of the BYAN create-excalidraw-wireframe workflow: plan a website/app wireframe, load Excalidraw resources, build elements per screen at the requested fidelity, optimize and save the .excalidraw file, then validate JSON syntax (bounded fix loop) and content against the checklist. Returns a structured verdict; the elicitation steps (type, requirements, theme) stay at the human gate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'CONTEXT', detail: 'step 0 - extract type, fidelity, screen count, device, save location from the request' },
|
|
6
|
+
{ title: 'PLAN', detail: 'step 5 - list screens, map navigation flow, identify key UI elements' },
|
|
7
|
+
{ title: 'LOAD', detail: 'step 6 - load templates(wireframe), library, theme.json, helpers' },
|
|
8
|
+
{ title: 'BUILD', detail: 'step 7 - build wireframe elements per screen in the prescribed build order at the chosen fidelity' },
|
|
9
|
+
{ title: 'SAVE', detail: 'step 8 - strip unused/isDeleted elements and save to the output file' },
|
|
10
|
+
{ title: 'VALIDATE_JSON', detail: 'step 9 - JSON.parse the file; on failure fix syntax and re-check (bounded loop)' },
|
|
11
|
+
{ title: 'VALIDATE_CONTENT', detail: 'step 10 - validate against checklist.md' },
|
|
12
|
+
{ title: 'VERDICT', detail: 'return a structured verdict to the orchestrating skill' },
|
|
13
|
+
],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// FD / STRICT STATE CONTRACT (re-asserted inline — enforcement-bridge).
|
|
18
|
+
//
|
|
19
|
+
// The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
|
|
20
|
+
// BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, strict-stop-
|
|
21
|
+
// guard, mantra-validate) DO NOT fire here. This script therefore:
|
|
22
|
+
// - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
|
|
23
|
+
// fd-state.json directly (enforced by byan-lint-workflows.js).
|
|
24
|
+
// - uses NO wall-clock and NO randomness primitive (a fixed timestamp/id is
|
|
25
|
+
// passed in via args so resume stays deterministic).
|
|
26
|
+
// - returns DATA only. The orchestrating skill is the human-gated conductor;
|
|
27
|
+
// IT records FD/strict state via the byan_fd_* / byan_strict_* MCP tools
|
|
28
|
+
// AT the gate, and owns the four elicit="true" steps (1: wireframe type,
|
|
29
|
+
// 2: requirements, 3: check theme, 4: create theme) — those are human
|
|
30
|
+
// decisions and are intentionally kept OUT of this autonomous engine.
|
|
31
|
+
// The .excalidraw FILE is the workflow's product, written by the SAVE leaf —
|
|
32
|
+
// that is the artifact, not BYAN platform state.
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
// Source paths (workflow.yaml) — passed to the agents so they read the REAL
|
|
36
|
+
// resources rather than inventing schema/colors.
|
|
37
|
+
const SRC = {
|
|
38
|
+
helpers: '_byan/connaissance/excalidraw/excalidraw-helpers.md',
|
|
39
|
+
jsonValidation: '_byan/connaissance/excalidraw/validate-json-instructions.md',
|
|
40
|
+
templates: '_byan/workflow/simple/excalidraw-diagrams/_shared/excalidraw-templates.yaml',
|
|
41
|
+
library: '_byan/workflow/simple/excalidraw-diagrams/_shared/excalidraw-library.json',
|
|
42
|
+
checklist: '_byan/workflow/simple/excalidraw-diagrams/create-wireframe/checklist.md',
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Inputs come from the human-gated elicitation steps (1-4), threaded in via args.
|
|
46
|
+
// Defaults keep the engine runnable; the skill overrides them at the gate.
|
|
47
|
+
const wireframeType = (args && args.wireframeType) || 'Web App (Responsive)'
|
|
48
|
+
const fidelity = (args && args.fidelity) || 'Medium'
|
|
49
|
+
const screenCount = (args && args.screenCount) || 'Few (2-3)'
|
|
50
|
+
const device = (args && args.device) || 'standard responsive dimensions'
|
|
51
|
+
const theme = (args && args.theme) || 'Classic Wireframe (white bg / light-gray container / gray border / dark-gray text)'
|
|
52
|
+
// timestamp/id MUST be supplied (no clock/RNG in the sandbox).
|
|
53
|
+
const timestamp = (args && args.timestamp) || 'TIMESTAMP'
|
|
54
|
+
const outputFile = (args && args.outputFile) || `_byan-output/excalidraw-diagrams/wireframe-${timestamp}.excalidraw`
|
|
55
|
+
|
|
56
|
+
// JSON-validation convergence guard (step 9). Mirrors the prose rule
|
|
57
|
+
// "Repeat until validation passes" with a real integer cap so the model
|
|
58
|
+
// cannot loop forever. NEVER delete the file on failure — always fix syntax.
|
|
59
|
+
const MAX_FIX_PASSES = 3
|
|
60
|
+
|
|
61
|
+
const VALIDATE_JSON_SCHEMA = {
|
|
62
|
+
type: 'object',
|
|
63
|
+
required: ['valid'],
|
|
64
|
+
properties: {
|
|
65
|
+
valid: { type: 'boolean', description: 'true ONLY if JSON.parse on the saved file succeeded' },
|
|
66
|
+
error: { type: 'string', description: 'the parser error and position when not valid' },
|
|
67
|
+
fixed: { type: 'boolean', description: 'true if a syntax fix was applied this pass' },
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const CHECKLIST_SCHEMA = {
|
|
72
|
+
type: 'object',
|
|
73
|
+
required: ['pass', 'failedItems'],
|
|
74
|
+
properties: {
|
|
75
|
+
pass: { type: 'boolean', description: 'true only if every checklist item is satisfied' },
|
|
76
|
+
failedItems: { type: 'array', items: { type: 'string' }, description: 'checklist items not satisfied' },
|
|
77
|
+
notes: { type: 'string' },
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// --- STEP 0: Contextual Analysis -------------------------------------------
|
|
82
|
+
phase('CONTEXT')
|
|
83
|
+
const context = await agent(
|
|
84
|
+
`You are create-excalidraw-wireframe (step 0, Contextual Analysis).\n` +
|
|
85
|
+
`Locked inputs from the human gate: type=${JSON.stringify(wireframeType)}, ` +
|
|
86
|
+
`fidelity=${JSON.stringify(fidelity)}, screenCount=${JSON.stringify(screenCount)}, ` +
|
|
87
|
+
`device=${JSON.stringify(device)}, theme=${JSON.stringify(theme)}, output=${JSON.stringify(outputFile)}.\n` +
|
|
88
|
+
`Restate these requirements cleanly and flag any that are still ambiguous (do NOT ask the user — ` +
|
|
89
|
+
`this engine runs headless; surface ambiguity as a note for the gate).`,
|
|
90
|
+
{ label: 'context', phase: 'CONTEXT' }
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
// --- STEP 5: Plan Wireframe Structure --------------------------------------
|
|
94
|
+
phase('PLAN')
|
|
95
|
+
const plan = await agent(
|
|
96
|
+
`Step 5 (Plan Wireframe Structure). Context: ${context}\n` +
|
|
97
|
+
`List every screen and its purpose, map the navigation flow between screens, and identify the key UI ` +
|
|
98
|
+
`elements per screen. Honor screenCount=${JSON.stringify(screenCount)} and device=${JSON.stringify(device)}. ` +
|
|
99
|
+
`Output the planned structure as a clear screen-by-screen outline.`,
|
|
100
|
+
{ label: 'plan', phase: 'PLAN' }
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
// --- STEP 6: Load Resources ------------------------------------------------
|
|
104
|
+
phase('LOAD')
|
|
105
|
+
const resources = await agent(
|
|
106
|
+
`Step 6 (Load Resources). Read these REAL files and extract what is needed:\n` +
|
|
107
|
+
`- templates: ${SRC.templates} (extract the \`wireframe\` section)\n` +
|
|
108
|
+
`- library: ${SRC.library}\n` +
|
|
109
|
+
`- helpers: ${SRC.helpers} (the authoritative element-creation rules)\n` +
|
|
110
|
+
`- the chosen theme: ${JSON.stringify(theme)} (use a theme.json if one exists).\n` +
|
|
111
|
+
`Summarize the wireframe template primitives, the relevant library elements, the theme color tokens, ` +
|
|
112
|
+
`and the element-creation constraints from helpers (grid 20px, containerId on text, grouping).`,
|
|
113
|
+
{ label: 'load-resources', phase: 'LOAD' }
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
// --- STEP 7: Build Wireframe Elements --------------------------------------
|
|
117
|
+
phase('BUILD')
|
|
118
|
+
const build = await agent(
|
|
119
|
+
`Step 7 (Build Wireframe Elements). Follow ${SRC.helpers} strictly for element creation.\n` +
|
|
120
|
+
`Plan: ${plan}\nResources: ${resources}\n` +
|
|
121
|
+
`For EACH screen create: container/frame, header section, content areas, navigation elements, ` +
|
|
122
|
+
`interactive elements (buttons, inputs), labels and annotations.\n` +
|
|
123
|
+
`Respect this BUILD ORDER: (1) screen containers, (2) layout sections header/content/footer, ` +
|
|
124
|
+
`(3) navigation elements, (4) content blocks, (5) interactive elements, (6) labels/annotations, ` +
|
|
125
|
+
`(7) flow indicators if multi-screen.\n` +
|
|
126
|
+
`Apply fidelity=${JSON.stringify(fidelity)} — Low: basic shapes, minimal detail, placeholder text; ` +
|
|
127
|
+
`Medium: more defined elements, some styling, representative content; ` +
|
|
128
|
+
`High: detailed elements, realistic sizing, actual content examples.\n` +
|
|
129
|
+
`Produce the full Excalidraw element set (valid scene JSON) for all screens.`,
|
|
130
|
+
{ label: 'build', phase: 'BUILD' }
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
// --- STEP 8: Optimize and Save ---------------------------------------------
|
|
134
|
+
phase('SAVE')
|
|
135
|
+
const saved = await agent(
|
|
136
|
+
`Step 8 (Optimize and Save). Built scene: ${build}\n` +
|
|
137
|
+
`Strip unused elements and any element with isDeleted:true. Then save the cleaned Excalidraw scene ` +
|
|
138
|
+
`to ${JSON.stringify(outputFile)} (create parent directories as needed). Report the saved path.`,
|
|
139
|
+
{ label: 'save', phase: 'SAVE' }
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
// --- STEP 9: Validate JSON Syntax (bounded fix loop) -----------------------
|
|
143
|
+
phase('VALIDATE_JSON')
|
|
144
|
+
let jsonPass = 0
|
|
145
|
+
let jsonResult = { valid: false, error: 'not started' }
|
|
146
|
+
while (true) {
|
|
147
|
+
jsonPass += 1
|
|
148
|
+
jsonResult = await agent(
|
|
149
|
+
`Step 9 (Validate JSON Syntax), pass ${jsonPass}/${MAX_FIX_PASSES}. Saved file: ${saved}\n` +
|
|
150
|
+
`Run: node -e "JSON.parse(require('fs').readFileSync('${outputFile}', 'utf8')); console.log('Valid JSON')".\n` +
|
|
151
|
+
`Follow ${SRC.jsonValidation} for the validation procedure. ` +
|
|
152
|
+
`CRITICAL: NEVER delete the file if validation fails — read the parser error (it shows the syntax ` +
|
|
153
|
+
`error and position), open the file at that location, fix the missing comma/bracket/quote, save, ` +
|
|
154
|
+
`and report. Set valid=true only when JSON.parse succeeds.`,
|
|
155
|
+
{ label: `validate-json-${jsonPass}`, phase: 'VALIDATE_JSON', schema: VALIDATE_JSON_SCHEMA }
|
|
156
|
+
)
|
|
157
|
+
log(`json pass ${jsonPass}: valid=${Boolean(jsonResult && jsonResult.valid)}`)
|
|
158
|
+
if (jsonResult && jsonResult.valid) break
|
|
159
|
+
if (jsonPass >= MAX_FIX_PASSES) break
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// --- STEP 10: Validate Content (against checklist) -------------------------
|
|
163
|
+
phase('VALIDATE_CONTENT')
|
|
164
|
+
const checklist = await agent(
|
|
165
|
+
`Step 10 (Validate Content). Validate the saved wireframe ${JSON.stringify(outputFile)} against the ` +
|
|
166
|
+
`REAL checklist at ${SRC.checklist}. Check layout structure (device-appropriate dimensions, 20px grid ` +
|
|
167
|
+
`alignment, consistent spacing, header/content/footer hierarchy), UI elements (interactive elements ` +
|
|
168
|
+
`marked, controls sized, readable labels, navigation indicated), fidelity match (${JSON.stringify(fidelity)}), ` +
|
|
169
|
+
`annotations (interactions, flow indicators if multi-screen, notes, element purposes), and technical ` +
|
|
170
|
+
`quality (grouping, text containerId, grid snapping, no isDeleted:true, valid JSON, correct save path). ` +
|
|
171
|
+
`Report pass=true only if every item is satisfied; otherwise list the failed items.`,
|
|
172
|
+
{ label: 'validate-content', phase: 'VALIDATE_CONTENT', schema: CHECKLIST_SCHEMA }
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
// --- VERDICT: data only, gate is owned by the orchestrating skill ----------
|
|
176
|
+
phase('VERDICT')
|
|
177
|
+
const jsonValid = Boolean(jsonResult && jsonResult.valid)
|
|
178
|
+
const contentPass = Boolean(checklist && checklist.pass)
|
|
179
|
+
return {
|
|
180
|
+
workflow: 'create-excalidraw-wireframe',
|
|
181
|
+
summary: `Wireframe (${wireframeType}, ${fidelity} fidelity, ${screenCount}) built and saved to ${outputFile}.`,
|
|
182
|
+
inputs: { wireframeType, fidelity, screenCount, device, theme, outputFile },
|
|
183
|
+
steps: 7,
|
|
184
|
+
outputFile,
|
|
185
|
+
jsonValid,
|
|
186
|
+
jsonFixPasses: jsonPass,
|
|
187
|
+
maxJsonFixPasses: MAX_FIX_PASSES,
|
|
188
|
+
contentPass,
|
|
189
|
+
failedChecklistItems: (checklist && checklist.failedItems) || [],
|
|
190
|
+
status: jsonValid && contentPass ? 'ready-for-review' : jsonValid ? 'content-gaps' : 'invalid-json',
|
|
191
|
+
needsHumanGate: true,
|
|
192
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'create-story',
|
|
3
|
+
description: 'Native port of the BYAN create-story workflow: select the next backlog story, exhaustively analyze epics + previous story + git + architecture, web-research latest tech, write the ULTIMATE ready-for-dev story file from the template, then return a structured verdict for the orchestrating skill to update sprint-status and present at the human gate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'TARGET', detail: 'determine the target story (auto-discover first backlog from sprint-status, or use the provided story key)' },
|
|
6
|
+
{ title: 'ARTIFACTS', detail: 'load + exhaustively analyze epics, previous story learnings, and git history' },
|
|
7
|
+
{ title: 'ARCHITECTURE', detail: 'extract architecture guardrails the developer MUST follow' },
|
|
8
|
+
{ title: 'RESEARCH', detail: 'web-research latest stable versions / breaking changes for the relevant tech' },
|
|
9
|
+
{ title: 'WRITE', detail: 'create the comprehensive story file from template.md and set Status: ready-for-dev' },
|
|
10
|
+
{ title: 'FINALIZE', detail: 'validate against the checklist and return a verdict (sprint-status update + report happen at the gate)' },
|
|
11
|
+
],
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// FD / STRICT STATE CONTRACT (re-asserted inline).
|
|
16
|
+
//
|
|
17
|
+
// The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
|
|
18
|
+
// BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, mantra-validate)
|
|
19
|
+
// DO NOT fire here. This script therefore:
|
|
20
|
+
// - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
|
|
21
|
+
// fd-state.json directly (enforced by byan-lint-workflows.js).
|
|
22
|
+
// - uses NO wall-clock and NO randomness primitive (Date/RNG break
|
|
23
|
+
// resume); any date/id is passed in via args.
|
|
24
|
+
// - returns DATA only. The orchestrating skill is the human-gated conductor:
|
|
25
|
+
// IT updates sprint-status.yaml (source step 6) and records FD/strict state
|
|
26
|
+
// via the byan_fd_* / byan_strict_* MCP tools AT the gate. Source step 1's
|
|
27
|
+
// HALT/ask branches (no sprint file, no backlog, done/invalid epic) are
|
|
28
|
+
// human gates -> surfaced as a verdict, never decided inside the script.
|
|
29
|
+
// The story FILE (the {{story_key}}.md product) is the workflow's artifact,
|
|
30
|
+
// written by the WRITE leaf — that is the deliverable, not BYAN platform state.
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
// Inputs are passed in (no fs, no clock, no RNG in the sandbox).
|
|
34
|
+
// storyKey: explicit "epic-story-title" the user provided (skips auto-discover).
|
|
35
|
+
// date: caller-supplied date string for the story header (system-generated upstream).
|
|
36
|
+
const storyKey = (args && args.storyKey) || null
|
|
37
|
+
const date = (args && args.date) || 'unspecified'
|
|
38
|
+
const storyDir = (args && args.storyDir) || '{implementation_artifacts}'
|
|
39
|
+
|
|
40
|
+
// Verdict shape for the TARGET step: either a story is resolved, or we hit one
|
|
41
|
+
// of source step 1's human-gate conditions (HALT/ask) that the script must NOT
|
|
42
|
+
// resolve on its own.
|
|
43
|
+
const TARGET_SCHEMA = {
|
|
44
|
+
type: 'object',
|
|
45
|
+
required: ['resolved'],
|
|
46
|
+
properties: {
|
|
47
|
+
resolved: { type: 'boolean', description: 'true if a concrete target story key was determined' },
|
|
48
|
+
epicNum: { type: 'string' },
|
|
49
|
+
storyNum: { type: 'string' },
|
|
50
|
+
storyKey: { type: 'string', description: 'e.g. 1-2-user-authentication' },
|
|
51
|
+
storyId: { type: 'string', description: 'e.g. 1.2' },
|
|
52
|
+
storyTitle: { type: 'string' },
|
|
53
|
+
isFirstStoryInEpic: { type: 'boolean', description: 'true if matches {epicNum}-1-*; epic should be flagged in-progress at the gate' },
|
|
54
|
+
gate: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'human-gate condition when resolved=false: no-sprint-status | no-backlog | epic-done | invalid-epic-status | none',
|
|
57
|
+
},
|
|
58
|
+
gateMessage: { type: 'string', description: 'message to surface to the human when resolved=false' },
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Verdict shape for the final FINALIZE step.
|
|
63
|
+
const FINAL_SCHEMA = {
|
|
64
|
+
type: 'object',
|
|
65
|
+
required: ['storyFileWritten', 'status', 'checklistVerdict'],
|
|
66
|
+
properties: {
|
|
67
|
+
storyFileWritten: { type: 'boolean' },
|
|
68
|
+
storyFilePath: { type: 'string' },
|
|
69
|
+
status: { type: 'string', description: "the Status set in the story file; must be 'ready-for-dev' on success" },
|
|
70
|
+
checklistVerdict: { type: 'string', enum: ['pass', 'gaps'], description: 'result of validating the story against checklist.md' },
|
|
71
|
+
criticalIssues: { type: 'array', items: { type: 'string' }, description: 'checklist critical misses (must-fix)' },
|
|
72
|
+
enhancements: { type: 'array', items: { type: 'string' } },
|
|
73
|
+
openQuestions: { type: 'array', items: { type: 'string' }, description: 'questions saved for the end (source: SAVE QUESTIONS rule)' },
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// === STEP 1 — Determine target story =======================================
|
|
78
|
+
// Source: instructions.xml step n="1". Auto-discover the FIRST backlog story
|
|
79
|
+
// from sprint-status.yaml (read top-to-bottom, preserve order), OR honour an
|
|
80
|
+
// explicitly provided story key. The HALT/ask branches (missing sprint file,
|
|
81
|
+
// no backlog story, epic done, invalid epic status) are HUMAN gates: the agent
|
|
82
|
+
// reports them via resolved=false + gate, it does NOT pick or HALT autonomously.
|
|
83
|
+
phase('TARGET')
|
|
84
|
+
const target = await agent(
|
|
85
|
+
`You are create-story (BYAN). Goal: determine the target story.\n` +
|
|
86
|
+
`Read the REAL source: _byan/workflow/simple/4-implementation/create-story/workflow.yaml and instructions.xml (step 1).\n` +
|
|
87
|
+
(storyKey
|
|
88
|
+
? `The user provided a story key: ${JSON.stringify(storyKey)}. Parse it into epicNum, storyNum, storyTitle (format "epic-story-title", e.g. "1-2-user-auth"). Set storyId = "{epicNum}.{storyNum}", storyKey, resolved=true, gate="none".`
|
|
89
|
+
: `No story key was provided. Read the COMPLETE sprint-status.yaml (variable {implementation_artifacts}/sprint-status.yaml) from start to end, preserving order. Parse development_status fully. Find the FIRST story key (top-to-bottom) matching number-number-name, NOT an epic-X or epic-X-retrospective key, whose status equals "backlog". Extract epicNum (before first dash), storyNum (after first dash), storyTitle (remainder); set storyId="{epicNum}.{storyNum}".\n` +
|
|
90
|
+
`Then detect the HUMAN-GATE conditions and report them WITHOUT deciding:\n` +
|
|
91
|
+
` - sprint-status.yaml missing -> resolved=false, gate="no-sprint-status".\n` +
|
|
92
|
+
` - no backlog story found -> resolved=false, gate="no-backlog".\n` +
|
|
93
|
+
` - if this is the first story in the epic ({epicNum}-1-*): check epic-{epicNum} status. If "done" -> resolved=false, gate="epic-done". If not one of backlog/contexted/in-progress/done -> resolved=false, gate="invalid-epic-status". Otherwise set isFirstStoryInEpic=true (the epic should be flagged in-progress at the gate) and resolved=true.\n` +
|
|
94
|
+
` - otherwise resolved=true, gate="none".`) +
|
|
95
|
+
`\nDo NOT write any file in this step. Only resolve / report the target.`,
|
|
96
|
+
{ label: 'determine-target', phase: 'TARGET', schema: TARGET_SCHEMA }
|
|
97
|
+
)
|
|
98
|
+
log(`target: resolved=${target.resolved} key=${target.storyKey || '(none)'} gate=${target.gate || 'n/a'}`)
|
|
99
|
+
|
|
100
|
+
// If a human gate blocks selection, stop the autonomous run and return the
|
|
101
|
+
// gate to the orchestrating skill. The script never HALTs or asks the user.
|
|
102
|
+
if (!target.resolved) {
|
|
103
|
+
return {
|
|
104
|
+
workflow: 'create-story',
|
|
105
|
+
summary: `Target story could not be resolved autonomously — human gate: ${target.gate}.`,
|
|
106
|
+
steps: 1,
|
|
107
|
+
needsHumanGate: true,
|
|
108
|
+
gate: target.gate,
|
|
109
|
+
gateMessage: target.gateMessage || '',
|
|
110
|
+
target,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const resolvedKey = target.storyKey
|
|
115
|
+
const storyFilePath = `${storyDir}/${resolvedKey}.md`
|
|
116
|
+
|
|
117
|
+
// === STEP 2 — Load and analyze core artifacts ==============================
|
|
118
|
+
// Source: step n="2". Exhaustive (NOT lazy) analysis of epics for THIS story,
|
|
119
|
+
// previous-story intelligence (if storyNum > 1), and git history for recent
|
|
120
|
+
// work patterns. This is where future developer mistakes are prevented.
|
|
121
|
+
phase('ARTIFACTS')
|
|
122
|
+
const artifacts = await agent(
|
|
123
|
+
`create-story step 2 — EXHAUSTIVE artifact analysis for story ${JSON.stringify(resolvedKey)} (id ${target.storyId}). Do NOT skim.\n` +
|
|
124
|
+
`Run discover_inputs: load epics ({planning_artifacts}/*epic*.md), and fall back to prd / architecture / ux / project-context only as needed.\n` +
|
|
125
|
+
`EPIC ANALYSIS: from epics, extract Epic ${target.epicNum} objectives + business value, ALL stories in the epic (cross-story context), our story's user-story statement + BDD acceptance criteria + technical requirements + dependencies + source hints.\n` +
|
|
126
|
+
`STORY FOUNDATION: As-a / I-want / so-that, detailed acceptance criteria, story-specific technical requirements, success criteria.\n` +
|
|
127
|
+
`PREVIOUS STORY INTELLIGENCE: if storyNum (${target.storyNum}) > 1, load the previous story file ${storyDir}/${target.epicNum}-{previous_story_num}-*.md and extract dev notes, review feedback, files created/modified + their patterns, testing approaches that worked/failed, problems + solutions, code patterns established.\n` +
|
|
128
|
+
`GIT INTELLIGENCE: if a previous story exists AND a git repo is detected, read the last 5 commit titles; analyze recent commits for files touched, conventions, dependency changes, architecture decisions, testing approaches; extract actionable insights for this story.\n` +
|
|
129
|
+
`Return a tight, structured analysis (no fluff). Save any clarifying questions for the END (do not ask now).`,
|
|
130
|
+
{ label: 'analyze-artifacts', phase: 'ARTIFACTS' }
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
// === STEP 3 — Architecture analysis for developer guardrails ===============
|
|
134
|
+
// Source: step n="3". Pull every architecture constraint the developer MUST
|
|
135
|
+
// follow (stack/versions, structure, API, DB, security, performance, testing,
|
|
136
|
+
// deployment, integration); flag decisions that override previous patterns.
|
|
137
|
+
phase('ARCHITECTURE')
|
|
138
|
+
const architecture = await agent(
|
|
139
|
+
`create-story step 3 — ARCHITECTURE guardrails for story ${JSON.stringify(resolvedKey)}.\n` +
|
|
140
|
+
`Artifact analysis so far: ${artifacts}\n` +
|
|
141
|
+
`Load architecture: complete file if single, or the index + all shards if sharded ({planning_artifacts}/*architecture*.md or */*.md).\n` +
|
|
142
|
+
`For each section, decide relevance to THIS story and extract what the developer MUST follow: Technical Stack (languages/frameworks/libraries WITH versions); Code Structure (folders, naming, file patterns); API Patterns (service structure, endpoints, data contracts); Database Schemas (tables/relationships/constraints relevant to the story); Security Requirements (auth/authz); Performance Requirements (caching, optimization); Testing Standards (frameworks, coverage, patterns); Deployment Patterns; Integration Patterns (external services, data flows).\n` +
|
|
143
|
+
`Explicitly identify any architectural decision that OVERRIDES a previous pattern. Return a tight list of binding constraints.`,
|
|
144
|
+
{ label: 'analyze-architecture', phase: 'ARCHITECTURE' }
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
// === STEP 4 — Web research for latest technical specifics ==================
|
|
148
|
+
// Source: step n="4". For each critical library/framework, research latest
|
|
149
|
+
// stable version + breaking changes + security/perf notes + best practices,
|
|
150
|
+
// so the story never carries outdated implementation guidance.
|
|
151
|
+
phase('RESEARCH')
|
|
152
|
+
const research = await agent(
|
|
153
|
+
`create-story step 4 — LATEST-TECH web research for story ${JSON.stringify(resolvedKey)}.\n` +
|
|
154
|
+
`From the architecture guardrails: ${architecture}\n` +
|
|
155
|
+
`Identify the specific libraries / APIs / frameworks this story depends on. For each critical one, research: latest stable version + key breaking changes; security vulnerabilities/updates; performance improvements/deprecations; best practices for the current version; migration considerations if upgrading.\n` +
|
|
156
|
+
`Return ONLY the critical, story-relevant facts the developer needs (specific versions and WHY, endpoints with params/auth, recent security patches, perf techniques). If no external lookup is warranted, say so explicitly rather than padding.`,
|
|
157
|
+
{ label: 'web-research', phase: 'RESEARCH' }
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
// === STEP 5 — Create comprehensive story file ==============================
|
|
161
|
+
// Source: step n="5". Initialize from template.md and write the full story:
|
|
162
|
+
// header, requirements, the developer_context section (MOST IMPORTANT), tech
|
|
163
|
+
// requirements, architecture compliance, library/framework reqs, file-structure
|
|
164
|
+
// reqs, testing reqs, previous-story intelligence, git summary, latest tech,
|
|
165
|
+
// project-context reference, completion status; set Status: ready-for-dev.
|
|
166
|
+
phase('WRITE')
|
|
167
|
+
const written = await agent(
|
|
168
|
+
`create-story step 5 — WRITE the ULTIMATE story file at ${storyFilePath} (story ${target.storyId}, date ${date}).\n` +
|
|
169
|
+
`Initialize from the template: _byan/workflow/simple/4-implementation/create-story/template.md (keep its section order).\n` +
|
|
170
|
+
`Fill EVERY relevant section from the analyses below — this single file is ALL the dev agent will have, so make flawless implementation inevitable:\n` +
|
|
171
|
+
` story_header (epic_num/story_num/title, Status), story_requirements (As-a/I-want/so-that + Acceptance Criteria + Tasks/Subtasks with AC refs),\n` +
|
|
172
|
+
` developer_context_section (MOST IMPORTANT — anti-reinvention, exact file locations, reuse opportunities),\n` +
|
|
173
|
+
` technical_requirements, architecture_compliance, library_framework_requirements, file_structure_requirements, testing_requirements,\n` +
|
|
174
|
+
` previous_story_intelligence (only if available), git_intelligence_summary (only if git analysis ran), latest_tech_information (only if research produced facts),\n` +
|
|
175
|
+
` project_context_reference, story_completion_status.\n` +
|
|
176
|
+
`EPICS/STORY ANALYSIS:\n${artifacts}\nARCHITECTURE GUARDRAILS:\n${architecture}\nLATEST-TECH:\n${research}\n` +
|
|
177
|
+
`Cite technical details with source paths/sections, e.g. [Source: docs/<file>.md#Section]. Set Status to "ready-for-dev" and add the completion note "Ultimate context engine analysis completed - comprehensive developer guide created". Write ONLY the story file. Report the path written and the Status set.`,
|
|
178
|
+
{ label: 'write-story', phase: 'WRITE' }
|
|
179
|
+
)
|
|
180
|
+
log(`write: ${typeof written === 'string' ? written.slice(0, 120) : 'done'}`)
|
|
181
|
+
|
|
182
|
+
// === STEP 6 — Validate against checklist & finalize ========================
|
|
183
|
+
// Source: step n="6". Validate the freshly written story against checklist.md
|
|
184
|
+
// (the quality-competition reviewer) and report gaps. The unconditional save,
|
|
185
|
+
// the sprint-status.yaml update (backlog -> ready-for-dev) and the user report
|
|
186
|
+
// are the HUMAN-GATE side: the script returns a verdict; the skill applies
|
|
187
|
+
// the sprint-status mutation and surfaces the report.
|
|
188
|
+
phase('FINALIZE')
|
|
189
|
+
const finalVerdict = await agent(
|
|
190
|
+
`create-story step 6 — VALIDATE the story at ${storyFilePath} against the checklist: _byan/workflow/simple/4-implementation/create-story/checklist.md.\n` +
|
|
191
|
+
`Re-analyze the source artifacts with a critical eye (the checklist is a fresh-context quality reviewer hunting for misses the writer left). Classify findings: critical issues (must-fix blockers), enhancements (should-add), and any open questions you saved for the end.\n` +
|
|
192
|
+
`Confirm the story file was written and its Status is exactly "ready-for-dev". Set checklistVerdict="pass" only if there are NO critical issues, otherwise "gaps". Do NOT modify sprint-status.yaml here — that mutation happens at the human gate.`,
|
|
193
|
+
{ label: 'validate-checklist', phase: 'FINALIZE', schema: FINAL_SCHEMA }
|
|
194
|
+
)
|
|
195
|
+
log(`finalize: status=${finalVerdict.status} checklist=${finalVerdict.checklistVerdict}`)
|
|
196
|
+
|
|
197
|
+
// Return DATA only. The orchestrating skill presents this at the human gate,
|
|
198
|
+
// updates sprint-status.yaml (backlog -> ready-for-dev), optionally flags the
|
|
199
|
+
// epic in-progress, and records FD/strict state via MCP.
|
|
200
|
+
return {
|
|
201
|
+
workflow: 'create-story',
|
|
202
|
+
storyKey: resolvedKey,
|
|
203
|
+
storyId: target.storyId,
|
|
204
|
+
storyFilePath,
|
|
205
|
+
status: finalVerdict.status,
|
|
206
|
+
isFirstStoryInEpic: Boolean(target.isFirstStoryInEpic),
|
|
207
|
+
checklistVerdict: finalVerdict.checklistVerdict,
|
|
208
|
+
criticalIssues: finalVerdict.criticalIssues || [],
|
|
209
|
+
enhancements: finalVerdict.enhancements || [],
|
|
210
|
+
openQuestions: finalVerdict.openQuestions || [],
|
|
211
|
+
steps: 6,
|
|
212
|
+
summary: `Story ${resolvedKey} written to ${storyFilePath} as ready-for-dev (checklist: ${finalVerdict.checklistVerdict}).`,
|
|
213
|
+
needsHumanGate: true,
|
|
214
|
+
// Action the skill must apply at the gate (kept OUT of the script):
|
|
215
|
+
sprintStatusUpdate: { storyKey: resolvedKey, from: 'backlog', to: 'ready-for-dev' },
|
|
216
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'dev-story',
|
|
3
|
+
description: 'Native port of the BYAN dev-story workflow: implement a story task-by-task via a red-green-refactor loop, run to green (or hard-abort at the 3-cycle convergence cap), and return a structured verdict for the orchestrating skill to present at the human gate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'LOAD', detail: 'load the story + first incomplete task' },
|
|
6
|
+
{ title: 'RGR', detail: 'red-green-refactor loop until green or the 3-cycle cap' },
|
|
7
|
+
{ title: 'VERDICT', detail: 'return a structured verdict to the orchestrating skill' },
|
|
8
|
+
],
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// FD / STRICT STATE CONTRACT (re-asserted inline — enforcement-bridge F3).
|
|
13
|
+
//
|
|
14
|
+
// The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
|
|
15
|
+
// BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, strict-stop-
|
|
16
|
+
// guard, mantra-validate) DO NOT fire here. This script therefore:
|
|
17
|
+
// - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
|
|
18
|
+
// fd-state.json directly (enforced by byan-lint-workflows.js).
|
|
19
|
+
// - returns DATA only. The orchestrating skill (.claude/skills/
|
|
20
|
+
// byan-native-dev-story) is the human-gated conductor; IT records FD/strict
|
|
21
|
+
// state via the byan_fd_* / byan_strict_* MCP tools AT the gate.
|
|
22
|
+
// The story FILE (Status, Tasks/Subtasks, Dev Agent Record, File List, Change
|
|
23
|
+
// Log) is the workflow's product, written by the implement leaf — that is the
|
|
24
|
+
// artifact, not BYAN platform state.
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
// Convergence guard — mirror of _byan/mcp/byan-mcp-server/lib/native-loop.js.
|
|
28
|
+
// The sandbox forbids import, so the tiny guard is inlined verbatim; the lib
|
|
29
|
+
// copy is the unit-tested reference (test/native-loop.test.js). Keep in sync.
|
|
30
|
+
// This turns dev-story's prose rule ("3 consecutive failures -> HALT") into a
|
|
31
|
+
// real JS counter the model cannot silently overrun.
|
|
32
|
+
const MAX_CYCLES = 3
|
|
33
|
+
function convergenceGuard({ cycles, green, maxCycles = MAX_CYCLES }) {
|
|
34
|
+
if (green) return { done: true, abort: false, reason: 'green' }
|
|
35
|
+
if (cycles >= maxCycles) return { done: true, abort: true, reason: `no convergence after ${maxCycles} cycles` }
|
|
36
|
+
return { done: false, abort: false, reason: 'continue' }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const VERIFY_SCHEMA = {
|
|
40
|
+
type: 'object',
|
|
41
|
+
required: ['green', 'blocking'],
|
|
42
|
+
properties: {
|
|
43
|
+
green: { type: 'boolean', description: 'true ONLY if the full test suite passes and the current task acceptance criteria are met' },
|
|
44
|
+
blocking: { type: 'array', items: { type: 'string' }, description: 'blocking issues when not green' },
|
|
45
|
+
summary: { type: 'string', description: 'one-line status' },
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const story = (args && args.story) || 'next ready-for-dev story'
|
|
50
|
+
|
|
51
|
+
phase('LOAD')
|
|
52
|
+
const loaded = await agent(
|
|
53
|
+
`You are dev-story (BYAN dev agent). Target story: ${JSON.stringify(story)}.\n` +
|
|
54
|
+
`Read the COMPLETE story file. Parse Story, Acceptance Criteria, Tasks/Subtasks, Dev Notes, File List, Status. ` +
|
|
55
|
+
`Identify the FIRST incomplete task (unchecked [ ]). Report the story key and that task. ` +
|
|
56
|
+
`If no story is found or the file is inaccessible, say so explicitly (do not invent one).`,
|
|
57
|
+
{ label: 'load-story', phase: 'LOAD' }
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
phase('RGR')
|
|
61
|
+
// Red-green-refactor loop with a real convergence counter (max 3 cycles).
|
|
62
|
+
let cycles = 0
|
|
63
|
+
let last = { green: false, blocking: ['not started'] }
|
|
64
|
+
let guard = { done: false, abort: false, reason: 'init' }
|
|
65
|
+
while (true) {
|
|
66
|
+
cycles += 1
|
|
67
|
+
const impl = await agent(
|
|
68
|
+
`dev-story red-green-refactor, cycle ${cycles}, story ${JSON.stringify(story)}.\n` +
|
|
69
|
+
`Load context: ${loaded}\n` +
|
|
70
|
+
`On the first incomplete task: (RED) write FAILING tests first and confirm they fail; ` +
|
|
71
|
+
`(GREEN) implement the MINIMAL code to pass; (REFACTOR) improve structure while keeping tests green. ` +
|
|
72
|
+
`Modify ONLY the permitted story-file sections (Tasks/Subtasks checkboxes, Dev Agent Record, File List, Change Log, Status). ` +
|
|
73
|
+
`Do NOT mark a task [x] unless its tests actually pass. Then stop and report what you did.`,
|
|
74
|
+
{ label: `rgr-cycle-${cycles}`, phase: 'RGR' }
|
|
75
|
+
)
|
|
76
|
+
last = await agent(
|
|
77
|
+
`Run the project's full test suite for story ${JSON.stringify(story)} (infer the test command from the repo). ` +
|
|
78
|
+
`Cycle ${cycles}. Implementation notes: ${impl}\n` +
|
|
79
|
+
`Set green=true ONLY if all tests pass with zero regressions AND the current task's acceptance criteria are met. ` +
|
|
80
|
+
`Otherwise green=false and list the blocking issues precisely.`,
|
|
81
|
+
{ label: `verify-cycle-${cycles}`, phase: 'RGR', schema: VERIFY_SCHEMA }
|
|
82
|
+
)
|
|
83
|
+
guard = convergenceGuard({ cycles, green: Boolean(last && last.green) })
|
|
84
|
+
log(`cycle ${cycles}: green=${Boolean(last && last.green)} -> ${guard.reason}`)
|
|
85
|
+
if (guard.done) break
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
phase('VERDICT')
|
|
89
|
+
// Return DATA only. The skill presents this at the human gate and records state.
|
|
90
|
+
return {
|
|
91
|
+
workflow: 'dev-story',
|
|
92
|
+
story,
|
|
93
|
+
status: last.green ? 'review-ready' : guard.abort ? 'aborted-no-convergence' : 'in-progress',
|
|
94
|
+
green: Boolean(last.green),
|
|
95
|
+
cycles,
|
|
96
|
+
maxCycles: MAX_CYCLES,
|
|
97
|
+
blocking: (last && last.blocking) || [],
|
|
98
|
+
reason: guard.reason,
|
|
99
|
+
needsHumanGate: true,
|
|
100
|
+
}
|