@ryuenn3123/agentic-senior-core 4.3.2 → 4.3.5
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 +56 -222
- package/.agent-context/rules/api-docs.md +17 -126
- package/.agent-context/rules/api-versioning.md +9 -86
- package/.agent-context/rules/architecture.md +18 -136
- package/.agent-context/rules/background-jobs.md +9 -85
- package/.agent-context/rules/config-and-flags.md +8 -71
- package/.agent-context/rules/database-design.md +9 -65
- package/.agent-context/rules/docker-runtime.md +9 -62
- package/.agent-context/rules/efficiency-vs-hype.md +7 -37
- package/.agent-context/rules/error-handling.md +8 -33
- package/.agent-context/rules/event-driven.md +8 -34
- package/.agent-context/rules/frontend-architecture.md +22 -140
- package/.agent-context/rules/git-workflow.md +8 -77
- package/.agent-context/rules/microservices.md +8 -36
- package/.agent-context/rules/migrations.md +8 -76
- package/.agent-context/rules/observability.md +7 -60
- package/.agent-context/rules/performance.md +8 -28
- package/.agent-context/rules/realtime.md +7 -22
- package/.agent-context/rules/resilience.md +9 -69
- package/.agent-context/rules/security.md +9 -64
- package/.agent-context/rules/testing.md +8 -34
- package/AGENTS.md +11 -18
- package/README.md +1 -1
- package/lib/cli/adaptive-context/catalog.mjs +1 -6
- package/lib/cli/commands/audit-design-anti-repeat.mjs +26 -185
- package/lib/cli/commands/init/project-context.mjs +0 -41
- package/lib/cli/commands/init.mjs +12 -41
- package/lib/cli/commands/upgrade.mjs +12 -35
- package/lib/cli/compiler.mjs +5 -81
- package/lib/cli/preflight.mjs +0 -21
- package/lib/cli/project-scaffolder/constants.mjs +1 -1
- package/lib/cli/project-scaffolder/design-contract.mjs +3 -45
- package/lib/cli/project-scaffolder/prompt-builders.mjs +18 -161
- package/lib/cli/project-scaffolder/storage.mjs +0 -9
- package/lib/cli/project-scaffolder.mjs +0 -1
- package/package.json +1 -1
- package/scripts/frontend-usability-audit.mjs +4 -45
- package/scripts/release-gate/constants.mjs +1 -0
- package/scripts/release-gate/static-checks.mjs +0 -36
- package/scripts/validate/config.mjs +20 -144
- package/scripts/validate/coverage-checks.mjs +2 -12
- package/scripts/validate/file-structure.mjs +165 -0
- package/scripts/validate/markdown-content.mjs +109 -0
- package/scripts/validate/project-metadata.mjs +166 -0
- package/scripts/validate.mjs +42 -435
- package/.agent-context/prompts/research-design.md +0 -160
- package/lib/cli/commands/upgrade/design-intent-seed.mjs +0 -46
- package/lib/cli/project-scaffolder/design-contract/research-dossier-migration.mjs +0 -190
|
@@ -3,196 +3,37 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* `agentic-senior-core audit:design-anti-repeat`
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Skip behavior is friendly: missing design-intent.json or missing ledger
|
|
12
|
-
* print actionable next steps and exit 0. Typography violations and palette
|
|
13
|
-
* findings (when palette is blocking, which is the default) exit 1.
|
|
6
|
+
* [DEPRECATED in 2026 Context Ops Paradigm]
|
|
7
|
+
* This script is retired because the anti-repeat ledger is now maintained
|
|
8
|
+
* as plain-text inside docs/DESIGN.md. The Adaptive Context AI agent enforces
|
|
9
|
+
* this naturally without needing regex-based JSON compliance theater.
|
|
14
10
|
*/
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
' agentic-senior-core audit:design-anti-repeat --json',
|
|
33
|
-
' agentic-senior-core audit:design-anti-repeat --palette-advisory',
|
|
34
|
-
' agentic-senior-core audit:design-anti-repeat --threshold 0.05',
|
|
35
|
-
'',
|
|
36
|
-
'Defaults:',
|
|
37
|
-
' Target directory: current working directory',
|
|
38
|
-
' Typography matches: blocking (BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION)',
|
|
39
|
-
' Palette matches: blocking (BOUNDARY_PALETTE_LEDGER_VIOLATION)',
|
|
40
|
-
' OKLCH distance: 0.04 in L*C*H space',
|
|
41
|
-
'',
|
|
42
|
-
'Options:',
|
|
43
|
-
' --json Print the full report as JSON only (no human summary).',
|
|
44
|
-
' --palette-advisory Opt out of blocking palette severity. Findings still',
|
|
45
|
-
' print but do not fail the run. Typography stays blocking.',
|
|
46
|
-
' --threshold <num> Override the OKLCH perceptual distance threshold.',
|
|
47
|
-
' Higher values are more permissive.',
|
|
48
|
-
' --help Show this help.',
|
|
49
|
-
'',
|
|
50
|
-
'Skip behavior (exit 0):',
|
|
51
|
-
' - docs/design-intent.json absent. Run `npx @ryuenn3123/agentic-senior-core init`',
|
|
52
|
-
' in a fresh project, or `... upgrade` in an existing project to seed the',
|
|
53
|
-
' design contract.',
|
|
54
|
-
' - docs/design-intent.json present but researchDossier metadata absent.',
|
|
55
|
-
" Run `... upgrade` to migrate the contract, then run `.agent-context/prompts/research-design.md`",
|
|
56
|
-
' so the dossier and anti-repeat ledger get populated before the next UI work.',
|
|
57
|
-
'',
|
|
58
|
-
'Exit codes:',
|
|
59
|
-
' 0 = no blocking violations (or audit skipped with a friendly note).',
|
|
60
|
-
' 1 = at least one BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION or, in default mode,',
|
|
61
|
-
' BOUNDARY_PALETTE_LEDGER_VIOLATION.',
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
function buildHelpText() {
|
|
65
|
-
return HELP_TEXT_LINES.join('\n');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function readNumericFlag(commandLineArgs, flagName) {
|
|
69
|
-
const flagIndex = commandLineArgs.indexOf(flagName);
|
|
70
|
-
if (flagIndex === -1) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
const flagValue = commandLineArgs[flagIndex + 1];
|
|
74
|
-
if (typeof flagValue !== 'string' || flagValue.length === 0) {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
const numericValue = Number(flagValue);
|
|
78
|
-
return Number.isFinite(numericValue) ? numericValue : null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const VALUE_FLAGS = new Set(['--threshold']);
|
|
82
|
-
|
|
83
|
-
function extractTargetDirectoryArgument(commandLineArgs) {
|
|
84
|
-
for (let argumentIndex = 0; argumentIndex < commandLineArgs.length; argumentIndex += 1) {
|
|
85
|
-
const candidateArgument = commandLineArgs[argumentIndex];
|
|
86
|
-
if (VALUE_FLAGS.has(candidateArgument)) {
|
|
87
|
-
argumentIndex += 1;
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (!candidateArgument.startsWith('--')) {
|
|
91
|
-
return candidateArgument;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function buildSkipMessage(reason) {
|
|
98
|
-
if (reason === 'design-intent-file-absent') {
|
|
99
|
-
return [
|
|
100
|
-
'Audit skipped: docs/design-intent.json is missing.',
|
|
101
|
-
'Next step:',
|
|
102
|
-
' - Fresh project: run `npx @ryuenn3123/agentic-senior-core init` to seed the design contract.',
|
|
103
|
-
' - Existing project: run `npx @ryuenn3123/agentic-senior-core upgrade` to seed it without touching app code.',
|
|
104
|
-
'Then re-run this audit.',
|
|
105
|
-
];
|
|
106
|
-
}
|
|
107
|
-
if (reason === 'anti-repeat-ledger-absent') {
|
|
108
|
-
return [
|
|
109
|
-
'Audit skipped: docs/design-intent.json is present but researchDossier metadata is absent.',
|
|
110
|
-
'Next step:',
|
|
111
|
-
' - Run `npx @ryuenn3123/agentic-senior-core upgrade` to migrate the contract; the upgrade injects',
|
|
112
|
-
' `researchDossier.metadata` and seeds the anti-repeat ledger from existing anchor, palette,',
|
|
113
|
-
' motion, and typography fields without overwriting them.',
|
|
114
|
-
" - Then run the design-research dossier prompt at `.agent-context/prompts/research-design.md`",
|
|
115
|
-
' so the ledger and `researchVerifiedAt` get populated before the next UI work.',
|
|
116
|
-
'After that, re-run this audit to enforce the ledger against your CSS.',
|
|
117
|
-
];
|
|
118
|
-
}
|
|
119
|
-
if (typeof reason === 'string' && reason.startsWith('design-intent-file-not-valid-json')) {
|
|
120
|
-
return [
|
|
121
|
-
'Audit skipped: docs/design-intent.json is present but cannot be parsed as JSON.',
|
|
122
|
-
` ${reason}`,
|
|
123
|
-
'Next step: fix the JSON syntax, then re-run this audit.',
|
|
124
|
-
];
|
|
12
|
+
export async function runDesignAntiRepeatAuditCommand(commandLineArgs = []) {
|
|
13
|
+
if (commandLineArgs.includes('--json')) {
|
|
14
|
+
process.stdout.write(JSON.stringify({
|
|
15
|
+
passed: true,
|
|
16
|
+
skipped: true,
|
|
17
|
+
reason: 'audit-design-anti-repeat is deprecated in Context Ops 2026. Plain text ledgers in DESIGN.md are handled by the agent contextually.',
|
|
18
|
+
targetDirectoryPath: process.cwd(),
|
|
19
|
+
filesScanned: 0,
|
|
20
|
+
typographyViolationCount: 0,
|
|
21
|
+
paletteFindingCount: 0,
|
|
22
|
+
paletteSeverity: 'advisory',
|
|
23
|
+
oklchDistanceThreshold: 0.04,
|
|
24
|
+
typographyViolations: [],
|
|
25
|
+
paletteFindings: []
|
|
26
|
+
}, null, 2) + '\n');
|
|
27
|
+
return 0;
|
|
125
28
|
}
|
|
126
|
-
return [`Audit skipped: ${reason || 'unknown reason'}`];
|
|
127
|
-
}
|
|
128
29
|
|
|
129
|
-
function printHumanReport(auditReport) {
|
|
130
30
|
console.log('===============================================');
|
|
131
|
-
console.log(' audit:design-anti-repeat');
|
|
31
|
+
console.log(' audit:design-anti-repeat (DEPRECATED)');
|
|
132
32
|
console.log('===============================================');
|
|
133
|
-
console.log(
|
|
134
|
-
console.log(
|
|
135
|
-
console.log(
|
|
136
|
-
console.log(` Palette findings: ${auditReport.paletteFindingCount} (${auditReport.paletteSeverity})`);
|
|
137
|
-
console.log(` OKLCH distance threshold: ${auditReport.oklchDistanceThreshold}`);
|
|
33
|
+
console.log(' Audit skipped: audit-design-anti-repeat is retired in Context Ops 2026.');
|
|
34
|
+
console.log(' Plain text ledgers in docs/DESIGN.md are handled by the agent contextually.');
|
|
35
|
+
console.log(' You can safely remove this check from your CI pipeline.');
|
|
138
36
|
console.log('');
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
for (const skipLine of buildSkipMessage(auditReport.reason)) {
|
|
142
|
-
console.log(` ${skipLine}`);
|
|
143
|
-
}
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (auditReport.typographyViolations.length > 0) {
|
|
148
|
-
console.log(' Typography violations (blocking):');
|
|
149
|
-
for (const violation of auditReport.typographyViolations) {
|
|
150
|
-
console.log(` [${violation.kind}] ${violation.file}:${violation.line} ${violation.detail}`);
|
|
151
|
-
}
|
|
152
|
-
console.log('');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (auditReport.paletteFindings.length > 0) {
|
|
156
|
-
console.log(` Palette findings (${auditReport.paletteSeverity}):`);
|
|
157
|
-
for (const finding of auditReport.paletteFindings) {
|
|
158
|
-
console.log(` [${finding.kind}] ${finding.file}:${finding.line} ${finding.detail}`);
|
|
159
|
-
}
|
|
160
|
-
console.log('');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (auditReport.passed) {
|
|
164
|
-
console.log(' No blocking violations against the anti-repeat ledger.');
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const blockingPaletteCount = auditReport.paletteSeverity === 'blocking' ? auditReport.paletteFindingCount : 0;
|
|
169
|
-
console.log(` ${auditReport.typographyViolationCount} typography violation(s) and ${blockingPaletteCount} palette violation(s) found; release blocked.`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export async function runDesignAntiRepeatAuditCommand(commandLineArgs = []) {
|
|
173
|
-
if (commandLineArgs.includes('--help') || commandLineArgs.includes('-h')) {
|
|
174
|
-
console.log(buildHelpText());
|
|
175
|
-
return 0;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const shouldOutputJsonOnly = commandLineArgs.includes('--json');
|
|
179
|
-
const shouldTreatPaletteAsAdvisory = commandLineArgs.includes('--palette-advisory');
|
|
180
|
-
const oklchDistanceThreshold = readNumericFlag(commandLineArgs, '--threshold');
|
|
181
|
-
const targetDirectoryArgument = extractTargetDirectoryArgument(commandLineArgs);
|
|
182
|
-
const targetDirectoryPath = resolve(targetDirectoryArgument || process.cwd());
|
|
183
|
-
|
|
184
|
-
const auditReport = runTypographyPaletteAntiRepeatAudit({
|
|
185
|
-
repositoryRootPath: targetDirectoryPath,
|
|
186
|
-
treatPaletteAsAdvisory: shouldTreatPaletteAsAdvisory,
|
|
187
|
-
...(typeof oklchDistanceThreshold === 'number' ? { oklchDistanceThreshold } : {}),
|
|
188
|
-
});
|
|
189
|
-
const auditReportWithRoot = { ...auditReport, targetDirectoryPath };
|
|
190
|
-
|
|
191
|
-
if (shouldOutputJsonOnly) {
|
|
192
|
-
process.stdout.write(`${JSON.stringify(auditReportWithRoot, null, 2)}\n`);
|
|
193
|
-
return auditReportWithRoot.passed ? 0 : 1;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
printHumanReport(auditReportWithRoot);
|
|
197
|
-
return auditReportWithRoot.passed ? 0 : 1;
|
|
37
|
+
|
|
38
|
+
return 0;
|
|
198
39
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import { buildDesignIntentSeedFromSignals } from '../../project-scaffolder.mjs';
|
|
5
4
|
|
|
6
5
|
function normalizeContextLine(rawText) {
|
|
7
6
|
return String(rawText || '')
|
|
@@ -59,43 +58,3 @@ export async function inferExistingProjectDescriptionHint(targetDirectoryPath) {
|
|
|
59
58
|
return evidence.slice(0, 3).join(' | ');
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
export function buildInitExistingProjectDesignIntentSeed({
|
|
63
|
-
targetDirectoryPath,
|
|
64
|
-
packageManifest,
|
|
65
|
-
selectedStackFileName,
|
|
66
|
-
selectedBlueprintFileName,
|
|
67
|
-
uiScopeSignals,
|
|
68
|
-
projectDescriptionHint,
|
|
69
|
-
}) {
|
|
70
|
-
const projectName = String(packageManifest?.name || path.basename(targetDirectoryPath)).trim() || 'existing-ui-project';
|
|
71
|
-
const isMobileUiProject = String(selectedStackFileName || '').toLowerCase().includes('react-native')
|
|
72
|
-
|| String(selectedStackFileName || '').toLowerCase().includes('flutter')
|
|
73
|
-
|| uiScopeSignals.signalReasons.some((signalReason) => signalReason.includes('android') || signalReason.includes('ios'));
|
|
74
|
-
const resolvedDomain = isMobileUiProject ? 'Mobile app' : 'Web application';
|
|
75
|
-
const projectDescription = String(packageManifest?.description || projectDescriptionHint || '').trim()
|
|
76
|
-
|| `Existing ${resolvedDomain.toLowerCase()} detected during init. Create a project-specific dynamic design contract before shipping new UI work.`;
|
|
77
|
-
|
|
78
|
-
return buildDesignIntentSeedFromSignals({
|
|
79
|
-
projectName,
|
|
80
|
-
projectDescription,
|
|
81
|
-
primaryDomain: resolvedDomain,
|
|
82
|
-
features: [],
|
|
83
|
-
initContext: {
|
|
84
|
-
stackFileName: selectedStackFileName,
|
|
85
|
-
blueprintFileName: selectedBlueprintFileName,
|
|
86
|
-
},
|
|
87
|
-
status: 'seed-generated-during-init',
|
|
88
|
-
supplementalFields: {
|
|
89
|
-
initSignals: {
|
|
90
|
-
detectedFrom: uiScopeSignals.signalReasons,
|
|
91
|
-
generatedBy: 'init-existing-project-seed',
|
|
92
|
-
},
|
|
93
|
-
repoEvidence: {
|
|
94
|
-
uiSignalReasons: uiScopeSignals.signalReasons,
|
|
95
|
-
frontendMetrics: uiScopeSignals.frontendEvidenceMetrics || null,
|
|
96
|
-
designEvidenceSummary: uiScopeSignals.designEvidenceSummary || null,
|
|
97
|
-
workspaceUiEntries: uiScopeSignals.workspaceUiEntries || [],
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
}
|
|
@@ -59,7 +59,6 @@ import {
|
|
|
59
59
|
loadProjectConfig,
|
|
60
60
|
normalizeDocsLanguage,
|
|
61
61
|
} from '../project-scaffolder.mjs';
|
|
62
|
-
import { migrateExistingDesignIntentToResearchDossierSchema } from '../project-scaffolder/design-contract/research-dossier-migration.mjs';
|
|
63
62
|
import { performRollback } from '../rollback.mjs';
|
|
64
63
|
import {
|
|
65
64
|
createTokenOptimizationState,
|
|
@@ -72,10 +71,7 @@ import {
|
|
|
72
71
|
ensureActiveMemorySnapshot,
|
|
73
72
|
writeMemoryContinuityState,
|
|
74
73
|
} from '../memory-continuity.mjs';
|
|
75
|
-
|
|
76
|
-
buildInitExistingProjectDesignIntentSeed,
|
|
77
|
-
inferExistingProjectDescriptionHint,
|
|
78
|
-
} from './init/project-context.mjs';
|
|
74
|
+
|
|
79
75
|
import {
|
|
80
76
|
detectRuntimeEnvironment,
|
|
81
77
|
resolveRuntimeEnvironmentKeyFromLabel,
|
|
@@ -87,6 +83,7 @@ import {
|
|
|
87
83
|
resolveProjectScopeLabelFromKey,
|
|
88
84
|
resolveSilentCiGuardrailsDefault,
|
|
89
85
|
} from './init/setup-decisions.mjs';
|
|
86
|
+
import { inferExistingProjectDescriptionHint } from './init/project-context.mjs';
|
|
90
87
|
|
|
91
88
|
export { REPOSITORY_ROOT } from '../constants.mjs';
|
|
92
89
|
export {
|
|
@@ -493,36 +490,14 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
493
490
|
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
494
491
|
})
|
|
495
492
|
: null;
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
505
|
-
packageManifest: existingProjectUiScopeSignals.packageManifest,
|
|
506
|
-
selectedStackFileName: selectedResolvedStackFileName,
|
|
507
|
-
selectedBlueprintFileName: selectedResolvedBlueprintFileName,
|
|
508
|
-
uiScopeSignals: existingProjectUiScopeSignals,
|
|
509
|
-
projectDescriptionHint,
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
await ensureDirectory(docsDirectoryPath);
|
|
513
|
-
await fs.writeFile(designIntentTargetPath, designIntentSeedContent, 'utf8');
|
|
514
|
-
supplementalMaterializedDocFileNames.push('design-intent.json');
|
|
515
|
-
|
|
516
|
-
console.log('\nExisting UI/frontend scope detected. Seeded docs/design-intent.json so the machine-readable design contract exists before UI implementation work continues.');
|
|
517
|
-
} else if (projectDetection.hasExistingProjectFiles && (await pathExists(designIntentTargetPath))) {
|
|
518
|
-
// Scenario E: existing project being initialized for the first time
|
|
519
|
-
// already has docs/design-intent.json. Migrate it to carry researchDossier.metadata
|
|
520
|
-
// so the anti-repeat ledger and freshness gate become available without
|
|
521
|
-
// touching existing tokens, anchor, or palette.
|
|
522
|
-
const migrationResult = await migrateExistingDesignIntentToResearchDossierSchema(designIntentTargetPath);
|
|
523
|
-
if (migrationResult.migrated) {
|
|
524
|
-
supplementalMaterializedDocFileNames.push('design-intent.json (research-dossier metadata migrated)');
|
|
525
|
-
console.log('\n[MIGRATED] docs/design-intent.json now carries researchDossier.metadata. Run research-design.md before next UI implementation to populate the dossier and refresh researchVerifiedAt.');
|
|
493
|
+
const obsoleteDesignIntentPath = path.join(resolvedTargetDirectoryPath, 'docs', 'design-intent.json');
|
|
494
|
+
if (await pathExists(obsoleteDesignIntentPath)) {
|
|
495
|
+
try {
|
|
496
|
+
await fs.unlink(obsoleteDesignIntentPath);
|
|
497
|
+
supplementalMaterializedDocFileNames.push('design-intent.json (DELETED - Obsolete Compliance Theater)');
|
|
498
|
+
console.log('\n[CLEANUP] Removed obsolete docs/design-intent.json. The 2026 Context Ops Paradigm uses plain-text DESIGN.md only.');
|
|
499
|
+
} catch (err) {
|
|
500
|
+
// ignore error
|
|
526
501
|
}
|
|
527
502
|
}
|
|
528
503
|
|
|
@@ -644,7 +619,7 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
644
619
|
console.log('\nPrompt starter examples (copy and adapt in your IDE):');
|
|
645
620
|
console.log('- If docs/project-brief.md is missing, execute .agent-context/prompts/bootstrap-project-context.md now and create all required docs files.');
|
|
646
621
|
if ((scaffoldingResult.generatedPromptFileNames || []).includes('bootstrap-design.md')) {
|
|
647
|
-
console.log('- If docs/DESIGN.md
|
|
622
|
+
console.log('- If docs/DESIGN.md is missing, execute .agent-context/prompts/bootstrap-design.md now before building UI components.');
|
|
648
623
|
}
|
|
649
624
|
console.log(`- Build an MVP for ${promptProjectName} using the newly synthesized docs as strict project context.`);
|
|
650
625
|
console.log('- When scope changes, update docs/* in the same change so future prompts stay aligned.');
|
|
@@ -656,12 +631,8 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
|
|
|
656
631
|
console.log(`- Build an MVP for ${promptProjectName}. Follow Layer 9 docs and keep the current stack, database, and auth constraints.`);
|
|
657
632
|
console.log('- Add [new feature] and update docs/project-brief.md plus docs/flow-overview.md in the same change.');
|
|
658
633
|
console.log('- If this change needs architecture migration, propose a migration plan first, then implement after approval.');
|
|
659
|
-
} else if (supplementalMaterializedDocFileNames.includes('design-intent.json')) {
|
|
660
|
-
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.');
|
|
661
|
-
console.log('\nPrompt starter examples (copy and adapt in your IDE):');
|
|
662
|
-
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.');
|
|
663
|
-
console.log('- Keep docs/design-intent.json and docs/DESIGN.md synchronized whenever the UI direction changes.');
|
|
664
634
|
}
|
|
635
|
+
|
|
665
636
|
console.log('Your AI tools will now receive AGENTS.md, native import bridges, and the lazy-loaded .agent-context rule library. Your review threshold is stored in .agent-context/policies/llm-judge-threshold.json.');
|
|
666
637
|
console.log('MCP server registration is manual inside your IDE settings, even when mcp.json exists.');
|
|
667
638
|
} catch (error) {
|
|
@@ -46,10 +46,8 @@ import {
|
|
|
46
46
|
} from '../backup.mjs';
|
|
47
47
|
import { performRollback } from '../rollback.mjs';
|
|
48
48
|
import { detectProjectDocTemplateStaleness } from '../project-scaffolder.mjs';
|
|
49
|
-
import { migrateExistingDesignIntentToResearchDossierSchema } from '../project-scaffolder/design-contract/research-dossier-migration.mjs';
|
|
50
49
|
import { ensureActiveMemorySnapshot } from '../memory-continuity.mjs';
|
|
51
50
|
import { buildExistingProjectMajorConstraints } from '../init-detection-flow.mjs';
|
|
52
|
-
import { buildUpgradeDesignIntentSeed } from './upgrade/design-intent-seed.mjs';
|
|
53
51
|
import {
|
|
54
52
|
applyUpgradeTokenOptimizationPlan,
|
|
55
53
|
resolveUpgradeTokenOptimizationPlan,
|
|
@@ -184,7 +182,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
184
182
|
projectScopeSourceLabel: 'onboarding project scope',
|
|
185
183
|
});
|
|
186
184
|
const packageManifest = uiScopeSignals.packageManifest;
|
|
187
|
-
const designContractPaths = ['docs/DESIGN.md'
|
|
185
|
+
const designContractPaths = ['docs/DESIGN.md'];
|
|
188
186
|
const missingDesignContractPaths = [];
|
|
189
187
|
|
|
190
188
|
for (const designContractPath of designContractPaths) {
|
|
@@ -193,17 +191,6 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
193
191
|
missingDesignContractPaths.push(designContractPath);
|
|
194
192
|
}
|
|
195
193
|
}
|
|
196
|
-
const shouldSeedDesignIntentOnApply = uiScopeSignals.isUiScopeLikely
|
|
197
|
-
&& missingDesignContractPaths.includes('docs/design-intent.json');
|
|
198
|
-
const designIntentSeedContent = shouldSeedDesignIntentOnApply
|
|
199
|
-
? buildUpgradeDesignIntentSeed({
|
|
200
|
-
targetDirectoryPath: resolvedTargetDirectoryPath,
|
|
201
|
-
packageManifest,
|
|
202
|
-
selectedStackFileName,
|
|
203
|
-
selectedBlueprintFileName,
|
|
204
|
-
uiScopeSignals,
|
|
205
|
-
})
|
|
206
|
-
: null;
|
|
207
194
|
|
|
208
195
|
const detectionMajorConstraints = buildExistingProjectMajorConstraints({ mode: 'upgrade' });
|
|
209
196
|
const detectionTransparency = {
|
|
@@ -320,11 +307,8 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
320
307
|
if (Array.isArray(uiScopeSignals.workspaceUiEntries) && uiScopeSignals.workspaceUiEntries.length > 0) {
|
|
321
308
|
console.log(`- Nested UI workspaces: ${uiScopeSignals.workspaceUiEntries.map((workspaceUiEntry) => workspaceUiEntry.relativePath).join(', ')}`);
|
|
322
309
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
console.log('Required action: create or refresh docs/DESIGN.md and docs/design-intent.json before allowing UI implementation work.');
|
|
327
|
-
console.log('Upgrade synchronizes governance assets and can seed docs/design-intent.json, but it does not author project-specific docs/DESIGN.md automatically.');
|
|
310
|
+
console.log('Required action: create or refresh docs/DESIGN.md before allowing UI implementation work.');
|
|
311
|
+
console.log('Upgrade synchronizes governance assets, but it does not author project-specific docs/DESIGN.md automatically.');
|
|
328
312
|
}
|
|
329
313
|
|
|
330
314
|
if (upgradeOptions.dryRun) {
|
|
@@ -369,21 +353,14 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
369
353
|
supplementalCreatedFileNames.push(tokenOptimizationApplyResult.createdFileName);
|
|
370
354
|
}
|
|
371
355
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
// Inject researchDossier.metadata when absent so the anti-repeat ledger
|
|
381
|
-
// becomes available and active validation can enforce freshness.
|
|
382
|
-
const existingDesignIntentPath = path.join(resolvedTargetDirectoryPath, 'docs', 'design-intent.json');
|
|
383
|
-
const migrationResult = await migrateExistingDesignIntentToResearchDossierSchema(existingDesignIntentPath);
|
|
384
|
-
if (migrationResult.migrated) {
|
|
385
|
-
supplementalCreatedFileNames.push('docs/design-intent.json (research-dossier metadata migrated)');
|
|
386
|
-
console.log('\n[MIGRATED] docs/design-intent.json now carries researchDossier.metadata. Run research-design.md before next UI implementation to populate the dossier and refresh researchVerifiedAt.');
|
|
356
|
+
const obsoleteDesignIntentPath = path.join(resolvedTargetDirectoryPath, 'docs', 'design-intent.json');
|
|
357
|
+
if (await pathExists(obsoleteDesignIntentPath)) {
|
|
358
|
+
try {
|
|
359
|
+
await fs.unlink(obsoleteDesignIntentPath);
|
|
360
|
+
supplementalCreatedFileNames.push('docs/design-intent.json (DELETED - Obsolete Compliance Theater)');
|
|
361
|
+
console.log('\n[CLEANUP] Removed obsolete docs/design-intent.json. The 2026 Context Ops Paradigm uses plain-text DESIGN.md only.');
|
|
362
|
+
} catch (err) {
|
|
363
|
+
// ignore error
|
|
387
364
|
}
|
|
388
365
|
}
|
|
389
366
|
|
|
@@ -453,7 +430,7 @@ export async function runUpgradeCommand(targetDirectoryArgument, upgradeOptions
|
|
|
453
430
|
console.log('\nRefreshed files: AGENTS.md, CLAUDE.md, GEMINI.md, .agent-context/, and .agent-context/state/onboarding-report.json');
|
|
454
431
|
console.log('Default activation cues remain Adaptive Context bootstrap, ASCX command wrappers, and Compact Natural final replies.');
|
|
455
432
|
console.log('Default response mode remains Compact Natural Mode through .agent-context/prompts/compact-natural-mode.md.');
|
|
456
|
-
|
|
433
|
+
|
|
457
434
|
} catch (error) {
|
|
458
435
|
console.error('\n[FATAL] An error occurred during upgrade. Attempting automatic rollback...');
|
|
459
436
|
try {
|
package/lib/cli/compiler.mjs
CHANGED
|
@@ -32,78 +32,8 @@ function toSingleLine(value, fallbackValue) {
|
|
|
32
32
|
return normalizedValue || fallbackValue;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
async function readDesignIntentIfExists(targetDirectoryPath) {
|
|
36
|
-
const designIntentPath = path.join(targetDirectoryPath, 'docs', 'design-intent.json');
|
|
37
|
-
if (!(await pathExists(designIntentPath))) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
return JSON.parse(await fs.readFile(designIntentPath, 'utf8'));
|
|
43
|
-
} catch {
|
|
44
|
-
return {
|
|
45
|
-
parseError: true,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
35
|
function buildAnchorCommitmentHeader(designIntent) {
|
|
51
|
-
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (designIntent.parseError) {
|
|
56
|
-
return [
|
|
57
|
-
'## [UI TASK ANCHOR - READ FIRST]',
|
|
58
|
-
'Source: docs/design-intent.json',
|
|
59
|
-
'Status: design-intent.json could not be parsed.',
|
|
60
|
-
'Required action: fix docs/design-intent.json before UI implementation so the creative commitment can be loaded.',
|
|
61
|
-
].join('\n');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const conceptualAnchor = designIntent.conceptualAnchor || {};
|
|
65
|
-
const derivedTokenLogic = designIntent.derivedTokenLogic || {};
|
|
66
|
-
const creativeCommitment = designIntent.designExecutionHandoff?.creativeCommitment || {};
|
|
67
|
-
const designFlexibilityPolicy = designIntent.designFlexibilityPolicy || {};
|
|
68
|
-
const expressionFlexibility = designIntent.designExecutionHandoff?.expressionFlexibility || {};
|
|
69
|
-
const anchorReference = conceptualAnchor.anchorReference || derivedTokenLogic.anchorReference;
|
|
70
|
-
const conceptualAnchorName = conceptualAnchor.name || anchorReference;
|
|
71
|
-
const signatureMove = conceptualAnchor.signatureMove
|
|
72
|
-
|| designIntent.designExecutionHandoff?.signatureMoveRationale;
|
|
73
|
-
const signatureMotion = conceptualAnchor.signatureMotion
|
|
74
|
-
|| creativeCommitment.signatureMotion
|
|
75
|
-
|| derivedTokenLogic.motionDerivationSource;
|
|
76
|
-
const typographicDecision = conceptualAnchor.typographicDecision
|
|
77
|
-
|| creativeCommitment.typographicDecision
|
|
78
|
-
|| derivedTokenLogic.typographyDerivationSource;
|
|
79
|
-
const flexibleAxes = Array.isArray(designFlexibilityPolicy.flexibleExpressionAxes)
|
|
80
|
-
? designFlexibilityPolicy.flexibleExpressionAxes
|
|
81
|
-
: expressionFlexibility.flexibleAxes;
|
|
82
|
-
const lockedOutcomes = Array.isArray(expressionFlexibility.lockedOutcomes)
|
|
83
|
-
? expressionFlexibility.lockedOutcomes
|
|
84
|
-
: designFlexibilityPolicy.lockedOutcomeTypes;
|
|
85
|
-
|
|
86
|
-
if (!conceptualAnchorName && !anchorReference) {
|
|
87
|
-
return [
|
|
88
|
-
'## [UI TASK ANCHOR - READ FIRST]',
|
|
89
|
-
'Source: docs/design-intent.json',
|
|
90
|
-
'Status: Creative commitment is missing.',
|
|
91
|
-
'Required action: define conceptualAnchor.anchorReference, a concrete real-world anchor, signature motion, typographic decision, derivedTokenLogic, and libraryDecisions before UI implementation.',
|
|
92
|
-
].join('\n');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return [
|
|
96
|
-
'## [UI TASK ANCHOR - READ FIRST]',
|
|
97
|
-
'Source: docs/design-intent.json',
|
|
98
|
-
`Conceptual Anchor: ${toSingleLine(conceptualAnchorName, 'MISSING - complete Creative Commitment Gate before UI implementation')}`,
|
|
99
|
-
`Anchor Reference: ${toSingleLine(anchorReference, 'MISSING - required for deterministic token validation')}`,
|
|
100
|
-
`Signature Move: ${toSingleLine(signatureMove, 'MISSING - define one concrete authored move before UI implementation')}`,
|
|
101
|
-
`Motion Signature: ${toSingleLine(signatureMotion, 'MISSING - define timing/easing/choreography before UI implementation')}`,
|
|
102
|
-
`Typographic Decision: ${toSingleLine(typographicDecision, 'MISSING - define role contrast before UI implementation')}`,
|
|
103
|
-
`Locked Outcomes: ${toSingleLine(Array.isArray(lockedOutcomes) ? lockedOutcomes.join(', ') : '', 'user goals, accessibility, production readiness, forbidden patterns')}`,
|
|
104
|
-
`Flexible Expression: ${toSingleLine(Array.isArray(flexibleAxes) ? flexibleAxes.join(', ') : '', 'exact primitives, typeface, surface treatment, component skin, candidate moves')}`,
|
|
105
|
-
'If the UI output does not reflect these lines, stop and revise the design contract before continuing.',
|
|
106
|
-
].join('\n');
|
|
36
|
+
return null;
|
|
107
37
|
}
|
|
108
38
|
|
|
109
39
|
function buildContainerizationStrategySnapshot(dockerStrategy) {
|
|
@@ -400,7 +330,7 @@ export async function buildCompiledRulesContent({
|
|
|
400
330
|
'3. .agent-context/prompts/review-code.md -> review, audit, check, analyze',
|
|
401
331
|
'4. .agent-context/prompts/bootstrap-design.md -> ui, ux, layout, screen, tailwind, frontend, redesign',
|
|
402
332
|
'Documentation-first policy:',
|
|
403
|
-
'- Create or refine required project docs before implementation: README.md for every fresh or existing project; docs/doc-index.md whenever docs/ exists; docs/project-brief.md; docs/architecture-decision-record.md; docs/flow-overview.md; docs/api-contract.md when APIs, firmware endpoints, CLI commands, or web application flows exist; docs/database-schema.md when persistent data exists; and docs/DESIGN.md
|
|
333
|
+
'- Create or refine required project docs before implementation: README.md for every fresh or existing project; docs/doc-index.md whenever docs/ exists; docs/project-brief.md; docs/architecture-decision-record.md; docs/flow-overview.md; docs/api-contract.md when APIs, firmware endpoints, CLI commands, or web application flows exist; docs/database-schema.md when persistent data exists; and docs/DESIGN.md for UI scope.',
|
|
404
334
|
'- Keep README.md public and developer friendly, including for private projects: explain what the project is, who it is for, setup, usage, configuration, and links to deeper docs. Do not put secrets, internal agent notes, private reasoning, or governance policy dumps in it.',
|
|
405
335
|
'- Use docs/doc-index.md as the compact read-routing map before selecting deeper docs. Do not broad-read docs/*.md by default.',
|
|
406
336
|
'- Add PRD, SRS, technical-design, or separate ERD only when project evidence justifies them.',
|
|
@@ -409,8 +339,7 @@ export async function buildCompiledRulesContent({
|
|
|
409
339
|
'- For docs-only/docs-first requests, do not write application, firmware, or UI code until the user asks or approves an implementation plan.',
|
|
410
340
|
'UI trigger policy:',
|
|
411
341
|
'- Load .agent-context/prompts/bootstrap-design.md and .agent-context/rules/frontend-architecture.md first.',
|
|
412
|
-
'-
|
|
413
|
-
'- For UI scope, materialize docs/DESIGN.md and docs/design-intent.json before implementing UI surfaces.',
|
|
342
|
+
'- Follow the three-step design direction process in bootstrap-design.md: name defaults, choose anchor, commit to creative direction.',
|
|
414
343
|
].join('\n')
|
|
415
344
|
);
|
|
416
345
|
|
|
@@ -567,7 +496,7 @@ export async function buildCompiledRulesContent({
|
|
|
567
496
|
'- Stop implementation if docs/flow-overview.md is missing.',
|
|
568
497
|
'- If the product uses persistent data, docs/database-schema.md must exist before coding continues.',
|
|
569
498
|
'- If the product exposes API or web application flows, docs/api-contract.md must exist before coding continues.',
|
|
570
|
-
'- For UI scope, stop implementation if docs/DESIGN.md
|
|
499
|
+
'- For UI scope, stop implementation if docs/DESIGN.md is missing.',
|
|
571
500
|
'- Keep README.md overview-level, public, and developer friendly; do not put secrets, internal agent notes, private reasoning, or governance policy dumps in it.',
|
|
572
501
|
'- Use README.md plus docs/doc-index.md to choose the smallest relevant read set before loading deeper docs.',
|
|
573
502
|
'- Add PRD, SRS, technical-design, or separate ERD only when project evidence justifies them.',
|
|
@@ -612,7 +541,7 @@ export async function buildCompiledRulesContent({
|
|
|
612
541
|
'- For docs-only/docs-first requests, stop after docs unless the user asks for implementation or approves an implementation plan.',
|
|
613
542
|
'- If docs/project-brief.md is missing, execute bootstrap-project-context prompt immediately.',
|
|
614
543
|
hasBootstrapDesignPrompt
|
|
615
|
-
? '- For UI scope: if docs/DESIGN.md
|
|
544
|
+
? '- For UI scope: if docs/DESIGN.md is missing, execute bootstrap-design prompt before implementing UI surfaces.'
|
|
616
545
|
: '- For UI scope: add a design bootstrap prompt before implementing UI surfaces.',
|
|
617
546
|
'- Bootstrap docs from repo evidence and the latest user request. Do not use generic placeholder templates.',
|
|
618
547
|
'- Separate confirmed facts from assumptions, include an Assumptions to Validate section when context is incomplete, and end with the next validation action.',
|
|
@@ -623,11 +552,6 @@ export async function buildCompiledRulesContent({
|
|
|
623
552
|
);
|
|
624
553
|
}
|
|
625
554
|
|
|
626
|
-
const designIntent = await readDesignIntentIfExists(resolvedTargetDirectoryPath);
|
|
627
|
-
const anchorCommitmentHeader = buildAnchorCommitmentHeader(designIntent);
|
|
628
|
-
if (anchorCommitmentHeader) {
|
|
629
|
-
contextBlocks.unshift(anchorCommitmentHeader);
|
|
630
|
-
}
|
|
631
555
|
|
|
632
556
|
return [
|
|
633
557
|
'# AGENTIC-SENIOR-CORE DYNAMIC GOVERNANCE RULESET',
|
package/lib/cli/preflight.mjs
CHANGED
|
@@ -71,27 +71,6 @@ export async function runPreflightChecks(targetDirectoryPath, operationMode) {
|
|
|
71
71
|
result.checks.push(`Skipping disk space check due to standard library limitation: ${error.message}`);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// Check 4: Conflicting Files
|
|
75
|
-
if (operationMode === 'init') {
|
|
76
|
-
const potentiallyConflictingPaths = [
|
|
77
|
-
...entryPointFiles.map((entryPointFileName) => path.join(targetDirectoryPath, entryPointFileName)),
|
|
78
|
-
path.join(targetDirectoryPath, '.agent-context'),
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
const conflictingFound = [];
|
|
82
|
-
for (const conflictPath of potentiallyConflictingPaths) {
|
|
83
|
-
if (await pathExists(conflictPath)) {
|
|
84
|
-
conflictingFound.push(path.relative(targetDirectoryPath, conflictPath).replace(/\\/g, '/'));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (conflictingFound.length > 0) {
|
|
89
|
-
result.passed = false;
|
|
90
|
-
result.errors.push(`Conflicting governance files already exist during init: ${conflictingFound.join(', ')}. Use upgrade instead.`);
|
|
91
|
-
} else {
|
|
92
|
-
result.checks.push('No conflicting governance files found.');
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
74
|
|
|
96
75
|
return result;
|
|
97
76
|
}
|
|
@@ -7,7 +7,7 @@ export const PROJECT_DOC_FILE_NAMES = [
|
|
|
7
7
|
'flow-overview.md',
|
|
8
8
|
];
|
|
9
9
|
export const DOC_INDEX_FILE_NAME = 'doc-index.md';
|
|
10
|
-
export const UI_DESIGN_CONTRACT_FILE_NAMES = ['DESIGN.md'
|
|
10
|
+
export const UI_DESIGN_CONTRACT_FILE_NAMES = ['DESIGN.md'];
|
|
11
11
|
|
|
12
12
|
// Legacy project docs may still carry this version header; keep for upgrade staleness checks.
|
|
13
13
|
export const PROJECT_DOC_TEMPLATE_VERSION = '1.2.0';
|