@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.
@@ -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 `previousMotionSignatures` as a hard blocklist before producing any candidate in Sections 3-5.
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
- ## Reference Routing
72
+ ## Default Detection Protocol
73
73
 
74
- After Section 1, identify the product category. Then run web_search
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
- Developer tool / CLI / AI infrastructure:
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
- SaaS / B2B productivity:
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
- AI product / API:
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
- Ecommerce:
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
- Design tool / creative:
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
- Consumer / mobile:
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
- Data / analytics:
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
- For every product category:
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
+ }
@@ -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,
@@ -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: {
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "4.3.0",
3
+ "version": "4.3.2",
4
4
  "type": "module",
5
5
  "description": "Change your AI Agent to code like a Staff Engineer, not a Junior.",
6
6
  "bin": {
@@ -393,6 +393,7 @@ export const REQUIRED_UI_DESIGN_AUTOMATION_SNIPPETS = [
393
393
  'genericity findings that cannot name the exact drift signal',
394
394
  'research-design.md',
395
395
  'Section 3 gate from `research-design.md`',
396
+ 'Pre-Emit Identity Check',
396
397
  ],
397
398
  },
398
399
  {
@@ -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: 220 },
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