@event4u/agent-config 7.1.0 → 7.3.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/.claude-plugin/marketplace.json +2 -1
- package/CHANGELOG.md +80 -0
- package/README.md +9 -10
- package/dist/agent-src/rules/brand-source-of-truth.md +10 -0
- package/dist/agent-src/rules/delegation-policy.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +42 -4
- package/dist/agent-src/rules/output-discipline.md +85 -0
- package/dist/agent-src/rules/telegraph-speak.md +4 -1
- package/dist/agent-src/rules/token-budget-discipline.md +94 -0
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +20 -5
- package/dist/agent-src/skills/blade-ui/SKILL.md +9 -0
- package/dist/agent-src/skills/bug-analyzer/evals/evals.json +13 -0
- package/dist/agent-src/skills/code-review/evals/evals.json +21 -0
- package/dist/agent-src/skills/contract-review/SKILL.md +3 -2
- package/dist/agent-src/skills/dashboard-design/SKILL.md +21 -5
- package/dist/agent-src/skills/design-intelligence/SKILL.md +96 -0
- package/dist/agent-src/skills/design-review/SKILL.md +83 -0
- package/dist/agent-src/skills/design-system-capture/SKILL.md +234 -0
- package/dist/agent-src/skills/design-tokens/SKILL.md +1 -0
- package/dist/agent-src/skills/dpa-review/SKILL.md +3 -2
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +15 -4
- package/dist/agent-src/skills/fe-design/SKILL.md +98 -16
- package/dist/agent-src/skills/flux/SKILL.md +8 -0
- package/dist/agent-src/skills/iconography/SKILL.md +1 -0
- package/dist/agent-src/skills/legal-intake-triage/SKILL.md +3 -2
- package/dist/agent-src/skills/legal-practice-profile/SKILL.md +3 -2
- package/dist/agent-src/skills/livewire/SKILL.md +8 -0
- package/dist/agent-src/skills/nda-triage/SKILL.md +3 -2
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +21 -9
- package/dist/agent-src/skills/skill-writing/SKILL.md +18 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +7 -10
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +17 -7
- package/dist/agent-src/skills/typography-system/SKILL.md +14 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +123 -59
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -8
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +18 -15
- package/dist/discovery/trust-report.md +5 -5
- package/dist/discovery/workspaces.json +15 -12
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/router.json +1 -1
- package/dist/server/routes/wizard.js +4 -3
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/schemas/settings.js +9 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/ui/assets/{index-CoQo90sz.js → index-UjcTG_9O.js} +2 -2
- package/dist/ui/assets/index-UjcTG_9O.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/RELEASE_STORY_TEMPLATE.md +37 -0
- package/docs/architecture.md +3 -3
- package/docs/contracts/capability-boundary.md +64 -0
- package/docs/contracts/discovery-manifest.schema.json +2 -2
- package/docs/contracts/governance-enforcement-projection.md +154 -0
- package/docs/contracts/package-self-orientation.md +3 -0
- package/docs/contracts/subagent-boundary.md +54 -0
- package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +13 -0
- package/docs/decisions/ADR-107-legal-domain-pack-adoption.md +19 -0
- package/docs/enforcement-by-host.md +35 -0
- package/docs/getting-started.md +1 -1
- package/docs/guidelines/agent-infra/domain-pack-architecture.md +1 -0
- package/docs/guidelines/design-antipatterns-triggers.json +17 -0
- package/docs/guidelines/design-antipatterns.md +170 -0
- package/docs/guidelines/design-modes.md +97 -0
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +31 -0
- package/src/config/discovery/packs.yml +16 -5
- package/src/config/discovery/workspaces.yml +4 -4
- package/src/scripts/_lib/eval_discrimination.ts +95 -0
- package/src/scripts/_lib/trigger_routers.ts +268 -0
- package/src/scripts/bench_ab_v2_run.ts +38 -0
- package/src/scripts/check_trunk_drift.ts +67 -0
- package/src/scripts/cross_model_smoke.ts +245 -0
- package/src/scripts/lint_design_quality.ts +321 -0
- package/src/scripts/lint_discovery_vocabulary.ts +4 -4
- package/src/scripts/lint_legal_pack.ts +62 -4
- package/src/scripts/lint_output_slop.ts +223 -0
- package/src/scripts/lint_pack_risk_class.ts +79 -0
- package/src/scripts/run_skill_evals.ts +38 -0
- package/src/scripts/schemas/agent-settings.schema.json +12 -0
- package/src/scripts/schemas/skill.schema.json +5 -0
- package/src/scripts/skill_linter.ts +26 -10
- package/dist/ui/assets/index-CoQo90sz.js.map +0 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint the `risk_class` invariant on packs (road-to-capability-governance Phase 2).
|
|
3
|
+
*
|
|
4
|
+
* `risk_class: high` is the regulated-advice-adjacent tier. A high-risk pack MUST
|
|
5
|
+
* ship conservatively — off by default, consent-gated, lab-tier — or it is a
|
|
6
|
+
* governance hole. This linter makes that invariant a hard CI failure.
|
|
7
|
+
*
|
|
8
|
+
* high ⇒ default_install: false AND requires_explicit_consent: true AND surface_tier: lab
|
|
9
|
+
*
|
|
10
|
+
* `medium` / `low` carry no structural requirement here (their disclaimers live
|
|
11
|
+
* in the domain safety floors). Absent `risk_class` = `low`.
|
|
12
|
+
*
|
|
13
|
+
* Pure core (`riskClassViolations`) takes the packs.yml text so it is unit-testable
|
|
14
|
+
* without the filesystem. Exit 0 = clean, 1 = at least one violation.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
20
|
+
|
|
21
|
+
const QUIET = process.argv.includes('--quiet');
|
|
22
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
23
|
+
const REPO = path.resolve(path.dirname(_HERE), '..', '..');
|
|
24
|
+
const PACKS_YML = path.join(REPO, 'src', 'config', 'discovery', 'packs.yml');
|
|
25
|
+
|
|
26
|
+
export interface RiskViolation {
|
|
27
|
+
pack: string;
|
|
28
|
+
msg: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function _field(block: string, key: string): string | undefined {
|
|
32
|
+
return new RegExp(`(^|\\n)\\s*${key}:\\s*([^\\n#]+)`).exec(block)?.[2]?.trim();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Pure invariant check over packs.yml text. */
|
|
36
|
+
export function riskClassViolations(packsYml: string): RiskViolation[] {
|
|
37
|
+
const out: RiskViolation[] = [];
|
|
38
|
+
// Split into per-pack blocks on top-level `- id:` entries.
|
|
39
|
+
const re = /(^|\n)- id:\s*([^\n#]+?)\s*\n([\s\S]*?)(?=\n- id:|\n*$)/g;
|
|
40
|
+
let m: RegExpExecArray | null;
|
|
41
|
+
while ((m = re.exec(packsYml)) !== null) {
|
|
42
|
+
const id = (m[2] ?? '').trim();
|
|
43
|
+
const block = m[3] ?? '';
|
|
44
|
+
const risk = _field(block, 'risk_class') ?? 'low';
|
|
45
|
+
if (risk !== 'high') continue;
|
|
46
|
+
const checks: Array<[string, string, string]> = [
|
|
47
|
+
['default_install', 'false', `${id}: risk_class high requires default_install: false`],
|
|
48
|
+
['requires_explicit_consent', 'true', `${id}: risk_class high requires requires_explicit_consent: true`],
|
|
49
|
+
['surface_tier', 'lab', `${id}: risk_class high requires surface_tier: lab`],
|
|
50
|
+
];
|
|
51
|
+
for (const [key, want, msg] of checks) {
|
|
52
|
+
if (_field(block, key) !== want) out.push({ pack: id, msg });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function _print(s: string): void {
|
|
59
|
+
if (!QUIET) process.stdout.write(`${s}\n`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function main(): number {
|
|
63
|
+
if (!fs.existsSync(PACKS_YML)) {
|
|
64
|
+
_print('⚠️ packs.yml not found — skipping risk_class lint');
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
const violations = riskClassViolations(fs.readFileSync(PACKS_YML, 'utf-8'));
|
|
68
|
+
if (violations.length === 0) {
|
|
69
|
+
_print('✅ risk_class invariant OK — every high-risk pack is off-by-default + consent + lab');
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
_print(`❌ risk_class invariant — ${violations.length} violation(s):`);
|
|
73
|
+
for (const v of violations) _print(` - ${v.msg}`);
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
78
|
+
process.exit(main());
|
|
79
|
+
}
|
|
@@ -97,6 +97,39 @@ export function _spawn_subagent(
|
|
|
97
97
|
);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Count "findings" in an eval output for the `finding_floor` assertion
|
|
102
|
+
* (roadmap `road-to-operator-runtime-harvest`, Phase 1). With an explicit
|
|
103
|
+
* `pattern`, counts non-overlapping global regex matches; without one, counts
|
|
104
|
+
* markdown list-item lines (the default shape a skill's findings take).
|
|
105
|
+
*
|
|
106
|
+
* Deterministic on purpose: this only *counts*. The substantive judgement —
|
|
107
|
+
* is each match a real finding, and what should `n` be per host — is the
|
|
108
|
+
* calibration layer (Phase 1 gold set + per-host floor), which is gated on the
|
|
109
|
+
* P0 cross-model distributions and therefore NOT wired here yet. So
|
|
110
|
+
* `finding_floor` is available as a mechanism and exercised by fixtures, but is
|
|
111
|
+
* not an enforcing CI gate until calibrated.
|
|
112
|
+
*/
|
|
113
|
+
export function _count_findings(output: string, pattern?: string): number {
|
|
114
|
+
if (pattern !== undefined && pattern !== '') {
|
|
115
|
+
let re: RegExp;
|
|
116
|
+
try {
|
|
117
|
+
re = new RegExp(pattern, 'g');
|
|
118
|
+
} catch {
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
const m = output.match(re);
|
|
122
|
+
return m ? m.length : 0;
|
|
123
|
+
}
|
|
124
|
+
let count = 0;
|
|
125
|
+
for (const line of output.split('\n')) {
|
|
126
|
+
if (/^\s*(?:[-*+]|\d+[.)])\s+\S/.test(line)) {
|
|
127
|
+
count += 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return count;
|
|
131
|
+
}
|
|
132
|
+
|
|
100
133
|
export function _grade_assertions(
|
|
101
134
|
output: string,
|
|
102
135
|
run_dir: string,
|
|
@@ -119,6 +152,11 @@ export function _grade_assertions(
|
|
|
119
152
|
pass: null,
|
|
120
153
|
note: 'rubric grading requires sub-agent — fill in manually or via grader',
|
|
121
154
|
});
|
|
155
|
+
} else if (kind === 'finding_floor') {
|
|
156
|
+
const n = (a['n'] as number | undefined) ?? 1;
|
|
157
|
+
const pattern = a['pattern'] as string | undefined;
|
|
158
|
+
const count = _count_findings(output, pattern);
|
|
159
|
+
results.push({ kind, n, count, pass: count >= n });
|
|
122
160
|
} else {
|
|
123
161
|
results.push({ kind: kind ?? null, pass: false, note: `unknown assertion kind ${_pyRepr(kind)}` });
|
|
124
162
|
}
|
|
@@ -83,6 +83,18 @@
|
|
|
83
83
|
"description": "How strictly the agent must follow a user-provided prototype / mockup / design system. Consumed by the design-fidelity rule. strict = build 1:1, every visible deviation needs confirmation; structural = structure locked, silent gaps fillable with a stated assumption; hard-floor = any deviation is never autonomous."
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
},
|
|
87
|
+
"tokens": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"additionalProperties": true,
|
|
90
|
+
"description": "Token-spend governance for skills marked token_budget_class: rich. See token-budget-discipline rule.",
|
|
91
|
+
"properties": {
|
|
92
|
+
"rich_skills": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"enum": ["on", "ask", "off"],
|
|
95
|
+
"description": "Controls whether skills marked token_budget_class: rich may load in full (exempt from telegraph-speak and thin-projector trimming). on = allowed (default); off = fall back to standard condensed behavior; ask = surface an estimated token delta (tokens, not dollars) and ask the user once per session before loading."
|
|
96
|
+
}
|
|
97
|
+
}
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
100
|
}
|
|
@@ -182,6 +182,11 @@
|
|
|
182
182
|
"removable": {"type": "boolean", "default": false}
|
|
183
183
|
},
|
|
184
184
|
"description": "ADR-013 install hints (default-on at consumer install; user-removable)."
|
|
185
|
+
},
|
|
186
|
+
"token_budget_class": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"enum": ["lean", "standard", "rich"],
|
|
189
|
+
"description": "Token-cost class for this skill. `lean` (default): subject to telegraph-speak condensation and thin-projector trimming; optimize for <500 tokens. `standard`: balanced guidance, normal condensation. `rich`: exempt from telegraph-speak and thin-projector trimming; detailed examples preserved; eager-load eligible; ≤15% of skills in a suite may be `rich` (CI-enforced). A `rich` skill MUST carry a '## Why this skill is rich' section explaining the irreducible complexity that makes condensation harmful. Governed by `token-budget-discipline` rule + `tokens.rich_skills` consumer setting. See docs/guidelines/token-budget-governance.md."
|
|
185
190
|
}
|
|
186
191
|
}
|
|
187
192
|
}
|
|
@@ -1667,7 +1667,7 @@ export function validate_evals_json(skillPath: string): Issue[] {
|
|
|
1667
1667
|
);
|
|
1668
1668
|
return issues;
|
|
1669
1669
|
}
|
|
1670
|
-
const validKinds = ['contains', 'file_exists', 'rubric'];
|
|
1670
|
+
const validKinds = ['contains', 'file_exists', 'rubric', 'finding_floor'];
|
|
1671
1671
|
const validKindsSet = new Set(validKinds);
|
|
1672
1672
|
scenarios.forEach((scenario, idx) => {
|
|
1673
1673
|
const loc = `scenarios[${idx}]`;
|
|
@@ -1709,15 +1709,31 @@ export function validate_evals_json(skillPath: string): Issue[] {
|
|
|
1709
1709
|
);
|
|
1710
1710
|
return;
|
|
1711
1711
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
`${aLoc} (kind
|
|
1719
|
-
)
|
|
1720
|
-
|
|
1712
|
+
if (kind === 'finding_floor') {
|
|
1713
|
+
// finding_floor (run_skill_evals): `n` (number; runtime-defaults to
|
|
1714
|
+
// 1) and `pattern` (regex string) are both OPTIONAL — validate type
|
|
1715
|
+
// only when present, require neither.
|
|
1716
|
+
if ('n' in a && typeof a.n !== 'number') {
|
|
1717
|
+
issues.push(
|
|
1718
|
+
new Issue('warning', 'evals_json_assertion_field_type', `${aLoc} (kind=finding_floor) 'n' must be a number`),
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
if ('pattern' in a && typeof a.pattern !== 'string') {
|
|
1722
|
+
issues.push(
|
|
1723
|
+
new Issue('warning', 'evals_json_assertion_field_type', `${aLoc} (kind=finding_floor) 'pattern' must be a string`),
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
} else {
|
|
1727
|
+
const requiredField = { contains: 'value', file_exists: 'path', rubric: 'criterion' }[kind] as string;
|
|
1728
|
+
if (!(requiredField in a) || typeof a[requiredField] !== 'string') {
|
|
1729
|
+
issues.push(
|
|
1730
|
+
new Issue(
|
|
1731
|
+
'warning',
|
|
1732
|
+
'evals_json_assertion_missing_field',
|
|
1733
|
+
`${aLoc} (kind=${kind}) missing required string field '${requiredField}'`,
|
|
1734
|
+
),
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1721
1737
|
}
|
|
1722
1738
|
});
|
|
1723
1739
|
});
|