@ryuenn3123/agentic-senior-core 3.0.6 → 3.0.8
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/.agent-context/prompts/bootstrap-design.md +38 -12
- package/.agent-context/prompts/init-project.md +3 -3
- package/.agent-context/prompts/refactor.md +1 -1
- package/.agent-context/prompts/review-code.md +1 -1
- package/.agent-context/review-checklists/pr-checklist.md +1 -1
- package/.agent-context/rules/architecture.md +1 -1
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.cursorrules +2 -2
- package/.gemini/instructions.md +1 -1
- package/.github/copilot-instructions.md +1 -1
- package/.windsurfrules +2 -2
- package/AGENTS.md +1 -1
- package/README.md +5 -5
- package/lib/cli/commands/init.mjs +97 -2
- package/lib/cli/commands/upgrade.mjs +98 -2
- package/lib/cli/compiler.mjs +6 -2
- package/lib/cli/detector.mjs +101 -0
- package/lib/cli/init-architecture-flow.mjs +2 -0
- package/lib/cli/project-scaffolder.mjs +240 -223
- package/package.json +1 -1
- package/scripts/validate.mjs +41 -4
|
@@ -1,22 +1,48 @@
|
|
|
1
1
|
|
|
2
|
-
# Bootstrap
|
|
2
|
+
# Bootstrap Dynamic Design Contract
|
|
3
3
|
|
|
4
|
-
When a user requests frontend design or redesign, the agent should automatically synthesize a
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- User journey and interaction flows
|
|
10
|
-
- Design tokens and handoff notes for developers
|
|
4
|
+
When a user requests frontend design or redesign, the agent should automatically synthesize a dynamic design contract made of:
|
|
5
|
+
- `docs/DESIGN.md` for human-readable design direction and implementation rationale
|
|
6
|
+
- `docs/design-intent.json` for machine-readable intent, anti-generic constraints, and validation hints
|
|
7
|
+
|
|
8
|
+
This contract is a structure and reasoning system, not a fixed visual template. It must adapt to product context, user needs, platform constraints, and current design signals.
|
|
11
9
|
|
|
12
10
|
The agent must:
|
|
13
11
|
1. Read [AGENTS.md](../../AGENTS.md) for project context and team roles.
|
|
14
12
|
2. Scan all files in [.agent-context/rules/](../rules/) for UI/UX and accessibility standards.
|
|
15
13
|
3. Reference [docs/deep-dive.md](../../docs/deep-dive.md) and [docs/faq.md](../../docs/faq.md) for architecture and product background.
|
|
16
|
-
4. If [docs/DESIGN.md](../../docs/DESIGN.md) exists, check for drift and
|
|
17
|
-
5.
|
|
14
|
+
4. If [docs/DESIGN.md](../../docs/DESIGN.md) or `docs/design-intent.json` already exists, check for drift and improve them instead of rewriting blindly.
|
|
15
|
+
5. Treat any example structure or stylistic inspiration as non-normative. Use it only to judge depth and clarity, never to copy a visual language directly.
|
|
16
|
+
6. All references to docs or rules must be clickable markdown links.
|
|
17
|
+
|
|
18
|
+
Required `docs/DESIGN.md` sections:
|
|
19
|
+
1. Design Intent and Product Personality
|
|
20
|
+
2. Audience and Use-Context Signals
|
|
21
|
+
3. Visual Direction and Distinctive Moves
|
|
22
|
+
4. Color System and Semantic Roles
|
|
23
|
+
5. Typography System and Hierarchy
|
|
24
|
+
6. Spacing, Layout Rhythm, and Density Strategy
|
|
25
|
+
7. Interaction, Motion, and Feedback Rules
|
|
26
|
+
8. Component Language and Shared Patterns
|
|
27
|
+
9. Accessibility Non-Negotiables
|
|
28
|
+
10. Responsive Strategy
|
|
29
|
+
11. Anti-Patterns to Avoid
|
|
30
|
+
12. Implementation Notes for Future UI Tasks
|
|
31
|
+
|
|
32
|
+
Required `docs/design-intent.json` fields:
|
|
33
|
+
- `mode`
|
|
34
|
+
- `status`
|
|
35
|
+
- `project`
|
|
36
|
+
- `brandAdjectives`
|
|
37
|
+
- `antiAdjectives`
|
|
38
|
+
- `visualDirection`
|
|
39
|
+
- `experiencePrinciples`
|
|
40
|
+
- `forbiddenPatterns`
|
|
41
|
+
- `requiredDesignSections`
|
|
42
|
+
- `implementation`
|
|
18
43
|
|
|
19
44
|
Output:
|
|
20
|
-
-
|
|
21
|
-
-
|
|
45
|
+
- Create or update both `docs/DESIGN.md` and `docs/design-intent.json`.
|
|
46
|
+
- Keep both files synchronized: the markdown explains the why, the JSON captures the contract in machine-readable form.
|
|
47
|
+
- Use practical, modern, accessible language grounded in the project, not generic SaaS defaults.
|
|
22
48
|
- Wait for user approval before generating Figma or code assets.
|
|
@@ -35,7 +35,7 @@ If the user specifies a framework/blueprint, the agent should:
|
|
|
35
35
|
See [docs/roadmap.md](../../docs/roadmap.md) and [docs/deep-dive.md](../../docs/deep-dive.md) for the latest stack and blueprint list.
|
|
36
36
|
|
|
37
37
|
## UI/UX Bootstrap
|
|
38
|
-
When a user requests frontend or UI/UX design, the agent should automatically execute the [bootstrap-design.md](./bootstrap-design.md) prompt to synthesize DESIGN.md.
|
|
38
|
+
When a user requests frontend or UI/UX design, the agent should automatically execute the [bootstrap-design.md](./bootstrap-design.md) prompt to synthesize a dynamic design contract (`docs/DESIGN.md` + `docs/design-intent.json`).
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
@@ -97,6 +97,6 @@ See [docs/roadmap.md](../../docs/roadmap.md) and [docs/deep-dive.md](../../docs/
|
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
100
|
-
## Bootstrap UI/UX (
|
|
100
|
+
## Bootstrap UI/UX (Dynamic Design Contract)
|
|
101
101
|
|
|
102
|
-
To start UI/UX design from scratch, use the [bootstrap-design.md](./bootstrap-design.md) prompt to synthesize `docs/DESIGN.md`.
|
|
102
|
+
To start UI/UX design from scratch, use the [bootstrap-design.md](./bootstrap-design.md) prompt to synthesize `docs/DESIGN.md` and `docs/design-intent.json`.
|
|
@@ -15,7 +15,7 @@ Before making changes:
|
|
|
15
15
|
3. Read .agent-context/rules/error-handling.md — fix error handling patterns.
|
|
16
16
|
4. Resolve active language guidance from dynamic stack signals (TypeScript in this repository).
|
|
17
17
|
5. Enforce backend universal principles: no clever hacks, no premature abstraction, readability over brevity.
|
|
18
|
-
6. Enforce Universal SOP hard gate: stop implementation if `docs/architecture-decision-record.md` is missing, and for UI scope stop if `docs/DESIGN.md` is missing.
|
|
18
|
+
6. Enforce Universal SOP hard gate: stop implementation if `docs/architecture-decision-record.md` is missing, and for UI scope stop if `docs/DESIGN.md` or `docs/design-intent.json` is missing.
|
|
19
19
|
|
|
20
20
|
For every change you make, provide a Reasoning Chain:
|
|
21
21
|
- What was wrong (rule reference)
|
|
@@ -20,7 +20,7 @@ Use these checklists:
|
|
|
20
20
|
7. Enforce cross-session consistency guardian: session handoff must include active architecture contract summary, drift detection must warn before direction changes, and direction changes require explicit user confirmation.
|
|
21
21
|
8. Enforce explain-on-demand state visibility: default responses must avoid unnecessary state-file internals, state internals are exposed only on explicit request, and diagnostic mode must explain relevant state decisions when needed.
|
|
22
22
|
9. Enforce single-source and lazy-loading policy: canonical rule source must be explicitly enforced, language-specific guidance must load lazily based on detected scope, and conflicting duplicate rule instructions must not appear during normal flow.
|
|
23
|
-
10. Enforce Universal SOP hard gate: block coding flow when required project docs are missing (`docs/architecture-decision-record.md`, and for UI scope `docs/DESIGN.md`).
|
|
23
|
+
10. Enforce Universal SOP hard gate: block coding flow when required project docs are missing (`docs/architecture-decision-record.md`, and for UI scope `docs/DESIGN.md` plus `docs/design-intent.json`).
|
|
24
24
|
|
|
25
25
|
For EVERY violation found:
|
|
26
26
|
- State the exact file and line
|
|
@@ -135,4 +135,4 @@ VERDICT: PASS / FAIL (X/Y items passed)
|
|
|
135
135
|
- [ ] Backend and frontend mindset checks are both applied when scope spans API and UI boundaries
|
|
136
136
|
- [ ] Security and testing requirements remain mandatory after static template purge
|
|
137
137
|
- [ ] Coding flow is blocked if `docs/architecture-decision-record.md` (or `docs/Architecture-Decision-Record.md`) is missing
|
|
138
|
-
- [ ] UI implementation flow is blocked if `docs/DESIGN.md` is missing
|
|
138
|
+
- [ ] UI implementation flow is blocked if `docs/DESIGN.md` or `docs/design-intent.json` is missing
|
|
@@ -21,7 +21,7 @@ The `.agent-context/rules/` directory is the default guidance source for impleme
|
|
|
21
21
|
- Security and testing are non-negotiable baseline requirements.
|
|
22
22
|
- Hard block before coding:
|
|
23
23
|
- `docs/architecture-decision-record.md` (alias: `docs/Architecture-Decision-Record.md`) must exist.
|
|
24
|
-
- For UI scope, `docs/DESIGN.md` must exist.
|
|
24
|
+
- For UI scope, `docs/DESIGN.md` and `docs/design-intent.json` must exist.
|
|
25
25
|
- If required project context docs are missing, stop implementation and bootstrap docs before writing application code.
|
|
26
26
|
|
|
27
27
|
## Rules as Guardian (Cross-Session Consistency)
|
package/.cursorrules
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
|
|
2
2
|
|
|
3
|
-
Generated by Agentic-Senior-Core CLI v3.0.
|
|
3
|
+
Generated by Agentic-Senior-Core CLI v3.0.8
|
|
4
4
|
Timestamp: 2026-04-18T00:00:00.000Z
|
|
5
5
|
Selected profile: beginner
|
|
6
6
|
Selected policy file: .agent-context/policies/llm-judge-threshold.json
|
|
@@ -46,4 +46,4 @@ Do not claim done before checklist pass.
|
|
|
46
46
|
|
|
47
47
|
## UNIVERSAL SOP HARD GATES
|
|
48
48
|
- Stop coding if docs/architecture-decision-record.md (or docs/Architecture-Decision-Record.md) is missing.
|
|
49
|
-
- For UI scope, stop coding if docs/DESIGN.md is missing.
|
|
49
|
+
- For UI scope, stop coding if docs/DESIGN.md or docs/design-intent.json is missing.
|
package/.gemini/instructions.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Adapter Mode: thin
|
|
4
4
|
Adapter Source: .instructions.md
|
|
5
|
-
Canonical Snapshot SHA256:
|
|
5
|
+
Canonical Snapshot SHA256: 08c326d79f2c0f4bd7ef106da3542ab0f78f4d02bc205d63598db34cf3f40731
|
|
6
6
|
|
|
7
7
|
Canonical policy source: [.instructions.md](../.instructions.md).
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Adapter Mode: thin
|
|
4
4
|
Adapter Source: .instructions.md
|
|
5
|
-
Canonical Snapshot SHA256:
|
|
5
|
+
Canonical Snapshot SHA256: 08c326d79f2c0f4bd7ef106da3542ab0f78f4d02bc205d63598db34cf3f40731
|
|
6
6
|
|
|
7
7
|
The canonical policy source for this repository is [.instructions.md](../.instructions.md).
|
|
8
8
|
|
package/.windsurfrules
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET
|
|
2
2
|
|
|
3
|
-
Generated by Agentic-Senior-Core CLI v3.0.
|
|
3
|
+
Generated by Agentic-Senior-Core CLI v3.0.8
|
|
4
4
|
Timestamp: 2026-04-18T00:00:00.000Z
|
|
5
5
|
Selected profile: beginner
|
|
6
6
|
Selected policy file: .agent-context/policies/llm-judge-threshold.json
|
|
@@ -46,4 +46,4 @@ Do not claim done before checklist pass.
|
|
|
46
46
|
|
|
47
47
|
## UNIVERSAL SOP HARD GATES
|
|
48
48
|
- Stop coding if docs/architecture-decision-record.md (or docs/Architecture-Decision-Record.md) is missing.
|
|
49
|
-
- For UI scope, stop coding if docs/DESIGN.md is missing.
|
|
49
|
+
- For UI scope, stop coding if docs/DESIGN.md or docs/design-intent.json is missing.
|
package/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Adapter Mode: thin
|
|
4
4
|
Adapter Source: .instructions.md
|
|
5
|
-
Canonical Snapshot SHA256:
|
|
5
|
+
Canonical Snapshot SHA256: 08c326d79f2c0f4bd7ef106da3542ab0f78f4d02bc205d63598db34cf3f40731
|
|
6
6
|
|
|
7
7
|
This file is an adapter entrypoint for agent discovery.
|
|
8
8
|
The canonical policy source is [.instructions.md](.instructions.md).
|
package/README.md
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
**Production-grade Rules Engine (Governance Engine) for AI coding agents.**
|
|
11
11
|
Works with Cursor, Windsurf, GitHub Copilot, Claude Code, Gemini, and other LLM-powered IDE workflows.
|
|
12
12
|
|
|
13
|
-
Latest release: 3.0.
|
|
13
|
+
Latest release: 3.0.8 (2026-04-20).
|
|
14
14
|
|
|
15
|
-
Highlights in 3.0.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
15
|
+
Highlights in 3.0.8:
|
|
16
|
+
- Existing UI repositories now get `docs/design-intent.json` seeded during both `init` and `upgrade`.
|
|
17
|
+
- Upgrade preview explicitly shows when a machine-readable design seed will be created on apply.
|
|
18
|
+
- UI scope detection is now shared between `init` and `upgrade` so design-contract enforcement stays consistent.
|
|
19
19
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createInterface } from 'node:readline/promises';
|
|
6
6
|
import { stdin, stdout } from 'node:process';
|
|
7
|
+
import fs from 'node:fs/promises';
|
|
7
8
|
import path from 'node:path';
|
|
8
9
|
|
|
9
10
|
import {
|
|
@@ -29,10 +30,16 @@ import {
|
|
|
29
30
|
formatBlockingSeverities,
|
|
30
31
|
formatDuration,
|
|
31
32
|
copyGovernanceAssetsToTarget,
|
|
33
|
+
pathExists,
|
|
32
34
|
} from '../utils.mjs';
|
|
33
35
|
|
|
34
36
|
import { collectProfilePacks, findProfilePackByInput } from '../profile-packs.mjs';
|
|
35
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
detectProjectContext,
|
|
39
|
+
buildDetectionSummary,
|
|
40
|
+
formatDetectionCandidates,
|
|
41
|
+
detectUiScopeSignals,
|
|
42
|
+
} from '../detector.mjs';
|
|
36
43
|
import { compileDynamicContext, writeSelectedPolicy, writeOnboardingReport } from '../compiler.mjs';
|
|
37
44
|
import {
|
|
38
45
|
filterBlueprintFileNamesByCandidates,
|
|
@@ -55,6 +62,7 @@ import {
|
|
|
55
62
|
hasExistingProjectDocs,
|
|
56
63
|
loadProjectConfig,
|
|
57
64
|
normalizeDocsLanguage,
|
|
65
|
+
buildDesignIntentSeedFromSignals,
|
|
58
66
|
} from '../project-scaffolder.mjs';
|
|
59
67
|
import { performRollback } from '../rollback.mjs';
|
|
60
68
|
import {
|
|
@@ -162,6 +170,41 @@ async function askBlueprintSelection(promptMessage, selectableBlueprintFileNames
|
|
|
162
170
|
return selectableBlueprintFileNames[selectedIndex] || selectableBlueprintFileNames[0] || null;
|
|
163
171
|
}
|
|
164
172
|
|
|
173
|
+
function buildInitExistingProjectDesignIntentSeed({
|
|
174
|
+
targetDirectoryPath,
|
|
175
|
+
packageManifest,
|
|
176
|
+
selectedStackFileName,
|
|
177
|
+
selectedBlueprintFileName,
|
|
178
|
+
uiScopeSignals,
|
|
179
|
+
architectureProjectDescription,
|
|
180
|
+
}) {
|
|
181
|
+
const projectName = String(packageManifest?.name || path.basename(targetDirectoryPath)).trim() || 'existing-ui-project';
|
|
182
|
+
const isMobileUiProject = String(selectedStackFileName || '').toLowerCase().includes('react-native')
|
|
183
|
+
|| String(selectedStackFileName || '').toLowerCase().includes('flutter')
|
|
184
|
+
|| uiScopeSignals.signalReasons.some((signalReason) => signalReason.includes('android') || signalReason.includes('ios'));
|
|
185
|
+
const resolvedDomain = isMobileUiProject ? 'Mobile app' : 'Web application';
|
|
186
|
+
const projectDescription = String(packageManifest?.description || architectureProjectDescription || '').trim()
|
|
187
|
+
|| `Existing ${resolvedDomain.toLowerCase()} detected during init. Create a project-specific dynamic design contract before shipping new UI work.`;
|
|
188
|
+
|
|
189
|
+
return buildDesignIntentSeedFromSignals({
|
|
190
|
+
projectName,
|
|
191
|
+
projectDescription,
|
|
192
|
+
primaryDomain: resolvedDomain,
|
|
193
|
+
features: [],
|
|
194
|
+
initContext: {
|
|
195
|
+
stackFileName: selectedStackFileName,
|
|
196
|
+
blueprintFileName: selectedBlueprintFileName,
|
|
197
|
+
},
|
|
198
|
+
status: 'seed-generated-during-init',
|
|
199
|
+
supplementalFields: {
|
|
200
|
+
initSignals: {
|
|
201
|
+
detectedFrom: uiScopeSignals.signalReasons,
|
|
202
|
+
generatedBy: 'init-existing-project-seed',
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
165
208
|
export async function runInitCommand(targetDirectoryArgument, initOptions = {}) {
|
|
166
209
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
167
210
|
const isTokenOptimizationEnabled = typeof initOptions.tokenOptimize === 'boolean'
|
|
@@ -399,6 +442,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
399
442
|
)?.label || 'Both (frontend + backend)';
|
|
400
443
|
|
|
401
444
|
let architectureRecommendation = null;
|
|
445
|
+
let architectureProjectDescription = '';
|
|
402
446
|
let architectPreferenceState = await readArchitectPreferenceState();
|
|
403
447
|
let architectPreferenceUpdated = false;
|
|
404
448
|
|
|
@@ -457,6 +501,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
457
501
|
selectedProjectScopeLabel = architectureSelection.selectedProjectScopeLabel;
|
|
458
502
|
selectedManualStackFileName = architectureSelection.selectedManualStackFileName;
|
|
459
503
|
selectedManualBlueprintFileName = architectureSelection.selectedManualBlueprintFileName;
|
|
504
|
+
architectureProjectDescription = architectureSelection.architectureProjectDescription;
|
|
460
505
|
architectureRecommendation = architectureSelection.architectureRecommendation;
|
|
461
506
|
architectPreferenceState = architectureSelection.architectPreferenceState;
|
|
462
507
|
architectPreferenceUpdated = architectureSelection.architectPreferenceUpdated;
|
|
@@ -578,6 +623,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
578
623
|
|
|
579
624
|
// --- Project Documentation Scaffolding ---
|
|
580
625
|
let scaffoldingResult = null;
|
|
626
|
+
const supplementalMaterializedDocFileNames = [];
|
|
581
627
|
const isFreshProjectTarget = wasDirectoryEffectivelyEmpty && !hadExistingProjectDocsBeforeInit;
|
|
582
628
|
const shouldOfferScaffolding = initOptions.scaffoldDocs === true
|
|
583
629
|
|| Boolean(initOptions.projectConfig)
|
|
@@ -607,6 +653,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
607
653
|
} else {
|
|
608
654
|
discoveryAnswers = await runProjectDiscovery(userInterface, {
|
|
609
655
|
defaultProjectName: path.basename(resolvedTargetDirectoryPath),
|
|
656
|
+
defaultProjectDescription: architectureProjectDescription,
|
|
610
657
|
});
|
|
611
658
|
}
|
|
612
659
|
|
|
@@ -645,6 +692,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
645
692
|
for (const generatedPromptFileName of scaffoldingResult.generatedPromptFileNames || []) {
|
|
646
693
|
console.log(` - .agent-context/prompts/${generatedPromptFileName}`);
|
|
647
694
|
}
|
|
695
|
+
for (const materializedFileName of scaffoldingResult.materializedFileNames || []) {
|
|
696
|
+
console.log(` - docs/${materializedFileName}`);
|
|
697
|
+
}
|
|
648
698
|
console.log('Project docs will be authored dynamically by your IDE assistant from these prompts.');
|
|
649
699
|
} else {
|
|
650
700
|
console.log(`\nProject documentation generated in docs/:`);
|
|
@@ -655,6 +705,36 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
655
705
|
}
|
|
656
706
|
}
|
|
657
707
|
|
|
708
|
+
const existingProjectUiScopeSignals = projectDetection.hasExistingProjectFiles
|
|
709
|
+
? await detectUiScopeSignals({
|
|
710
|
+
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
711
|
+
selectedStackFileName: selectedResolvedStackFileName,
|
|
712
|
+
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
713
|
+
})
|
|
714
|
+
: null;
|
|
715
|
+
const designIntentTargetPath = path.join(resolvedTargetDirectoryPath, 'docs', 'design-intent.json');
|
|
716
|
+
const shouldSeedExistingUiDesignIntent = projectDetection.hasExistingProjectFiles
|
|
717
|
+
&& existingProjectUiScopeSignals?.isUiScopeLikely === true
|
|
718
|
+
&& !(await pathExists(designIntentTargetPath));
|
|
719
|
+
|
|
720
|
+
if (shouldSeedExistingUiDesignIntent) {
|
|
721
|
+
const docsDirectoryPath = path.join(resolvedTargetDirectoryPath, 'docs');
|
|
722
|
+
const designIntentSeedContent = buildInitExistingProjectDesignIntentSeed({
|
|
723
|
+
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
724
|
+
packageManifest: existingProjectUiScopeSignals.packageManifest,
|
|
725
|
+
selectedStackFileName: selectedResolvedStackFileName,
|
|
726
|
+
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
727
|
+
uiScopeSignals: existingProjectUiScopeSignals,
|
|
728
|
+
architectureProjectDescription,
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
await ensureDirectory(docsDirectoryPath);
|
|
732
|
+
await fs.writeFile(designIntentTargetPath, designIntentSeedContent, 'utf8');
|
|
733
|
+
supplementalMaterializedDocFileNames.push('design-intent.json');
|
|
734
|
+
|
|
735
|
+
console.log('\nExisting UI/frontend scope detected. Seeded docs/design-intent.json so the machine-readable design contract exists before UI implementation work continues.');
|
|
736
|
+
}
|
|
737
|
+
|
|
658
738
|
await compileDynamicContext({
|
|
659
739
|
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
660
740
|
selectedProfileName,
|
|
@@ -674,6 +754,10 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
674
754
|
selectedProfileName,
|
|
675
755
|
selectedProfilePack,
|
|
676
756
|
selectedPreset: initOptions.preset || null,
|
|
757
|
+
projectScope: {
|
|
758
|
+
key: selectedProjectScopeKey,
|
|
759
|
+
label: selectedProjectScopeLabel,
|
|
760
|
+
},
|
|
677
761
|
selectedStackFileName: selectedResolvedStackFileName,
|
|
678
762
|
selectedAdditionalStackFileNames,
|
|
679
763
|
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
@@ -746,12 +830,18 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
746
830
|
console.log('- Generated files: .agent-instructions.md, .cursorrules, .windsurfrules, .clauderc, and .agent-context/state/onboarding-report.json');
|
|
747
831
|
if (scaffoldingResult?.bootstrapMode === 'ai-synthesis') {
|
|
748
832
|
console.log(`- Bootstrap prompts: ${(scaffoldingResult.generatedPromptFileNames || []).length} files generated in .agent-context/prompts/`);
|
|
833
|
+
if ((scaffoldingResult.materializedFileNames || []).length > 0) {
|
|
834
|
+
console.log(`- Seed docs: ${(scaffoldingResult.materializedFileNames || []).length} files generated in docs/`);
|
|
835
|
+
}
|
|
749
836
|
console.log(`- Bootstrap docs language: ${scaffoldingResult.docsLanguage}`);
|
|
750
837
|
console.log(`- Expected project docs after synthesis: ${scaffoldingResult.generatedFileNames.length} files in docs/`);
|
|
751
838
|
} else if (scaffoldingResult) {
|
|
752
839
|
console.log(`- Project docs: ${scaffoldingResult.generatedFileNames.length} files generated in docs/`);
|
|
753
840
|
console.log(`- Project docs language: ${scaffoldingResult.docsLanguage}`);
|
|
754
841
|
}
|
|
842
|
+
if (supplementalMaterializedDocFileNames.length > 0) {
|
|
843
|
+
console.log(`- Design seed docs: ${supplementalMaterializedDocFileNames.length} files generated in docs/`);
|
|
844
|
+
}
|
|
755
845
|
console.log(`- Repository workflows copied: no (workflows remain source-repo assets)`);
|
|
756
846
|
console.log(`- MCP configuration: ${shouldIncludeMcpTemplate ? 'auto-configured for your IDEs (VS Code, Cursor, Zed, Gemini)' : 'disabled (--no-mcp-template)'}`);
|
|
757
847
|
if (isMemoryContinuityEnabled) {
|
|
@@ -779,7 +869,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
779
869
|
console.log('\nPrompt starter examples (copy and adapt in your IDE):');
|
|
780
870
|
console.log('- If docs/project-brief.md is missing, execute .agent-context/prompts/bootstrap-project-context.md now and create all required docs files.');
|
|
781
871
|
if ((scaffoldingResult.generatedPromptFileNames || []).includes('bootstrap-design.md')) {
|
|
782
|
-
console.log('- If docs/DESIGN.md is missing, execute .agent-context/prompts/bootstrap-design.md now before building UI components.');
|
|
872
|
+
console.log('- If docs/DESIGN.md or docs/design-intent.json is missing, execute .agent-context/prompts/bootstrap-design.md now before building UI components.');
|
|
783
873
|
}
|
|
784
874
|
console.log(`- Build an MVP for ${promptProjectName} using the newly synthesized docs as strict project context.`);
|
|
785
875
|
console.log('- When scope changes, update docs/* in the same change so future prompts stay aligned.');
|
|
@@ -791,6 +881,11 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
791
881
|
console.log(`- Build an MVP for ${promptProjectName}. Follow Layer 9 docs and keep the current stack, database, and auth constraints.`);
|
|
792
882
|
console.log('- Add [new feature] and update docs/project-brief.md plus docs/flow-overview.md in the same change.');
|
|
793
883
|
console.log('- If this change needs architecture migration, propose a migration plan first, then implement after approval.');
|
|
884
|
+
} else if (supplementalMaterializedDocFileNames.includes('design-intent.json')) {
|
|
885
|
+
console.log('I also seeded docs/design-intent.json for this existing UI repository so future UI work starts from a machine-readable design contract without forcing a canned visual concept.');
|
|
886
|
+
console.log('\nPrompt starter examples (copy and adapt in your IDE):');
|
|
887
|
+
console.log('- If docs/DESIGN.md is missing, execute .agent-context/prompts/bootstrap-design.md now and refine docs/design-intent.json into a complete design contract before building UI components.');
|
|
888
|
+
console.log('- Keep docs/design-intent.json and docs/DESIGN.md synchronized whenever the UI direction changes.');
|
|
794
889
|
}
|
|
795
890
|
console.log('Your AI tools will now receive one compiled rulebook plus the original source rules, and your review threshold is stored in .agent-context/policies/llm-judge-threshold.json.');
|
|
796
891
|
console.log('MCP server registration is manual inside your IDE settings, even when mcp.json exists.');
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
detectProjectContext,
|
|
30
30
|
buildDetectionSummary,
|
|
31
31
|
formatDetectionCandidates,
|
|
32
|
+
detectUiScopeSignals,
|
|
32
33
|
} from '../detector.mjs';
|
|
33
34
|
import {
|
|
34
35
|
buildCompiledRulesContent,
|
|
@@ -40,7 +41,10 @@ import {
|
|
|
40
41
|
import { runPreflightChecks } from '../preflight.mjs';
|
|
41
42
|
import { createBackup } from '../backup.mjs';
|
|
42
43
|
import { performRollback } from '../rollback.mjs';
|
|
43
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
detectProjectDocTemplateStaleness,
|
|
46
|
+
buildDesignIntentSeedFromSignals,
|
|
47
|
+
} from '../project-scaffolder.mjs';
|
|
44
48
|
|
|
45
49
|
export function parseUpgradeArguments(commandArguments) {
|
|
46
50
|
const parsedUpgradeOptions = {
|
|
@@ -103,6 +107,40 @@ function buildExistingProjectMajorConstraints() {
|
|
|
103
107
|
];
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
function buildUpgradeDesignIntentSeed({
|
|
111
|
+
targetDirectoryPath,
|
|
112
|
+
packageManifest,
|
|
113
|
+
selectedStackFileName,
|
|
114
|
+
selectedBlueprintFileName,
|
|
115
|
+
uiScopeSignals,
|
|
116
|
+
}) {
|
|
117
|
+
const projectName = String(packageManifest?.name || path.basename(targetDirectoryPath)).trim() || 'existing-ui-project';
|
|
118
|
+
const isMobileUiProject = String(selectedStackFileName || '').toLowerCase().includes('react-native')
|
|
119
|
+
|| String(selectedStackFileName || '').toLowerCase().includes('flutter')
|
|
120
|
+
|| uiScopeSignals.signalReasons.some((signalReason) => signalReason.includes('android') || signalReason.includes('ios'));
|
|
121
|
+
const resolvedDomain = isMobileUiProject ? 'Mobile app' : 'Web application';
|
|
122
|
+
const projectDescription = String(packageManifest?.description || '').trim()
|
|
123
|
+
|| `Existing ${resolvedDomain.toLowerCase()} detected during upgrade. Create a project-specific dynamic design contract before shipping new UI work.`;
|
|
124
|
+
|
|
125
|
+
return buildDesignIntentSeedFromSignals({
|
|
126
|
+
projectName,
|
|
127
|
+
projectDescription,
|
|
128
|
+
primaryDomain: resolvedDomain,
|
|
129
|
+
features: [],
|
|
130
|
+
initContext: {
|
|
131
|
+
stackFileName: selectedStackFileName,
|
|
132
|
+
blueprintFileName: selectedBlueprintFileName,
|
|
133
|
+
},
|
|
134
|
+
status: 'seed-generated-during-upgrade',
|
|
135
|
+
supplementalFields: {
|
|
136
|
+
upgradeSignals: {
|
|
137
|
+
detectedFrom: uiScopeSignals.signalReasons,
|
|
138
|
+
generatedBy: 'upgrade-seed',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
106
144
|
export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions = {}) {
|
|
107
145
|
const resolvedTargetDirectoryPath = path.resolve(targetDirectoryArgument || '.');
|
|
108
146
|
|
|
@@ -135,7 +173,6 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
135
173
|
const blueprintFileNames = await collectFileNames(path.join(AGENT_CONTEXT_DIR, 'blueprints'));
|
|
136
174
|
const existingOnboardingReport = await loadOnboardingReportIfExists(resolvedTargetDirectoryPath);
|
|
137
175
|
const projectDetection = await detectProjectContext(resolvedTargetDirectoryPath);
|
|
138
|
-
|
|
139
176
|
const selectedProfileName = PROFILE_PRESETS[existingOnboardingReport?.selectedProfile]
|
|
140
177
|
? existingOnboardingReport.selectedProfile
|
|
141
178
|
: 'balanced';
|
|
@@ -167,6 +204,34 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
167
204
|
const includeCiGuardrails = typeof existingOnboardingReport?.ciGuardrailsEnabled === 'boolean'
|
|
168
205
|
? existingOnboardingReport.ciGuardrailsEnabled
|
|
169
206
|
: true;
|
|
207
|
+
const uiScopeSignals = await detectUiScopeSignals({
|
|
208
|
+
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
209
|
+
selectedStackFileName,
|
|
210
|
+
selectedBlueprintFileName,
|
|
211
|
+
projectScopeKey: existingOnboardingReport?.projectScope?.key || null,
|
|
212
|
+
projectScopeSourceLabel: 'onboarding project scope',
|
|
213
|
+
});
|
|
214
|
+
const packageManifest = uiScopeSignals.packageManifest;
|
|
215
|
+
const designContractPaths = ['docs/DESIGN.md', 'docs/design-intent.json'];
|
|
216
|
+
const missingDesignContractPaths = [];
|
|
217
|
+
|
|
218
|
+
for (const designContractPath of designContractPaths) {
|
|
219
|
+
const absoluteDesignContractPath = path.join(resolvedTargetDirectoryPath, ...designContractPath.split('/'));
|
|
220
|
+
if (!(await pathExists(absoluteDesignContractPath))) {
|
|
221
|
+
missingDesignContractPaths.push(designContractPath);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const shouldSeedDesignIntentOnApply = uiScopeSignals.isUiScopeLikely
|
|
225
|
+
&& missingDesignContractPaths.includes('docs/design-intent.json');
|
|
226
|
+
const designIntentSeedContent = shouldSeedDesignIntentOnApply
|
|
227
|
+
? buildUpgradeDesignIntentSeed({
|
|
228
|
+
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
229
|
+
packageManifest,
|
|
230
|
+
selectedStackFileName,
|
|
231
|
+
selectedBlueprintFileName,
|
|
232
|
+
uiScopeSignals,
|
|
233
|
+
})
|
|
234
|
+
: null;
|
|
170
235
|
|
|
171
236
|
const detectionMajorConstraints = buildExistingProjectMajorConstraints();
|
|
172
237
|
const detectionTransparency = {
|
|
@@ -288,6 +353,21 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
288
353
|
console.log('Recommendation: regenerate docs with init --scaffold-docs or update the files manually to match the latest template version.');
|
|
289
354
|
}
|
|
290
355
|
|
|
356
|
+
if (uiScopeSignals.isUiScopeLikely && missingDesignContractPaths.length > 0) {
|
|
357
|
+
console.log('\n[WARN] UI/frontend scope was detected, but the dynamic design contract is incomplete:');
|
|
358
|
+
for (const missingDesignContractPath of missingDesignContractPaths) {
|
|
359
|
+
console.log(`- Missing ${missingDesignContractPath}`);
|
|
360
|
+
}
|
|
361
|
+
if (uiScopeSignals.signalReasons.length > 0) {
|
|
362
|
+
console.log(`- Detection signals: ${uiScopeSignals.signalReasons.join('; ')}`);
|
|
363
|
+
}
|
|
364
|
+
if (shouldSeedDesignIntentOnApply) {
|
|
365
|
+
console.log('- Planned seed on apply: docs/design-intent.json');
|
|
366
|
+
}
|
|
367
|
+
console.log('Recommendation: create or refresh docs/DESIGN.md and docs/design-intent.json before allowing UI implementation work.');
|
|
368
|
+
console.log('Upgrade synchronizes governance assets and can seed docs/design-intent.json, but it does not author project-specific docs/DESIGN.md automatically.');
|
|
369
|
+
}
|
|
370
|
+
|
|
291
371
|
if (upgradeOptions.dryRun) {
|
|
292
372
|
console.log('\nDry run enabled. No files were modified.');
|
|
293
373
|
return;
|
|
@@ -310,6 +390,15 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
310
390
|
pruneManagedSurface: upgradeOptions.pruneManagedSurface === true,
|
|
311
391
|
managedSurfacePlan,
|
|
312
392
|
});
|
|
393
|
+
const supplementalCreatedFileNames = [];
|
|
394
|
+
|
|
395
|
+
if (shouldSeedDesignIntentOnApply && designIntentSeedContent) {
|
|
396
|
+
const docsDirectoryPath = path.join(resolvedTargetDirectoryPath, 'docs');
|
|
397
|
+
const designIntentTargetPath = path.join(docsDirectoryPath, 'design-intent.json');
|
|
398
|
+
await ensureDirectory(docsDirectoryPath);
|
|
399
|
+
await fs.writeFile(designIntentTargetPath, designIntentSeedContent, 'utf8');
|
|
400
|
+
supplementalCreatedFileNames.push('docs/design-intent.json');
|
|
401
|
+
}
|
|
313
402
|
|
|
314
403
|
await fs.writeFile(currentRulesPath, plannedRulesContent, 'utf8');
|
|
315
404
|
await fs.writeFile(path.join(resolvedTargetDirectoryPath, '.windsurfrules'), plannedRulesContent, 'utf8');
|
|
@@ -320,6 +409,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
320
409
|
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
321
410
|
selectedProfileName,
|
|
322
411
|
selectedProfilePack: existingOnboardingReport?.selectedProfilePack || null,
|
|
412
|
+
projectScope: existingOnboardingReport?.projectScope || null,
|
|
323
413
|
selectedStackFileName,
|
|
324
414
|
selectedAdditionalStackFileNames,
|
|
325
415
|
selectedBlueprintFileName,
|
|
@@ -346,6 +436,12 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
346
436
|
governanceSyncResult.updatedFiles.forEach((fileName) => console.log(` [UPDATED] ${fileName}`));
|
|
347
437
|
governanceSyncResult.deletedManagedFiles.forEach((fileName) => console.log(` [DELETED] ${fileName}`));
|
|
348
438
|
}
|
|
439
|
+
if (supplementalCreatedFileNames.length > 0) {
|
|
440
|
+
if (!(governanceSyncResult.updatedFiles.length > 0 || governanceSyncResult.createdFiles.length > 0 || governanceSyncResult.deletedManagedFiles.length > 0)) {
|
|
441
|
+
console.log('\nDetailed changes:');
|
|
442
|
+
}
|
|
443
|
+
supplementalCreatedFileNames.forEach((fileName) => console.log(` [NEW] ${fileName} (seed)`));
|
|
444
|
+
}
|
|
349
445
|
|
|
350
446
|
console.log('\nRefreshed files: .cursorrules, .windsurfrules, .agent-context/state/onboarding-report.json');
|
|
351
447
|
} catch (error) {
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -37,6 +37,7 @@ export async function writeOnboardingReport({
|
|
|
37
37
|
selectedProfileName,
|
|
38
38
|
selectedProfilePack,
|
|
39
39
|
selectedPreset,
|
|
40
|
+
projectScope = null,
|
|
40
41
|
selectedStackFileName,
|
|
41
42
|
selectedAdditionalStackFileNames = [],
|
|
42
43
|
selectedBlueprintFileName,
|
|
@@ -70,6 +71,7 @@ export async function writeOnboardingReport({
|
|
|
70
71
|
}
|
|
71
72
|
: null,
|
|
72
73
|
selectedPreset,
|
|
74
|
+
projectScope,
|
|
73
75
|
selectedStack: selectedStackFileName,
|
|
74
76
|
selectedAdditionalStacks: selectedAdditionalStackFileNames,
|
|
75
77
|
selectedBlueprint: selectedBlueprintFileName,
|
|
@@ -351,6 +353,8 @@ export async function buildCompiledRulesContent({
|
|
|
351
353
|
'database-schema.md',
|
|
352
354
|
'api-contract.md',
|
|
353
355
|
'flow-overview.md',
|
|
356
|
+
'DESIGN.md',
|
|
357
|
+
'design-intent.json',
|
|
354
358
|
];
|
|
355
359
|
|
|
356
360
|
for (const candidateFileName of candidateDocFileNames) {
|
|
@@ -369,7 +373,7 @@ export async function buildCompiledRulesContent({
|
|
|
369
373
|
'',
|
|
370
374
|
'Universal SOP hard block policy:',
|
|
371
375
|
'- Stop implementation if docs/architecture-decision-record.md (alias: docs/Architecture-Decision-Record.md) is missing.',
|
|
372
|
-
'- For UI scope, stop implementation if docs/DESIGN.md is missing.',
|
|
376
|
+
'- For UI scope, stop implementation if docs/DESIGN.md or docs/design-intent.json is missing.',
|
|
373
377
|
'- Materialize missing docs first, then continue coding.',
|
|
374
378
|
'',
|
|
375
379
|
'These docs were generated during project initialization and reflect the architecture,',
|
|
@@ -402,7 +406,7 @@ export async function buildCompiledRulesContent({
|
|
|
402
406
|
'- Hard block: do not write application code until docs/project-brief.md and docs/architecture-decision-record.md exist.',
|
|
403
407
|
'- If docs/project-brief.md is missing, execute bootstrap-project-context prompt immediately.',
|
|
404
408
|
hasBootstrapDesignPrompt
|
|
405
|
-
? '- For UI scope: if docs/DESIGN.md is missing, execute bootstrap-design prompt before implementing UI surfaces.'
|
|
409
|
+
? '- For UI scope: if docs/DESIGN.md or docs/design-intent.json is missing, execute bootstrap-design prompt before implementing UI surfaces.'
|
|
406
410
|
: '- For UI scope: add a design bootstrap prompt before implementing UI surfaces.',
|
|
407
411
|
'- Save generated docs under docs/ and keep them updated when feature scope changes.',
|
|
408
412
|
'Latest user prompt defines current feature scope and product direction.',
|