@ryuenn3123/agentic-senior-core 4.0.1 → 4.0.2
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 +2 -1
- package/.agent-context/prompts/research-design.md +17 -0
- package/README.md +2 -0
- package/lib/cli/project-scaffolder/design-contract/research-dossier-migration.mjs +24 -0
- package/lib/cli/project-scaffolder/design-contract/validation/completeness.mjs +38 -0
- package/lib/cli/project-scaffolder/design-contract/validation/research-dossier-validators.mjs +1 -1
- package/lib/cli/project-scaffolder/design-contract.mjs +8 -0
- package/package.json +1 -1
- package/scripts/documentation-boundary-audit.mjs +13 -0
- package/scripts/release-gate/static-checks.mjs +6 -1
- package/scripts/validate/config.mjs +7 -0
|
@@ -20,7 +20,8 @@ This contract is a decision scaffold, not a style preset. We guide the agent; we
|
|
|
20
20
|
5. Encode `repoEvidence.designEvidenceSummary` when onboarding or detector evidence exists.
|
|
21
21
|
6. Keep both design docs synchronized after implementation.
|
|
22
22
|
7. Complete the Section 3-5 gates from `research-design.md` before UI implementation: `conceptualAnchor.categoryCodes.candidateEntries`, `conceptualAnchor.morphologicalExploration` (selected and uncomfortable combinations), and `conceptualAnchor.anchorCandidates.candidates` (exactly five, each with the strengthened rename test recorded).
|
|
23
|
-
8.
|
|
23
|
+
8. Set `derivedTokenLogic.tokenContinuityClassification` for each of typography, palette, motion, and spacing. Use `anchor-derived` only when the token choice is causally tied to the anchor's real-world reality. Use `continuity-retained` when the token is kept from a previous design iteration without re-derivation. Use `newly-introduced` when the token is fresh but not anchor-derived. If any token category is `continuity-retained`, the typography, palette, or motion entry in `researchDossier.metadata.antiRepeatLedger` stays as historical record, and the classification declares the retention is intentional with explicit rationale recorded in the matching `derivationSource` field.
|
|
24
|
+
9. After agent and user select an anchor, set `researchDossier.metadata.researchVerifiedAt` to today's ISO date and flip `status` from any seed value to `active`. This closes the freshness window for additive UI tasks within `freshnessWindowDays`.
|
|
24
25
|
## Creative Commitment Gate
|
|
25
26
|
Before broad compliance review or UI implementation, record an agent-chosen visual direction in both design docs:
|
|
26
27
|
- one concrete real-world anchor reference
|
|
@@ -90,6 +90,23 @@ Self-test: read each category code aloud to someone unfamiliar with the project.
|
|
|
90
90
|
|
|
91
91
|
Output: at least three category codes per product surface in `categoryCodes`. Each entry must pass the specificity self-test, must include the one-sentence reason that pattern is the default for the category, and must include an explicit one-sentence rejection note ("I will not ship this; here is the trap it sets") so the cliche cannot quietly become the target.
|
|
92
92
|
|
|
93
|
+
### Dimensional split (mandatory)
|
|
94
|
+
|
|
95
|
+
Category codes must be broken down by dimension. Do not collapse multiple dimensions into a single category-level cliche. Each cluster lists the patterns that the product category will default to without intervention.
|
|
96
|
+
|
|
97
|
+
- `typographyClusters`: font family combinations that are the category default. Be explicit about font families. Name the actual trio or pair that this product's category currently defaults to, derived from live portfolio observation for THIS task. Do not anchor on examples from other categories or other timeframes.
|
|
98
|
+
- `paletteClusters`: palette signatures that are the category default.
|
|
99
|
+
- `layoutClusters`: layout patterns that are the category default.
|
|
100
|
+
- `motionClusters`: motion signatures that are the category default.
|
|
101
|
+
- `imageryClusters`: image style or visual treatment that is the category default.
|
|
102
|
+
|
|
103
|
+
Self-check before proceeding to Section 4: do the typography choices the agent is about to commit to in `derivedTokenLogic` (or downstream token sections) overlap with any item in `typographyClusters`? If yes, the agent must either:
|
|
104
|
+
|
|
105
|
+
1. Flag the typography as a continuity choice with an explicit rationale, set `derivedTokenLogic.tokenContinuityClassification.typography` to `continuity-retained`, and record the reason that font family swap is deferred. The previous typography ledger entry stays as historical record; the classification declares the retention is intentional. OR
|
|
106
|
+
2. Revise the typography pick to escape the autopilot cluster and set `tokenContinuityClassification.typography` to `anchor-derived` only when the new choice is causally tied to the anchor's real-world reality.
|
|
107
|
+
|
|
108
|
+
This self-check applies to every dimension, not only typography. Do not let an output token match a category-code item from the agent's own list without explicit (1) or (2) treatment per dimension. Pretending continuity is derivation is the failure mode this gate exists to prevent.
|
|
109
|
+
|
|
93
110
|
## Section 4 — Morphological Exploration
|
|
94
111
|
|
|
95
112
|
A morphological matrix forces the design space to be explored beyond the first idea.
|
package/README.md
CHANGED
|
@@ -63,6 +63,8 @@ The intended behavior is agent-led, not offline-template-led:
|
|
|
63
63
|
- Modern UI claims: research current-year libraries and patterns when relevant; 2026 work should use 2026 evidence, and future years should update automatically through agent research.
|
|
64
64
|
- Anti-generic rule: avoid safe dashboard shells, admin panels, card grids, scale-only mobile layouts, and static no-motion interfaces unless the product context explicitly justifies them.
|
|
65
65
|
|
|
66
|
+
UI design work runs a research dossier prompt (`.agent-context/prompts/research-design.md`) before the bootstrap prompt. The dossier captures product reading, reference intake, category cliches, a morphological matrix, and five anchor candidates with a strengthened rename test. The contract carries a 90-day `researchVerifiedAt` freshness gate and an anti-repeat ledger seeded from prior anchor, palette, motion, and typography choices on existing projects, so additive UI work within the freshness window skips the research stage while redesigns and stale dossiers re-run it.
|
|
67
|
+
|
|
66
68
|
---
|
|
67
69
|
|
|
68
70
|
## MCP Quick Setup (VS Code)
|
|
@@ -84,6 +84,28 @@ function buildPreviousMotionEntry(designIntentContract) {
|
|
|
84
84
|
}];
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
function buildPreviousTypographyEntry(designIntentContract) {
|
|
88
|
+
if (!designIntentContract || typeof designIntentContract !== 'object') {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
const tokenSystem = designIntentContract?.tokenSystem;
|
|
92
|
+
const typographyTokens = tokenSystem && typeof tokenSystem === 'object' ? tokenSystem.typographyTokens : null;
|
|
93
|
+
if (!typographyTokens || typeof typographyTokens !== 'object') {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
const tokenEntries = Object.entries(typographyTokens)
|
|
97
|
+
.filter(([, value]) => typeof value === 'string' && value.trim().length > 0)
|
|
98
|
+
.map(([role, value]) => `${role}: ${value.trim()}`);
|
|
99
|
+
if (tokenEntries.length === 0) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
return [{
|
|
103
|
+
summary: tokenEntries.join('; '),
|
|
104
|
+
source: 'migrated-from-existing-design-intent',
|
|
105
|
+
blockedBecause: 'previously-shipped-typography-trio',
|
|
106
|
+
}];
|
|
107
|
+
}
|
|
108
|
+
|
|
87
109
|
export function buildResearchDossierMetadata({
|
|
88
110
|
designIntentContract = null,
|
|
89
111
|
populateLedgerFromExistingContract = false,
|
|
@@ -99,6 +121,7 @@ export function buildResearchDossierMetadata({
|
|
|
99
121
|
previousAnchors: [],
|
|
100
122
|
previousPalettes: [],
|
|
101
123
|
previousMotionSignatures: [],
|
|
124
|
+
previousTypographyChoices: [],
|
|
102
125
|
},
|
|
103
126
|
userExplicitRedesignBypassesFreshness: true,
|
|
104
127
|
statusAwareValidation: {
|
|
@@ -116,6 +139,7 @@ export function buildResearchDossierMetadata({
|
|
|
116
139
|
metadata.antiRepeatLedger.previousAnchors = buildPreviousAnchorEntry(designIntentContract).slice(0, metadata.antiRepeatLedger.ledgerMaxEntriesPerCategory);
|
|
117
140
|
metadata.antiRepeatLedger.previousPalettes = buildPreviousPaletteEntry(designIntentContract).slice(0, metadata.antiRepeatLedger.ledgerMaxEntriesPerCategory);
|
|
118
141
|
metadata.antiRepeatLedger.previousMotionSignatures = buildPreviousMotionEntry(designIntentContract).slice(0, metadata.antiRepeatLedger.ledgerMaxEntriesPerCategory);
|
|
142
|
+
metadata.antiRepeatLedger.previousTypographyChoices = buildPreviousTypographyEntry(designIntentContract).slice(0, metadata.antiRepeatLedger.ledgerMaxEntriesPerCategory);
|
|
119
143
|
}
|
|
120
144
|
|
|
121
145
|
return metadata;
|
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
import { hasNonEmptyString } from './helpers.mjs';
|
|
9
9
|
|
|
10
|
+
const SEED_STATUSES = new Set([
|
|
11
|
+
'seed-needs-design-synthesis',
|
|
12
|
+
'seed-generated-during-init',
|
|
13
|
+
'seed-generated-during-upgrade',
|
|
14
|
+
]);
|
|
15
|
+
const REQUIRED_TOKEN_CATEGORIES = ['typography', 'palette', 'motion', 'spacing'];
|
|
16
|
+
const ACTIVE_CLASSIFICATION_VALUES = new Set(['anchor-derived', 'continuity-retained', 'newly-introduced']);
|
|
17
|
+
const SEED_CLASSIFICATION_VALUES = new Set(['anchor-derived', 'continuity-retained', 'newly-introduced', 'pending-research']);
|
|
18
|
+
|
|
10
19
|
export function validateDesignContractCompleteness(designIntentContract) {
|
|
11
20
|
const validationIssues = [];
|
|
12
21
|
const conceptualAnchor = designIntentContract?.conceptualAnchor;
|
|
@@ -47,6 +56,35 @@ export function validateDesignContractCompleteness(designIntentContract) {
|
|
|
47
56
|
) {
|
|
48
57
|
validationIssues.push('designIntent.derivedTokenLogic.validationRule must require traceability to anchorReference.');
|
|
49
58
|
}
|
|
59
|
+
|
|
60
|
+
const tokenContinuityClassification = derivedTokenLogic.tokenContinuityClassification;
|
|
61
|
+
const isSeedStatus = SEED_STATUSES.has(designIntentContract?.status);
|
|
62
|
+
const allowedClassificationValues = isSeedStatus ? SEED_CLASSIFICATION_VALUES : ACTIVE_CLASSIFICATION_VALUES;
|
|
63
|
+
if (!tokenContinuityClassification || typeof tokenContinuityClassification !== 'object') {
|
|
64
|
+
validationIssues.push('designIntent.derivedTokenLogic.tokenContinuityClassification must exist. Each token category (typography, palette, motion, spacing) must declare anchor-derived, continuity-retained, or newly-introduced (pending-research is allowed only on seed contracts).');
|
|
65
|
+
} else {
|
|
66
|
+
if (
|
|
67
|
+
!Array.isArray(tokenContinuityClassification.validValues)
|
|
68
|
+
|| !tokenContinuityClassification.validValues.includes('anchor-derived')
|
|
69
|
+
|| !tokenContinuityClassification.validValues.includes('continuity-retained')
|
|
70
|
+
|| !tokenContinuityClassification.validValues.includes('newly-introduced')
|
|
71
|
+
|| !tokenContinuityClassification.validValues.includes('pending-research')
|
|
72
|
+
) {
|
|
73
|
+
validationIssues.push('designIntent.derivedTokenLogic.tokenContinuityClassification.validValues must include anchor-derived, continuity-retained, newly-introduced, and pending-research.');
|
|
74
|
+
}
|
|
75
|
+
if (!hasNonEmptyString(tokenContinuityClassification.rule)) {
|
|
76
|
+
validationIssues.push('designIntent.derivedTokenLogic.tokenContinuityClassification.rule must explain when each value applies.');
|
|
77
|
+
}
|
|
78
|
+
for (const tokenCategoryName of REQUIRED_TOKEN_CATEGORIES) {
|
|
79
|
+
const classifiedValue = tokenContinuityClassification[tokenCategoryName];
|
|
80
|
+
if (!allowedClassificationValues.has(classifiedValue)) {
|
|
81
|
+
const allowedLabel = isSeedStatus
|
|
82
|
+
? 'anchor-derived, continuity-retained, newly-introduced, or pending-research'
|
|
83
|
+
: 'anchor-derived, continuity-retained, or newly-introduced';
|
|
84
|
+
validationIssues.push(`designIntent.derivedTokenLogic.tokenContinuityClassification.${tokenCategoryName} must be one of: ${allowedLabel}. Got: "${classifiedValue}".`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
50
88
|
}
|
|
51
89
|
|
|
52
90
|
if (!['verified', 'pending-verification', 'no-external-library-needed'].includes(designIntentContract?.libraryResearchStatus)) {
|
package/lib/cli/project-scaffolder/design-contract/validation/research-dossier-validators.mjs
CHANGED
|
@@ -12,7 +12,7 @@ const REQUIRED_SEED_STATUSES = [
|
|
|
12
12
|
'seed-generated-during-init',
|
|
13
13
|
'seed-generated-during-upgrade',
|
|
14
14
|
];
|
|
15
|
-
const ANTI_REPEAT_LEDGER_CATEGORIES = ['previousAnchors', 'previousPalettes', 'previousMotionSignatures'];
|
|
15
|
+
const ANTI_REPEAT_LEDGER_CATEGORIES = ['previousAnchors', 'previousPalettes', 'previousMotionSignatures', 'previousTypographyChoices'];
|
|
16
16
|
|
|
17
17
|
function validateMetadataBaseShape(metadata, validationErrors) {
|
|
18
18
|
if (
|
|
@@ -139,6 +139,14 @@ function buildDesignIntentContractObject({
|
|
|
139
139
|
typeScaleMethod: 'Prefer fluid clamp() type scales when supported; name ratio, role contrast, balance/wrap behavior, and numeric typography needs.',
|
|
140
140
|
motionBudget: 'Name micro, layout, entrance, easing, stagger, and reduced-motion budgets; prefer transform/opacity for high-frequency motion.',
|
|
141
141
|
validationRule: 'Every semantic token role must trace to anchorReference; keep exact primitive values flexible unless locked by repo evidence, accessibility validation, implementation constraints, or explicit user approval.',
|
|
142
|
+
tokenContinuityClassification: {
|
|
143
|
+
typography: 'pending-research',
|
|
144
|
+
palette: 'pending-research',
|
|
145
|
+
motion: 'pending-research',
|
|
146
|
+
spacing: 'pending-research',
|
|
147
|
+
validValues: ['anchor-derived', 'continuity-retained', 'newly-introduced', 'pending-research'],
|
|
148
|
+
rule: 'For each token category, classify whether the choice is anchor-derived (causally tied to anchorReference real-world reality), continuity-retained (kept from a previous design iteration without re-derivation), or newly-introduced (fresh choice not tied to anchor). Continuity-retained is acceptable; pretending continuity is derivation is not.',
|
|
149
|
+
},
|
|
142
150
|
},
|
|
143
151
|
motionPaletteDecision: buildMotionPaletteDecisionSection(),
|
|
144
152
|
aiSafeUiAudit: buildAiSafeUiAuditSection({ projectName }),
|
package/package.json
CHANGED
|
@@ -74,6 +74,19 @@ const BOUNDARY_RULES = [
|
|
|
74
74
|
'README.md',
|
|
75
75
|
],
|
|
76
76
|
trigger(filePath) {
|
|
77
|
+
// Path-based exclusion: design-contract JSON shape lives under
|
|
78
|
+
// lib/cli/project-scaffolder/. Files like research-dossier-migration.mjs
|
|
79
|
+
// describe agent-prompt JSON contract migrations, not database schema
|
|
80
|
+
// or persistent-store migrations, so they must not trigger this boundary
|
|
81
|
+
// even when the filename contains the words "schema" or "migration".
|
|
82
|
+
// Tests for those design-contract migrations are excluded for the same
|
|
83
|
+
// reason.
|
|
84
|
+
if (filePath.startsWith('lib/cli/project-scaffolder/')) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (filePath.startsWith('tests/') && /research-dossier|design-contract/i.test(filePath)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
77
90
|
return !isDocumentationFilePath(filePath)
|
|
78
91
|
&& /(database|schema|migration|repository|sql|prisma|typeorm|knex)/i.test(filePath);
|
|
79
92
|
},
|
|
@@ -79,7 +79,12 @@ export function runStaticReleaseChecks(results, diagnostics) {
|
|
|
79
79
|
stackFileName: 'agent-decision-runtime.md',
|
|
80
80
|
blueprintFileName: 'agent-decision-architecture.md',
|
|
81
81
|
},
|
|
82
|
-
status:
|
|
82
|
+
// Seed status so `tokenContinuityClassification: pending-research`
|
|
83
|
+
// is a valid placeholder. This probe asserts seed-shape completeness,
|
|
84
|
+
// not active-contract behavior; an agent or user fills the contract
|
|
85
|
+
// with anchor-derived / continuity-retained / newly-introduced once
|
|
86
|
+
// the dossier is filled.
|
|
87
|
+
status: 'seed-needs-design-synthesis',
|
|
83
88
|
}));
|
|
84
89
|
const designContractIssues = validateDesignContractCompleteness(designIntentSeed);
|
|
85
90
|
|
|
@@ -376,6 +376,13 @@ export const REQUIRED_UI_DESIGN_AUTOMATION_SNIPPETS = [
|
|
|
376
376
|
'Anti-Repeat Ledger Gate',
|
|
377
377
|
'previousAnchors',
|
|
378
378
|
'previousMotionSignatures',
|
|
379
|
+
'Dimensional split',
|
|
380
|
+
'typographyClusters',
|
|
381
|
+
'paletteClusters',
|
|
382
|
+
'layoutClusters',
|
|
383
|
+
'motionClusters',
|
|
384
|
+
'imageryClusters',
|
|
385
|
+
'tokenContinuityClassification',
|
|
379
386
|
],
|
|
380
387
|
},
|
|
381
388
|
{
|