@ryuenn3123/agentic-senior-core 4.3.0 → 4.3.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 +12 -0
- package/.agent-context/prompts/research-design.md +11 -35
- package/AGENTS.md +1 -1
- package/benchmarks/runtime-token-saver/fixtures.mjs +122 -0
- package/lib/cli/ascx/adapters/npm-install.mjs +94 -0
- package/lib/cli/ascx/adapters/tsc.mjs +70 -0
- package/lib/cli/ascx/lexer.mjs +20 -0
- package/lib/cli/ascx/runtime.mjs +4 -0
- package/lib/cli/project-scaffolder/design-contract/research-dossier-migration.mjs +1 -0
- package/lib/cli/project-scaffolder/design-contract/validation/research-dossier-validators.mjs +1 -1
- package/package.json +1 -1
- package/scripts/validate/config.mjs +1 -0
- package/scripts/validate/coverage-checks.mjs +1 -1
|
@@ -87,6 +87,18 @@ Before UI code, record:
|
|
|
87
87
|
- one morphology or composition choice that avoids interchangeable card stacks when the product allows it
|
|
88
88
|
- at least three at-a-glance product-specific signals for new screens or broad redesigns
|
|
89
89
|
Do not ship AI-safe UI. Record exact drift signals in `reviewRubric`; at minimum reject decorative grid wallpaper, default line backgrounds, calibration-mark wallpaper, soft glow backgrounds, generic abstract marks, testing/demo/placeholder UI copy, terminal-only user flows, and first-output composition with only local copy swapped in when they have no product function. Treat measurement, calibration, crop, route, timeline, and inspection marks as task overlays or control affordances only; never promote them to the page background, hero backdrop, or first-output visual texture. If a conceptual anchor suggests a forbidden motif, the forbidden motif wins; express the anchor through workflow, hierarchy, density, typography, material behavior, state design, and interaction grammar instead of literal wallpaper.
|
|
90
|
+
## Pre-Emit Identity Check
|
|
91
|
+
|
|
92
|
+
Before outputting any UI code, mockup, or design direction, answer:
|
|
93
|
+
|
|
94
|
+
1. **Specificity test**: If the product name and all text were removed from this UI, would a designer still identify what product category and what specific product this was built for? If the answer is "no" or "only category, not this specific product" -- revise the concept, not the details.
|
|
95
|
+
|
|
96
|
+
2. **Structural variety test**: Does the hero or primary viewport avoid the centred-everything composition (large name centered, subtitle below, CTA below that)? If yes, pass. If no, name the product reason for centred composition or revise.
|
|
97
|
+
|
|
98
|
+
3. **Default detection test**: Name the one design default you were most tempted to use. Confirm it was rejected or adapted with a product-specific reason, not merely avoided.
|
|
99
|
+
|
|
100
|
+
Failure on any test requires revision before output. This check is not optional and applies to both new designs and additive UI tasks that change composition.
|
|
101
|
+
|
|
90
102
|
## Brave Redesign Default
|
|
91
103
|
For UI design work, the agent owns the ambition decision. For broad screens, redesigns, or new visual systems, treat expressive motion, spatial hierarchy, distinctive composition, and product-specific interaction as the baseline even when the user did not say "rich". Do not reduce the request to a safer version of the existing UI, a static implementation, or a component-kit rearrangement because research or dependency selection feels inconvenient.
|
|
92
104
|
|
|
@@ -44,7 +44,7 @@ Research vocabulary is internal-only. Use `sourceFreshness`, `evidenceTable[]`,
|
|
|
44
44
|
|
|
45
45
|
## Anti-Repeat Ledger Gate (read first)
|
|
46
46
|
|
|
47
|
-
If `docs/design-intent.json` already exists and carries `researchDossier.metadata.antiRepeatLedger`, treat every entry under `previousAnchors`, `previousPalettes`, and `
|
|
47
|
+
If `docs/design-intent.json` already exists and carries `researchDossier.metadata.antiRepeatLedger`, treat every entry under `previousAnchors`, `previousPalettes`, `previousMotionSignatures`, and `previousStructuralFingerprints` as a hard blocklist before producing any candidate in Sections 3-5.
|
|
48
48
|
|
|
49
49
|
Rules:
|
|
50
50
|
|
|
@@ -69,49 +69,25 @@ Before any visual choice, write a structured product reading:
|
|
|
69
69
|
|
|
70
70
|
Output: `productReading` block. Each field must be one sentence, evidence-backed from repo or brief. Speculation is not allowed; if a field is unknown, name it as such and stop until the user resolves it.
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## Default Detection Protocol
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
and web_fetch on the matching domains below (or other modern, highly-regarded digital product equivalents) before picking any anchor.
|
|
74
|
+
Before fetching any reference, use the `productReading` output to derive search direction. Do not self-select from a fixed category list.
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
→ Linear, Raycast, Vercel, Warp, Resend, Railway (or equivalents)
|
|
76
|
+
1. **Name defaults.** Name three design directions the agent is most tempted to use for this brief. For each, write one sentence naming the specific visual pattern (layout, palette, density, motion, typography, composition).
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
→ Notion, Loom, Cron, Superhuman, Intercom (or equivalents)
|
|
78
|
+
2. **Argue against each default.** For each default, write one sentence on why it would flatten what is specific about THIS product's core verb, data shape, or context of use. The argument must reference a `productReading` field, not a generic aesthetic opinion.
|
|
82
79
|
|
|
83
|
-
|
|
84
|
-
→ Anthropic, Perplexity, ElevenLabs, Replicate, Mistral (or equivalents)
|
|
80
|
+
3. **Derive search direction from the argument.** The rejection argument reveals what the product needs that the default cannot provide. Use that need as the search query for `web_search` and `web_fetch`. Search by the product's core characteristic pair (medium x intent), not by product category name. Example: core verb "demonstrate" + data shape "narrative" -> search "editorial portfolio interaction design" not "portfolio sites."
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
→ SSENSE, Allbirds, Represent, Shopify examples (or equivalents)
|
|
82
|
+
4. **Cross-domain pull.** Identify one domain that shares the same interaction model but a different visual vocabulary. Pull one reference from there. Example: portfolio -> scientific publication, exhibition catalog, film press kit -- anything with "demonstrate body of work" as the core verb but a different surface expectation.
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
→ Framer, Spline, Rive, Penpot (or equivalents)
|
|
84
|
+
5. **Gallery check.** Find state-of-the-art quality references for the derived direction by searching the web. CRITICAL: DO NOT use gallery homepages or discovery platforms as references. You must drill down to find a specific featured product/website, fetch THAT specific product's URL, and use it as evidence.
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
→ Arc browser, Craft, Things, Bear (or equivalents)
|
|
86
|
+
DO NOT fetch: Wikipedia, Dribbble templates, or generic blog posts about "best UI design practices."
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
→ Retool, Posthog, Metabase, Grafana (or equivalents)
|
|
88
|
+
For each reference: fetch the actual product page this session, record what mechanic or hierarchy is borrowed, and explicitly state what is NOT borrowed (palette, component skin, layout rhythm).
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
→ Also check galleries like Awwwards, Godly.website, and Layers.to to find
|
|
100
|
-
state-of-the-art quality references.
|
|
101
|
-
CRITICAL: DO NOT use the gallery homepage itself as a reference. You must
|
|
102
|
-
find a specific featured product/website from those galleries, fetch THAT
|
|
103
|
-
specific product's URL, and use it as your anchor.
|
|
104
|
-
|
|
105
|
-
DO NOT fetch: Wikipedia, Dribbble templates, or generic blog posts
|
|
106
|
-
about "best UI design practices."
|
|
107
|
-
|
|
108
|
-
For each reference: fetch the actual product page this session, record what
|
|
109
|
-
mechanic or hierarchy is borrowed, and explicitly state what is NOT
|
|
110
|
-
borrowed (palette, component skin, layout rhythm).
|
|
111
|
-
|
|
112
|
-
If the anchor concept you're considering would make sense to someone
|
|
113
|
-
from 1920, it's too archival. The anchor must be legible to someone
|
|
114
|
-
who uses the web today.
|
|
90
|
+
If the anchor concept you're considering would make sense to someone from 1920, it's too archival. The anchor must be legible to someone who uses the web today.
|
|
115
91
|
|
|
116
92
|
## Section 2 — Reference Intake
|
|
117
93
|
|
package/AGENTS.md
CHANGED
|
@@ -29,7 +29,7 @@ Keep it short. Do not load every rule just to fill it out.
|
|
|
29
29
|
|
|
30
30
|
## Default Activation And Command Economy
|
|
31
31
|
Before any non-trivial task, run `agentic-senior-core context "<task_description>"` and emit the Bootstrap Receipt. Skip only for trivial tasks: version bumps, typo fixes, single-line commits.
|
|
32
|
-
Always prefix noisy shell commands: `ascx git status`, `ascx git diff`, `ascx npm test`, `ascx rg` searches. Use raw commands only for pipes, redirects, or commands not supported by ascx.
|
|
32
|
+
Always prefix noisy shell commands: `ascx git status`, `ascx git diff`, `ascx npm test`, `ascx npm install`, `ascx npm run build`, `ascx tsc`, `ascx rg` searches. Use raw commands only for pipes, redirects, or commands not supported by ascx.
|
|
33
33
|
Always read and apply `.agent-context/prompts/compact-natural-mode.md` for every final user-facing reply. Never repeat full command output; reference tee file paths when truncated.
|
|
34
34
|
|
|
35
35
|
## Layer Index
|
|
@@ -711,4 +711,126 @@ export const ASCX_RUNTIME_TOKEN_SAVER_FIXTURES = [
|
|
|
711
711
|
},
|
|
712
712
|
],
|
|
713
713
|
},
|
|
714
|
+
{
|
|
715
|
+
id: 'npm-install-success',
|
|
716
|
+
commandArguments: ['npm', 'install'],
|
|
717
|
+
capture: {
|
|
718
|
+
exitCode: 0,
|
|
719
|
+
stdout: [
|
|
720
|
+
'npm WARN deprecated package...',
|
|
721
|
+
'added 142 packages in 12s',
|
|
722
|
+
].join('\n'),
|
|
723
|
+
stderr: '',
|
|
724
|
+
},
|
|
725
|
+
expectCompressed: true,
|
|
726
|
+
expectTee: false,
|
|
727
|
+
requiredSubstrings: [
|
|
728
|
+
'npm install summary:',
|
|
729
|
+
'added 142 packages in 12s',
|
|
730
|
+
'exit: 0',
|
|
731
|
+
],
|
|
732
|
+
continuationChecks: [
|
|
733
|
+
{
|
|
734
|
+
id: 'npm-install-success-compacts-noise',
|
|
735
|
+
action: 'Recognize the install passed and avoid reading raw noise.',
|
|
736
|
+
requiredSubstrings: [
|
|
737
|
+
'added 142 packages in 12s',
|
|
738
|
+
'exit: 0',
|
|
739
|
+
],
|
|
740
|
+
expectTee: false,
|
|
741
|
+
},
|
|
742
|
+
],
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
id: 'npm-install-failure',
|
|
746
|
+
commandArguments: ['npm', 'install'],
|
|
747
|
+
capture: {
|
|
748
|
+
exitCode: 1,
|
|
749
|
+
stdout: '',
|
|
750
|
+
stderr: [
|
|
751
|
+
'npm WARN deprecated package...',
|
|
752
|
+
'npm ERR! code ERESOLVE',
|
|
753
|
+
'npm ERR! ERESOLVE unable to resolve dependency tree',
|
|
754
|
+
].join('\n'),
|
|
755
|
+
},
|
|
756
|
+
expectCompressed: true,
|
|
757
|
+
expectTee: true,
|
|
758
|
+
requiredSubstrings: [
|
|
759
|
+
'npm install summary:',
|
|
760
|
+
'failures:',
|
|
761
|
+
'npm ERR! code ERESOLVE',
|
|
762
|
+
'exit: 1',
|
|
763
|
+
],
|
|
764
|
+
continuationChecks: [
|
|
765
|
+
{
|
|
766
|
+
id: 'npm-install-failure-preserves-error',
|
|
767
|
+
action: 'Identify the installation error.',
|
|
768
|
+
requiredSubstrings: [
|
|
769
|
+
'failures:',
|
|
770
|
+
'npm ERR! code ERESOLVE',
|
|
771
|
+
],
|
|
772
|
+
expectTee: true,
|
|
773
|
+
},
|
|
774
|
+
],
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
id: 'tsc-success',
|
|
778
|
+
commandArguments: ['tsc'],
|
|
779
|
+
capture: {
|
|
780
|
+
exitCode: 0,
|
|
781
|
+
stdout: '',
|
|
782
|
+
stderr: '',
|
|
783
|
+
},
|
|
784
|
+
expectCompressed: true,
|
|
785
|
+
expectTee: false,
|
|
786
|
+
requiredSubstrings: [
|
|
787
|
+
'tsc summary:',
|
|
788
|
+
'result: passed',
|
|
789
|
+
'exit: 0',
|
|
790
|
+
],
|
|
791
|
+
continuationChecks: [
|
|
792
|
+
{
|
|
793
|
+
id: 'tsc-success-compacts-noise',
|
|
794
|
+
action: 'Recognize the typecheck passed.',
|
|
795
|
+
requiredSubstrings: [
|
|
796
|
+
'result: passed',
|
|
797
|
+
'exit: 0',
|
|
798
|
+
],
|
|
799
|
+
expectTee: false,
|
|
800
|
+
},
|
|
801
|
+
],
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
id: 'tsc-failure',
|
|
805
|
+
commandArguments: ['tsc'],
|
|
806
|
+
capture: {
|
|
807
|
+
exitCode: 1,
|
|
808
|
+
stdout: [
|
|
809
|
+
'src/components/Header.tsx:15:10 - error TS2322: Type \'string\' is not assignable to type \'number\'.',
|
|
810
|
+
'15 const age: number = "25";',
|
|
811
|
+
].join('\n'),
|
|
812
|
+
stderr: '',
|
|
813
|
+
},
|
|
814
|
+
expectCompressed: true,
|
|
815
|
+
expectTee: true,
|
|
816
|
+
requiredSubstrings: [
|
|
817
|
+
'tsc summary:',
|
|
818
|
+
'failures:',
|
|
819
|
+
'error TS2322',
|
|
820
|
+
'Header.tsx:15:10',
|
|
821
|
+
'exit: 1',
|
|
822
|
+
],
|
|
823
|
+
continuationChecks: [
|
|
824
|
+
{
|
|
825
|
+
id: 'tsc-failure-preserves-error',
|
|
826
|
+
action: 'Identify the typecheck error and file path.',
|
|
827
|
+
requiredSubstrings: [
|
|
828
|
+
'failures:',
|
|
829
|
+
'error TS2322',
|
|
830
|
+
'Header.tsx:15:10',
|
|
831
|
+
],
|
|
832
|
+
expectTee: true,
|
|
833
|
+
},
|
|
834
|
+
],
|
|
835
|
+
},
|
|
714
836
|
];
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const FAILURE_LINE_PATTERN = /(?:^npm error|^npm ERR!|^error\b|^ERESOLVE\b|^Failed to)/iu;
|
|
2
|
+
const SUMMARY_LINE_PATTERN = /(?:added \d+ packages|up to date in|Done in \d+|Packages: \+\d+)/iu;
|
|
3
|
+
|
|
4
|
+
function pushUniqueLine(lines, nextLine) {
|
|
5
|
+
const normalizedLine = String(nextLine || '').trimEnd();
|
|
6
|
+
if (normalizedLine && !lines.includes(normalizedLine)) {
|
|
7
|
+
lines.push(normalizedLine);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function compressNpmInstallOutput({ stdout, stderr, exitCode }) {
|
|
12
|
+
const rawOutput = [stdout, stderr].filter(Boolean).join('\n');
|
|
13
|
+
const lines = rawOutput.split(/\r?\n/u);
|
|
14
|
+
|
|
15
|
+
if (exitCode === 0) {
|
|
16
|
+
let summaryLine = 'result: passed';
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
if (SUMMARY_LINE_PATTERN.test(line)) {
|
|
19
|
+
summaryLine = line.trim();
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
filterName: 'npm-install-summary',
|
|
26
|
+
confident: true,
|
|
27
|
+
truncated: false,
|
|
28
|
+
output: `npm install summary:\n${summaryLine}`,
|
|
29
|
+
preservedFields: {
|
|
30
|
+
exitCode: true,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const keptLines = [];
|
|
36
|
+
let contextBuffer = [];
|
|
37
|
+
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
const trimmedLine = line.trim();
|
|
40
|
+
|
|
41
|
+
if (!trimmedLine) {
|
|
42
|
+
if (contextBuffer.length > 0) {
|
|
43
|
+
contextBuffer.push(line);
|
|
44
|
+
}
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (FAILURE_LINE_PATTERN.test(trimmedLine)) {
|
|
49
|
+
for (const ctxLine of contextBuffer) {
|
|
50
|
+
pushUniqueLine(keptLines, ctxLine);
|
|
51
|
+
}
|
|
52
|
+
contextBuffer = [];
|
|
53
|
+
pushUniqueLine(keptLines, line);
|
|
54
|
+
} else {
|
|
55
|
+
contextBuffer.push(line);
|
|
56
|
+
if (contextBuffer.length > 2) {
|
|
57
|
+
contextBuffer.shift();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const outputLines = ['npm install summary:'];
|
|
63
|
+
|
|
64
|
+
if (keptLines.length > 0) {
|
|
65
|
+
outputLines.push('failures:');
|
|
66
|
+
outputLines.push(...keptLines.slice(0, 50));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const truncated = keptLines.length > 50;
|
|
70
|
+
if (truncated) {
|
|
71
|
+
outputLines.push(`... truncated ${keptLines.length - 50} more failure evidence lines`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (keptLines.length === 0) {
|
|
75
|
+
return {
|
|
76
|
+
filterName: 'npm-install-raw-parse-uncertain',
|
|
77
|
+
confident: false,
|
|
78
|
+
truncated: false,
|
|
79
|
+
output: rawOutput,
|
|
80
|
+
preservedFields: {},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
filterName: 'npm-install-summary',
|
|
86
|
+
confident: true,
|
|
87
|
+
truncated,
|
|
88
|
+
output: outputLines.join('\n'),
|
|
89
|
+
preservedFields: {
|
|
90
|
+
rootError: keptLines.length > 0,
|
|
91
|
+
exitCode: true,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const ERROR_LINE_PATTERN = /(?:error TS\d+:|Error:)/iu;
|
|
2
|
+
const FILE_LINE_PATTERN = /(?:[A-Za-z]:)?[^:\s]+?\.(?:ts|tsx|js|jsx):\d+,\d+/u;
|
|
3
|
+
|
|
4
|
+
function pushUniqueLine(lines, nextLine) {
|
|
5
|
+
const normalizedLine = String(nextLine || '').trimEnd();
|
|
6
|
+
if (normalizedLine && !lines.includes(normalizedLine)) {
|
|
7
|
+
lines.push(normalizedLine);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function compressTscOutput({ stdout, stderr, exitCode }) {
|
|
12
|
+
const rawOutput = [stdout, stderr].filter(Boolean).join('\n');
|
|
13
|
+
const lines = rawOutput.split(/\r?\n/u);
|
|
14
|
+
|
|
15
|
+
if (exitCode === 0) {
|
|
16
|
+
return {
|
|
17
|
+
filterName: 'tsc-summary',
|
|
18
|
+
confident: true,
|
|
19
|
+
truncated: false,
|
|
20
|
+
output: 'tsc summary:\nresult: passed',
|
|
21
|
+
preservedFields: {
|
|
22
|
+
exitCode: true,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const keptLines = [];
|
|
28
|
+
|
|
29
|
+
for (const line of lines) {
|
|
30
|
+
const trimmedLine = line.trim();
|
|
31
|
+
if (!trimmedLine) continue;
|
|
32
|
+
|
|
33
|
+
if (ERROR_LINE_PATTERN.test(trimmedLine) || FILE_LINE_PATTERN.test(trimmedLine)) {
|
|
34
|
+
pushUniqueLine(keptLines, line);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const outputLines = ['tsc summary:'];
|
|
39
|
+
|
|
40
|
+
if (keptLines.length > 0) {
|
|
41
|
+
outputLines.push('failures:');
|
|
42
|
+
outputLines.push(...keptLines.slice(0, 50));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const truncated = keptLines.length > 50;
|
|
46
|
+
if (truncated) {
|
|
47
|
+
outputLines.push(`... truncated ${keptLines.length - 50} more failure evidence lines`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (keptLines.length === 0) {
|
|
51
|
+
return {
|
|
52
|
+
filterName: 'tsc-raw-parse-uncertain',
|
|
53
|
+
confident: false,
|
|
54
|
+
truncated: false,
|
|
55
|
+
output: rawOutput,
|
|
56
|
+
preservedFields: {},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
filterName: 'tsc-summary',
|
|
62
|
+
confident: true,
|
|
63
|
+
truncated,
|
|
64
|
+
output: outputLines.join('\n'),
|
|
65
|
+
preservedFields: {
|
|
66
|
+
rootError: keptLines.length > 0,
|
|
67
|
+
exitCode: true,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
package/lib/cli/ascx/lexer.mjs
CHANGED
|
@@ -121,6 +121,26 @@ export function classifyAscxInvocation(parsedCommand) {
|
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
const isNpmInstall = parsedCommand.executable === 'npm' && ['install', 'i', 'ci'].includes(parsedCommand.args[0]);
|
|
125
|
+
const isYarnInstall = parsedCommand.executable === 'yarn' && (parsedCommand.args.length === 0 || parsedCommand.args[0] === 'install');
|
|
126
|
+
const isPnpmInstall = parsedCommand.executable === 'pnpm' && ['install', 'i'].includes(parsedCommand.args[0]);
|
|
127
|
+
|
|
128
|
+
if (isNpmInstall || isYarnInstall || isPnpmInstall) {
|
|
129
|
+
return {
|
|
130
|
+
kind: 'compressible',
|
|
131
|
+
adapterName: 'npm-install',
|
|
132
|
+
reason: 'supported dependency installation adapter',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (parsedCommand.executable === 'tsc' || (parsedCommand.executable === 'npx' && parsedCommand.args[0] === 'tsc')) {
|
|
137
|
+
return {
|
|
138
|
+
kind: 'compressible',
|
|
139
|
+
adapterName: 'tsc',
|
|
140
|
+
reason: 'supported tsc adapter',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
124
144
|
return {
|
|
125
145
|
kind: 'passthrough',
|
|
126
146
|
adapterName: null,
|
package/lib/cli/ascx/runtime.mjs
CHANGED
|
@@ -4,6 +4,8 @@ import { compressGitDiffOutput } from './adapters/git-diff.mjs';
|
|
|
4
4
|
import { compressGitStatusOutput } from './adapters/git-status.mjs';
|
|
5
5
|
import { compressNpmTestOutput } from './adapters/npm-test.mjs';
|
|
6
6
|
import { compressNpmRunBuildOutput } from './adapters/npm-run-build.mjs';
|
|
7
|
+
import { compressNpmInstallOutput } from './adapters/npm-install.mjs';
|
|
8
|
+
import { compressTscOutput } from './adapters/tsc.mjs';
|
|
7
9
|
import { compressRgOutput } from './adapters/rg.mjs';
|
|
8
10
|
import { buildAscxFooter, shouldWriteSafetyTee } from './formatter.mjs';
|
|
9
11
|
import { classifyAscxInvocation, parseAscxCommand } from './lexer.mjs';
|
|
@@ -14,6 +16,8 @@ const ADAPTERS = {
|
|
|
14
16
|
'git-status': compressGitStatusOutput,
|
|
15
17
|
'npm-test': compressNpmTestOutput,
|
|
16
18
|
'npm-run-build': compressNpmRunBuildOutput,
|
|
19
|
+
'npm-install': compressNpmInstallOutput,
|
|
20
|
+
'tsc': compressTscOutput,
|
|
17
21
|
'rg': compressRgOutput,
|
|
18
22
|
};
|
|
19
23
|
|
|
@@ -122,6 +122,7 @@ export function buildResearchDossierMetadata({
|
|
|
122
122
|
previousPalettes: [],
|
|
123
123
|
previousMotionSignatures: [],
|
|
124
124
|
previousTypographyChoices: [],
|
|
125
|
+
previousStructuralFingerprints: [],
|
|
125
126
|
},
|
|
126
127
|
userExplicitRedesignBypassesFreshness: true,
|
|
127
128
|
statusAwareValidation: {
|
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', 'previousTypographyChoices'];
|
|
15
|
+
const ANTI_REPEAT_LEDGER_CATEGORIES = ['previousAnchors', 'previousPalettes', 'previousMotionSignatures', 'previousTypographyChoices', 'previousStructuralFingerprints'];
|
|
16
16
|
|
|
17
17
|
function validateMetadataBaseShape(metadata, validationErrors) {
|
|
18
18
|
if (
|
package/package.json
CHANGED
|
@@ -366,7 +366,7 @@ export async function validateInstructionAdapters(context) {
|
|
|
366
366
|
];
|
|
367
367
|
const instructionFootprintLimits = [
|
|
368
368
|
{ path: 'AGENTS.md', maxLines: 180 },
|
|
369
|
-
{ path: '.agent-context/prompts/bootstrap-design.md', maxLines:
|
|
369
|
+
{ path: '.agent-context/prompts/bootstrap-design.md', maxLines: 235 },
|
|
370
370
|
{ path: '.agent-context/rules/frontend-architecture.md', maxLines: 180 },
|
|
371
371
|
];
|
|
372
372
|
|