@event4u/agent-config 16.4.0 → 16.5.0
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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +40 -191
- package/README.md +1 -1
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- package/dist/agent-src/skills/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
- package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
- package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/commands/uiRender.js +201 -4
- package/dist/cli/commands/uiRenderAsset.js +1308 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
- package/dist/cli/main.js +47 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/{chunk-MSUL5NYP.js → chunk-4DBG5K7M.js} +1 -1
- package/dist/cli-delegate/{chunk-AED2VQGM.js → chunk-TMWYUOK4.js} +10 -1
- package/dist/cli-delegate/cmd_conformance.js +395 -214
- package/dist/cli-delegate/cmd_handoff.js +2 -2
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +47 -22
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +6 -6
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +19 -15
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +13 -9
- package/dist/hooks/dispatch.js +1073 -808
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/svg_rules.chunk.cjs +1626 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +931 -735
- package/dist/scripts/_lib/scan_scope.js +105 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1337 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/lint_svg_asset.js +324 -0
- package/docs/guidelines/design-antipatterns.md +1 -1
- package/package.json +4 -3
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/routing-coverage-seed.json +9 -2
- package/src/scripts/_lib/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1453 -0
- package/src/scripts/_lib/svg_urls.ts +72 -0
- package/src/scripts/_lib/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +27 -17
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
- package/src/scripts/hooks/design_pass_hook.ts +157 -3
- package/src/scripts/hooks/svg_obligation.ts +497 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +5 -3
- package/src/scripts/lint_consolidation_lineage.ts +6 -3
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- package/src/scripts/lint_svg_asset.ts +365 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uiRenderAssetTypes — the asset profile's declared vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* Its own module so that the profile and its geometry comparison can both read
|
|
5
|
+
* these without importing each other: the profile calls the comparison, the
|
|
6
|
+
* comparison needs the classes and the tolerance shape, and a direct import
|
|
7
|
+
* either way round is a cycle.
|
|
8
|
+
*
|
|
9
|
+
* Every constant here was pre-registered in step 0.3 of
|
|
10
|
+
* `road-to-svg-with-a-witness` — before any checker existed — so a threshold
|
|
11
|
+
* could not be chosen to fit what a rule already reported.
|
|
12
|
+
*/
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Declared constants — every one of them pre-registered in step 0.3
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
export const ASSET_CLASSES = ['icon', 'mark', 'illustration', 'diagram', 'animated'];
|
|
18
|
+
/**
|
|
19
|
+
* Per class, never global. A file is loose BELOW its class threshold.
|
|
20
|
+
* Overridden by a `fill_ratio_thresholds` block in `--thresholds <file>`.
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_FILL_RATIO_THRESHOLDS = {
|
|
23
|
+
icon: 0.3,
|
|
24
|
+
mark: 0.45,
|
|
25
|
+
illustration: 0.4,
|
|
26
|
+
diagram: 0.35,
|
|
27
|
+
animated: 0.35,
|
|
28
|
+
};
|
|
29
|
+
/** Step 2.6's tolerances. Overridden by `geometry_tolerances` in `--thresholds`. */
|
|
30
|
+
export const DEFAULT_GEOMETRY_TOLERANCES = {
|
|
31
|
+
icon: { silhouette_iou_min: 0.98, max_boundary_distance_units: 1 },
|
|
32
|
+
mark: { silhouette_iou_min: 0.98, max_boundary_distance_units: 2 },
|
|
33
|
+
illustration: { silhouette_iou_min: 0.96, max_boundary_distance_units: 3 },
|
|
34
|
+
diagram: { silhouette_iou_min: 0.97, max_boundary_distance_units: 2 },
|
|
35
|
+
animated: { silhouette_iou_min: 0.97, max_boundary_distance_units: 2 },
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Used ONLY when no `tokens.json` resolves. The manifest records
|
|
39
|
+
* `source: "fallback"` whenever these are used, because a reader cannot
|
|
40
|
+
* otherwise tell a project's own background from this module's guess.
|
|
41
|
+
*/
|
|
42
|
+
export const FALLBACK_BACKGROUNDS = { light: '#ffffff', dark: '#111111' };
|
|
43
|
+
/** The four paths the brand resolver searches, in its order. First hit wins. */
|
|
44
|
+
export const BRAND_TOKEN_PATHS = [
|
|
45
|
+
'tokens.json',
|
|
46
|
+
'assets/tokens.json',
|
|
47
|
+
'resources/tokens.json',
|
|
48
|
+
path.join('agents', 'settings', 'brand', 'tokens.json'),
|
|
49
|
+
];
|
|
50
|
+
/** Icon sizes are the three the incumbent sets ship at. Other classes: 1x and 2x. */
|
|
51
|
+
export const ICON_SIZES = [16, 24, 48];
|
|
52
|
+
/**
|
|
53
|
+
* A `mark` is captured here too — step 4.3 of
|
|
54
|
+
* `road-to-svg-from-a-live-session`.
|
|
55
|
+
*
|
|
56
|
+
* A review sent an accepted mark back because its face turned to mush at
|
|
57
|
+
* 32 px, and a simplified small-size variant was built. Nothing in the profile
|
|
58
|
+
* produced a capture at those sizes, so the only way to know was to look at
|
|
59
|
+
* something that did not exist. 16 and 32 are the two the review named.
|
|
60
|
+
*/
|
|
61
|
+
export const MARK_SMALL_SIZES = [16, 32];
|
|
62
|
+
/**
|
|
63
|
+
* Below this, a draw-on animation is not reported. The planted row reads
|
|
64
|
+
* 0.283 (a 300-unit dash on a 215-unit path) and its twin reads 0.0, so the
|
|
65
|
+
* band between them is wide; 0.05 is inside it with room on both sides.
|
|
66
|
+
*/
|
|
67
|
+
export const DRAW_ON_DEAD_TIME_THRESHOLD = 0.05;
|
|
68
|
+
/** A channel at or above this, with alpha 1, counts as near-white paint. */
|
|
69
|
+
export const NEAR_WHITE_CHANNEL = 237;
|
|
70
|
+
/**
|
|
71
|
+
* The synthetic host document. Fulfilled by the route handler at a URL inside
|
|
72
|
+
* the asset's OWN directory, so a relative `href` inside the asset resolves
|
|
73
|
+
* exactly as it would in place — without this module ever writing into the
|
|
74
|
+
* directory it is reading.
|
|
75
|
+
*/
|
|
76
|
+
export const HOST_BASENAME = '__agent-config-asset-host__.html';
|
|
77
|
+
/** Schemes a page may reach. Everything else is aborted and counted. */
|
|
78
|
+
export const ALLOWED_SCHEMES = ['file:', 'data:', 'blob:', 'about:'];
|
|
79
|
+
/**
|
|
80
|
+
* How a shape declares that a gap in the silhouette is DELIBERATE.
|
|
81
|
+
*
|
|
82
|
+
* Step 4.1. A ring has a hole in the middle and the ground shows through it on
|
|
83
|
+
* purpose; without a way to say so, every ring reads as a seam. By attribute
|
|
84
|
+
* rather than by geometry, because "is this gap intended" is a question only
|
|
85
|
+
* the author can answer.
|
|
86
|
+
*/
|
|
87
|
+
export const HOLE_ATTRIBUTE = 'data-hole';
|
|
88
|
+
/**
|
|
89
|
+
* The bleed share above which `geometry/background-bleed-inside-silhouette`
|
|
90
|
+
* fires, pre-registered in `fixtures/svg-assets/README.md` before the reading
|
|
91
|
+
* was written.
|
|
92
|
+
*
|
|
93
|
+
* A seam is a hairline: one or two pixels wide along a shared edge. The
|
|
94
|
+
* overlap twin — the same two shapes overlapping by one unit — reads 0. The
|
|
95
|
+
* threshold sits between them with room on both sides.
|
|
96
|
+
*
|
|
97
|
+
* IT DOES MOVE WITH THE RENDER SIZE, and this doc used to claim it does not.
|
|
98
|
+
* Finding 7 of the third completion review. A share is scale-free only when
|
|
99
|
+
* both terms scale together: a seam whose width is a fraction of a USER UNIT
|
|
100
|
+
* grows with the capture and its share is stable, but one that is an
|
|
101
|
+
* anti-aliasing artefact stays one or two DEVICE pixels wide at every size, so
|
|
102
|
+
* its count grows with the perimeter while the denominator grows with the
|
|
103
|
+
* area — the share falls roughly as 1/width. The planted fixture is the second
|
|
104
|
+
* kind (a ring of inner radius 20 against a disc of radius 20), so this number
|
|
105
|
+
* is pre-registered against the capture sizes THIS PROFILE TAKES, which top
|
|
106
|
+
* out at 2x the intrinsic width. A caller rendering the same file at several
|
|
107
|
+
* thousand pixels would read a share below the threshold on a file that still
|
|
108
|
+
* has the seam.
|
|
109
|
+
*
|
|
110
|
+
* Not re-derived here: fixing it means making the reading a function of the
|
|
111
|
+
* seam's width in user units rather than of its pixel count, which is a
|
|
112
|
+
* different measurement and a larger change than a remediation should take.
|
|
113
|
+
* Stated so a reader is not told the opposite.
|
|
114
|
+
*/
|
|
115
|
+
export const BLEED_SHARE_THRESHOLD = 0.002;
|
|
116
|
+
/**
|
|
117
|
+
* Above this share of the registered source's painted pixels lying OUTSIDE the
|
|
118
|
+
* subject, `geometry/foreign-content-in-frame` fires.
|
|
119
|
+
*
|
|
120
|
+
* Finding 14 of this change's completion review: it was an inline `0.02` beside
|
|
121
|
+
* two named, documented, pre-registered thresholds. 2 % is the band an
|
|
122
|
+
* anti-aliased outline can occupy on a small mark without anything foreign
|
|
123
|
+
* being in the frame — it is a NOISE FLOOR, not a measured quality line, and
|
|
124
|
+
* saying so is the difference between a number a reader can argue with and one
|
|
125
|
+
* they cannot find.
|
|
126
|
+
*/
|
|
127
|
+
export const FOREIGN_CONTENT_SHARE_THRESHOLD = 0.02;
|
|
128
|
+
/** Below this contrast ratio against its ground, a painted pixel is hard to see. */
|
|
129
|
+
export const MIN_CONTRAST_RATIO = 3;
|
|
130
|
+
/**
|
|
131
|
+
* The share of painted pixels below {@link MIN_CONTRAST_RATIO} above which
|
|
132
|
+
* `accessibility/low-contrast-on-background` fires.
|
|
133
|
+
*
|
|
134
|
+
* Half the mark, not a few anti-aliased edge pixels: an edge blends into its
|
|
135
|
+
* ground by construction, and a rule that fired on that would fire on every
|
|
136
|
+
* file. Pre-registered with the bleed threshold above.
|
|
137
|
+
*/
|
|
138
|
+
export const LOW_CONTRAST_SHARE_THRESHOLD = 0.5;
|
|
139
|
+
/**
|
|
140
|
+
* The square sample grid both the profile and the comparison rasterise into.
|
|
141
|
+
* One constant because a comparison taken at a different resolution than the
|
|
142
|
+
* reading it is compared against is not a comparison.
|
|
143
|
+
*/
|
|
144
|
+
export const SAMPLE_RES = 256;
|
|
145
|
+
//# sourceMappingURL=uiRenderAssetTypes.js.map
|
package/dist/cli/main.js
CHANGED
|
@@ -23,6 +23,7 @@ import { runDoctorShell } from './commands/doctorShell.js';
|
|
|
23
23
|
import { runRtkDetect } from './commands/rtkDetect.js';
|
|
24
24
|
import { runUiAudit } from './commands/uiAudit.js';
|
|
25
25
|
import { runUiRender } from './commands/uiRender.js';
|
|
26
|
+
import { parseRegistration } from './commands/uiRenderAssetCompare.js';
|
|
26
27
|
import { runUiServe } from './commands/uiServe.js';
|
|
27
28
|
import { shouldInitLaunchGui, buildInitGuiOptions, buildProjectInitDelegation, findInitGuiConflict, withoutGuiFlag } from './initRouting.js';
|
|
28
29
|
import { maybePrintFirstRunNotice } from './firstRunNotice.js';
|
|
@@ -125,8 +126,53 @@ async function main(rawArgv) {
|
|
|
125
126
|
.option('--json', 'Print the manifest on stdout as well as writing it')
|
|
126
127
|
.option('--project-root <path>', 'Override the project root')
|
|
127
128
|
.option('--slug <name>', 'Override the output directory name')
|
|
129
|
+
.option('--profile <name>', 'page (default) or asset — a single SVG, per class, light and dark')
|
|
130
|
+
.option('--class <name>', 'Asset class: icon | mark | illustration | diagram | animated')
|
|
131
|
+
.option('--delivery <mode>', 'Delivery mode: inline | document | img | css-bg')
|
|
132
|
+
.option('--thresholds <file>', 'JSON carrying fill_ratio_thresholds / geometry_tolerances')
|
|
133
|
+
.option('--icon-set <paths>', 'Comma-separated incumbent icon SVGs, read for their own grid')
|
|
134
|
+
.option('--compare <file>', 'Second render of the same frame to compare against')
|
|
135
|
+
.option('--registration <spec>', 'Raster source region as x,y,w,h[@scale]')
|
|
128
136
|
.action(async (target, opts) => {
|
|
129
|
-
|
|
137
|
+
// Validated, not cast. A cast let `--class Icon` through as an
|
|
138
|
+
// AssetClass that matches no threshold key, so
|
|
139
|
+
// `fill_ratio_threshold` came out `undefined`,
|
|
140
|
+
// `structure/loose-viewbox` could never fire, and the key
|
|
141
|
+
// vanished from the manifest — a silent downgrade of a reading
|
|
142
|
+
// to nothing. `lint_svg_asset` validates the same two
|
|
143
|
+
// vocabularies and exits 1; so does this.
|
|
144
|
+
const ASSET_CLASS_NAMES = ['icon', 'mark', 'illustration', 'diagram', 'animated'];
|
|
145
|
+
const DELIVERY_NAMES = ['inline', 'document', 'img', 'css-bg'];
|
|
146
|
+
if (opts.class !== undefined && !ASSET_CLASS_NAMES.includes(opts.class)) {
|
|
147
|
+
process.stderr.write(`[ui:render] unknown --class "${opts.class}"; expected one of ${ASSET_CLASS_NAMES.join(', ')}\n`);
|
|
148
|
+
process.exitCode = 1;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (opts.delivery !== undefined && !DELIVERY_NAMES.includes(opts.delivery)) {
|
|
152
|
+
process.stderr.write(`[ui:render] unknown --delivery "${opts.delivery}"; expected one of ${DELIVERY_NAMES.join(', ')}\n`);
|
|
153
|
+
process.exitCode = 1;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (opts.profile !== undefined && opts.profile !== 'page' && opts.profile !== 'asset') {
|
|
157
|
+
process.stderr.write(`[ui:render] unknown --profile "${opts.profile}"; expected page or asset\n`);
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
process.exitCode = await runUiRender({
|
|
162
|
+
target,
|
|
163
|
+
...(opts.json === undefined ? {} : { json: opts.json }),
|
|
164
|
+
...(opts.projectRoot === undefined ? {} : { projectRoot: opts.projectRoot }),
|
|
165
|
+
...(opts.slug === undefined ? {} : { slug: opts.slug }),
|
|
166
|
+
...(opts.profile === 'asset' ? { profile: 'asset' } : {}),
|
|
167
|
+
...(opts.class === undefined ? {} : { assetClass: opts.class }),
|
|
168
|
+
...(opts.delivery === undefined ? {} : { delivery: opts.delivery }),
|
|
169
|
+
...(opts.thresholds === undefined ? {} : { thresholds: opts.thresholds }),
|
|
170
|
+
...(opts.iconSet === undefined ? {} : { iconSet: opts.iconSet.split(',').map((s) => s.trim()) }),
|
|
171
|
+
...(opts.compare === undefined ? {} : { compareTo: opts.compare }),
|
|
172
|
+
...(parseRegistration(opts.registration) === null
|
|
173
|
+
? {}
|
|
174
|
+
: { registration: parseRegistration(opts.registration) }),
|
|
175
|
+
});
|
|
130
176
|
});
|
|
131
177
|
program
|
|
132
178
|
.command('ui:serve')
|
package/dist/cli/registry.js
CHANGED
|
@@ -37,7 +37,7 @@ export const REGISTRY = [
|
|
|
37
37
|
{ name: 'rtk:detect', disposition: 'native', synopsis: 'rtk (Rust Token Killer) presence + identity readout — contract: docs/contracts/rtk-detection.md.' },
|
|
38
38
|
{ name: 'ui:serve', disposition: 'native', synopsis: 'Start the local UI server.' },
|
|
39
39
|
{ name: 'ui:audit', disposition: 'native', synopsis: 'Inventory a UI tree into agents/runtime/state/ui-audit.json (Class A; the artefact ui-audit-gate reads).' },
|
|
40
|
-
{ name: 'ui:render', disposition: 'native', synopsis: 'Headless capture at desktop / 375px / 320px into agents/runtime/state/render/ (Class A; no process survives).' },
|
|
40
|
+
{ name: 'ui:render', disposition: 'native', synopsis: 'Headless capture at desktop / 375px / 320px, or --profile asset for one SVG per class on a light and a dark background, into agents/runtime/state/render/ (Class A; no process survives).' },
|
|
41
41
|
{ name: 'config', disposition: 'native', synopsis: 'Open the configuration GUI (global by default; --project for the project surface).' },
|
|
42
42
|
{ name: 'settings', disposition: 'native', synopsis: 'Open the local Settings GUI (alias of config).' },
|
|
43
43
|
{ name: 'install', disposition: 'native', synopsis: 'Open the install wizard (UI server, lands on Step 1 / AI tools).' },
|
|
@@ -562,6 +562,8 @@ function segmentVerifies(rawWords) {
|
|
|
562
562
|
case "node":
|
|
563
563
|
case "deno":
|
|
564
564
|
return rest.some((a) => a === "test" || a.startsWith("--test"));
|
|
565
|
+
case "agent-config":
|
|
566
|
+
return false;
|
|
565
567
|
case "scripts-run": {
|
|
566
568
|
const script = bareName(arg1);
|
|
567
569
|
return /^(check|lint|verify|validate)[-_]/.test(script);
|
|
@@ -579,6 +581,12 @@ var _WIDE_CANDIDATE_RE = /\b(test|tests|vitest|jest|pytest|phpunit|pest|tsc|esli
|
|
|
579
581
|
function mightBeVerification(command) {
|
|
580
582
|
return _WIDE_CANDIDATE_RE.test(command);
|
|
581
583
|
}
|
|
584
|
+
function isAssetRenderCommand(command) {
|
|
585
|
+
return /\bui:render\b/.test(command) && /--profile[= ]\s*asset\b/.test(command);
|
|
586
|
+
}
|
|
587
|
+
function isVerificationAttempt(command) {
|
|
588
|
+
return isVerificationCommand(command) || isAssetRenderCommand(command);
|
|
589
|
+
}
|
|
582
590
|
|
|
583
591
|
// src/scripts/_lib/touched_file_quality.ts
|
|
584
592
|
import { spawnSync } from "node:child_process";
|
|
@@ -2753,7 +2761,8 @@ function pruneAgedRefusalState(workspaceRoot, opts = {}) {
|
|
|
2753
2761
|
}
|
|
2754
2762
|
|
|
2755
2763
|
export {
|
|
2756
|
-
|
|
2764
|
+
isAssetRenderCommand,
|
|
2765
|
+
isVerificationAttempt,
|
|
2757
2766
|
readRunEvidence,
|
|
2758
2767
|
hasRedThenGreen,
|
|
2759
2768
|
describeRecordFinding,
|