@event4u/agent-config 9.17.0 → 9.18.1

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.
Files changed (131) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +122 -171
  3. package/dist/agent-src/commands/challenge-me/vision.md +5 -0
  4. package/dist/agent-src/commands/evals/rule-compliance-audit.json +46 -0
  5. package/dist/agent-src/commands/feature/plan.md +20 -0
  6. package/dist/agent-src/commands/feature/roadmap.md +19 -0
  7. package/dist/agent-src/commands/pr/create.md +29 -0
  8. package/dist/agent-src/commands/roadmap/create.md +29 -0
  9. package/dist/agent-src/commands/rule-compliance-audit.md +28 -5
  10. package/dist/agent-src/contexts/execution/plan-confidence-gate.md +133 -0
  11. package/dist/agent-src/rules/active-remediation.md +2 -0
  12. package/dist/agent-src/rules/architecture.md +2 -0
  13. package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
  14. package/dist/agent-src/rules/brand-consistency.md +10 -62
  15. package/dist/agent-src/rules/brand-source-of-truth.md +62 -11
  16. package/dist/agent-src/rules/broken-access-control.md +4 -0
  17. package/dist/agent-src/rules/cli-output-handling.md +5 -0
  18. package/dist/agent-src/rules/code-comment-discipline.md +3 -0
  19. package/dist/agent-src/rules/commit-conventions.md +2 -0
  20. package/dist/agent-src/rules/cross-source-consistency.md +3 -0
  21. package/dist/agent-src/rules/design-fidelity.md +2 -0
  22. package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
  23. package/dist/agent-src/rules/docker-commands.md +4 -0
  24. package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
  25. package/dist/agent-src/rules/domain-safety-disclaimer.md +5 -2
  26. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  27. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +9 -0
  28. package/dist/agent-src/rules/image-likeness-and-rights.md +4 -0
  29. package/dist/agent-src/rules/improve-before-implement.md +4 -0
  30. package/dist/agent-src/rules/laravel-routing.md +4 -0
  31. package/dist/agent-src/rules/legal-safety-floor.md +3 -0
  32. package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
  33. package/dist/agent-src/rules/media-governance-routing.md +5 -0
  34. package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
  35. package/dist/agent-src/rules/no-roadmap-references.md +2 -0
  36. package/dist/agent-src/rules/notes-first-reasoning.md +2 -0
  37. package/dist/agent-src/rules/php-coding.md +2 -0
  38. package/dist/agent-src/rules/prefer-enums-over-literals.md +3 -0
  39. package/dist/agent-src/rules/provider-lifecycle-discipline.md +5 -0
  40. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +2 -0
  41. package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
  42. package/dist/agent-src/rules/rule-type-governance.md +2 -0
  43. package/dist/agent-src/rules/scale-discipline.md +3 -0
  44. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  45. package/dist/agent-src/rules/security-sensitive-stop.md +9 -2
  46. package/dist/agent-src/rules/senior-engineering-discipline.md +6 -0
  47. package/dist/agent-src/rules/skill-quality.md +2 -0
  48. package/dist/agent-src/rules/source-confidentiality.md +4 -0
  49. package/dist/agent-src/rules/source-discovery-gate.md +3 -0
  50. package/dist/agent-src/rules/source-of-truth.md +2 -0
  51. package/dist/agent-src/rules/strategy-safety-floor.md +2 -0
  52. package/dist/agent-src/rules/think-before-action.md +5 -0
  53. package/dist/agent-src/rules/ui-audit-gate.md +2 -0
  54. package/dist/agent-src/skills/design-intelligence/SKILL.md +6 -180
  55. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +100 -0
  56. package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +91 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +4 -141
  58. package/dist/agent-src/skills/design-review/references/review-communication.md +92 -0
  59. package/dist/agent-src/skills/design-review/references/verification-automation.md +61 -0
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -27
  61. package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +31 -0
  62. package/dist/agent-src/skills/fe-design/SKILL.md +4 -289
  63. package/dist/agent-src/skills/fe-design/references/design-patterns.md +227 -0
  64. package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +75 -0
  65. package/dist/agent-src/skills/roadmap-management/SKILL.md +10 -0
  66. package/dist/agent-src/skills/roadmap-writing/SKILL.md +12 -1
  67. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  68. package/dist/agent-src/templates/roadmaps.md +12 -0
  69. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
  70. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
  71. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
  72. package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
  73. package/dist/cli/registry.js +2 -0
  74. package/dist/cli/registry.js.map +1 -1
  75. package/dist/cli-delegate/chunk-AIIUU73N.js +2040 -0
  76. package/dist/cli-delegate/{chunk-IMSXPRVH.js → chunk-ELMFOQPW.js} +11 -0
  77. package/dist/cli-delegate/chunk-LF2KKJ4Q.js +183 -0
  78. package/dist/cli-delegate/cmd_explain.js +36 -36
  79. package/dist/cli-delegate/cmd_export.js +1 -1
  80. package/dist/cli-delegate/cmd_handoff.js +203 -2228
  81. package/dist/cli-delegate/cmd_prune.js +1 -1
  82. package/dist/cli-delegate/cmd_route_audit.js +249 -0
  83. package/dist/cli-delegate/cmd_route_explain.js +285 -0
  84. package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
  85. package/dist/cli-delegate/cmd_sync.js +1 -1
  86. package/dist/cli-delegate/cmd_uninstall.js +1 -1
  87. package/dist/cli-delegate/cmd_validate.js +1 -1
  88. package/dist/discovery/deprecation-report.md +1 -1
  89. package/dist/discovery/discovery-manifest.json +57 -57
  90. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  91. package/dist/discovery/discovery-manifest.summary.md +1 -1
  92. package/dist/discovery/orphan-report.md +1 -1
  93. package/dist/discovery/packs.json +2 -2
  94. package/dist/discovery/trust-report.md +1 -1
  95. package/dist/discovery/workspaces.json +2 -2
  96. package/dist/install/install.mjs +11 -0
  97. package/dist/mcp/registry-manifest.json +1 -1
  98. package/dist/mcp/server.json +2 -2
  99. package/dist/router.json +1 -1
  100. package/dist/server/schemas/settings.js +12 -0
  101. package/dist/server/schemas/settings.js.map +1 -1
  102. package/package.json +1 -1
  103. package/src/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
  104. package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
  105. package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
  106. package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
  107. package/src/config/agent-settings.template.yml +46 -0
  108. package/src/config/evaluator-budgets.json +3 -3
  109. package/src/config/gate-coverage.yml +44 -0
  110. package/src/scripts/_cli/cmd_explain.ts +41 -36
  111. package/src/scripts/_cli/cmd_route_audit.ts +290 -0
  112. package/src/scripts/_cli/cmd_route_explain.ts +269 -0
  113. package/src/scripts/_dispatch.bash +23 -0
  114. package/src/scripts/_lib/git_env.ts +40 -0
  115. package/src/scripts/_lib/md_table.ts +27 -0
  116. package/src/scripts/_lib/planning_settings.ts +43 -0
  117. package/src/scripts/_lib/release_highlights.ts +279 -0
  118. package/src/scripts/_lib/router_match.ts +301 -0
  119. package/src/scripts/annotate_r1_outcomes.ts +258 -0
  120. package/src/scripts/check_completion_review.ts +1322 -0
  121. package/src/scripts/check_release_highlights.ts +60 -152
  122. package/src/scripts/compile_router.ts +20 -3
  123. package/src/scripts/dispatch_r2_reviewer.ts +969 -0
  124. package/src/scripts/eval_ui_triviality.ts +156 -0
  125. package/src/scripts/lint_abstraction_thresholds.ts +3 -1
  126. package/src/scripts/lint_plan_risk_register.ts +931 -0
  127. package/src/scripts/lint_trigger_collisions.ts +257 -0
  128. package/src/scripts/release.ts +47 -13
  129. package/src/scripts/router_telemetry.ts +16 -290
  130. package/src/scripts/schemas/rule.schema.json +10 -0
  131. package/src/server/schemas/settings.ts +18 -0
@@ -11,8 +11,14 @@
11
11
  * commit types + rule/schema diffs, honest-null markers, removed public
12
12
  * surface) and FAILS when a populated generated category meets a `_none_`
13
13
  * curated field. It blocks the contradiction only — a human still writes the
14
- * prose; nothing here auto-formulates highlights, and a filled field is
15
- * never judged for quality.
14
+ * prose, and a filled field is never judged for quality.
15
+ *
16
+ * The classifier lives in `_lib/release_highlights.ts` and is shared with the
17
+ * generator, which now pre-fills each substantiated label instead of writing
18
+ * `_none_` everywhere. That removes the guaranteed first-run red (9.17.0,
19
+ * 9.18.0) without blunting this gate: a machine-written `_none_` was never the
20
+ * failure it was built for — a HUMAN writing one was (9.13.0, 9.14.0), and that
21
+ * still fails here. An unrewritten derived line warns; it never blocks.
16
22
  *
17
23
  * Derivation is deliberately conservative (documented per-label below):
18
24
  * a false red makes every release annoying; a miss only returns the head to
@@ -25,96 +31,41 @@
25
31
  * `--from` defaults to the latest reachable release tag before `--to`
26
32
  * (default HEAD). Exit codes: 0 plausible · 1 contradiction · 2 usage error.
27
33
  */
28
- import { spawnSync } from 'node:child_process';
29
34
  import * as fs from 'node:fs';
30
35
  import * as path from 'node:path';
31
36
  import process from 'node:process';
32
37
  import { fileURLToPath } from 'node:url';
33
38
 
39
+ import {
40
+ HEAD_LABELS,
41
+ HEAD_NONE,
42
+ type SpanCommit,
43
+ collect_span_commits,
44
+ derive_categories,
45
+ parse_git_log,
46
+ previous_release_tag,
47
+ stale_draft_labels,
48
+ } from './_lib/release_highlights.js';
34
49
  import { extract_changelog_section } from './_lib/release_material.js';
35
50
 
36
51
  const _HERE = fileURLToPath(import.meta.url);
37
52
  const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
38
53
 
39
- // The five curated labels, mirrored from release.ts RELEASE_HEAD_SECTIONS
40
- // (kept literal here so this checker has no import edge into the release
41
- // pipeline it audits; the unit tests pin the two lists against each other).
42
- export const HEAD_LABELS: readonly string[] = [
43
- 'Behaviour changes',
44
- 'Default changes + migration',
45
- 'Security and correctness',
46
- 'Honest nulls',
47
- 'Known limitations',
48
- ];
49
-
50
- export const HEAD_NONE = '_none_';
51
-
52
- export interface SpanCommit {
53
- sha: string;
54
- subject: string;
55
- body: string;
56
- /** `A` / `M` / `D` / `R…` status per touched path. */
57
- files: ReadonlyArray<{ status: string; path: string }>;
58
- breaking: boolean;
59
- }
60
-
61
- /** Public artefact trees whose deletions count as removed public surface. */
62
- const _PUBLIC_SURFACE_PREFIXES = [
63
- 'src/skills/',
64
- 'src/rules/',
65
- 'src/agent-src/commands/',
66
- 'src/domains/',
67
- ];
68
-
69
- const _RULE_OR_SCHEMA_PREFIXES = ['src/rules/', 'src/scripts/schemas/'];
70
-
71
- /**
72
- * Derive evidence per curated label from the span. Rules per label:
73
- *
74
- * - Security and correctness: conventional scope matching /secur/i, or the
75
- * whole word "security" in the subject.
76
- * - Behaviour changes: breaking (`!` / BREAKING CHANGE) commits, diffs
77
- * touching `src/rules/` or `src/scripts/schemas/`, and deletions under the
78
- * public artefact trees (removed public surface).
79
- * - Default changes + migration: subject carrying the whole word "default",
80
- * "migration", or "migrate".
81
- * - Honest nulls: subject or body carrying an "honest null" marker.
82
- * - Known limitations: never derived — pure prose, not gate-checkable.
83
- */
84
- export function derive_categories(commits: readonly SpanCommit[]): Record<string, string[]> {
85
- const out: Record<string, string[]> = {};
86
- for (const label of HEAD_LABELS) {
87
- out[label] = [];
88
- }
89
- const evidence = (c: SpanCommit): string => `${c.sha.slice(0, 7)} ${c.subject}`;
90
- for (const c of commits) {
91
- const scopeMatch = /^\w+\(([^)]*)\)!?:/u.exec(c.subject);
92
- const scope = scopeMatch ? scopeMatch[1]! : '';
93
- if (/secur/iu.test(scope) || /\bsecurity\b/iu.test(c.subject)) {
94
- out['Security and correctness']!.push(evidence(c));
95
- }
96
- const removedPublic = c.files.filter(
97
- (f) => f.status.startsWith('D') && _PUBLIC_SURFACE_PREFIXES.some((p) => f.path.startsWith(p)),
98
- );
99
- const ruleOrSchema = c.files.some((f) =>
100
- _RULE_OR_SCHEMA_PREFIXES.some((p) => f.path.startsWith(p)),
101
- );
102
- if (c.breaking || ruleOrSchema || removedPublic.length > 0) {
103
- const detail =
104
- removedPublic.length > 0
105
- ? `${evidence(c)} (removes ${removedPublic.map((f) => f.path).join(', ')})`
106
- : evidence(c);
107
- out['Behaviour changes']!.push(detail);
108
- }
109
- if (/\b(default|migration|migrate)\b/iu.test(c.subject)) {
110
- out['Default changes + migration']!.push(evidence(c));
111
- }
112
- if (/honest[ -]null/iu.test(`${c.subject}\n${c.body}`)) {
113
- out['Honest nulls']!.push(evidence(c));
114
- }
115
- }
116
- return out;
117
- }
54
+ // Labels and derivation live in `_lib/release_highlights.ts` — ONE definition
55
+ // shared with the generator that pre-fills the head. They used to be duplicated
56
+ // here to keep the checker independent of the release pipeline, and that
57
+ // independence is what produced the defect this gate now guards against from
58
+ // the other side: the generator wrote `_none_` into every field while this
59
+ // checker rejected exactly that, so every release PR was red on its first run.
60
+ // Sharing the classifier does not blunt the gate — it still blocks the failure
61
+ // it was built for, a human editing a substantiated line back to `_none_`.
62
+ export {
63
+ HEAD_LABELS,
64
+ HEAD_NONE,
65
+ derive_categories,
66
+ parse_git_log as _parse_git_log,
67
+ type SpanCommit,
68
+ };
118
69
 
119
70
  /**
120
71
  * Parse the curated head from a changelog section body. Returns null when
@@ -162,74 +113,6 @@ export function highlight_contradictions(
162
113
  return out;
163
114
  }
164
115
 
165
- // ─── git span collection (CLI only — the core above is pure) ────────────────
166
-
167
- const _RECORD = '\u001e';
168
- const _FIELD = '\u001f';
169
-
170
- export function _parse_git_log(raw: string): SpanCommit[] {
171
- const commits: SpanCommit[] = [];
172
- for (const record of raw.split(_RECORD)) {
173
- if (!record.trim()) {
174
- continue;
175
- }
176
- const [head, ...restLines] = record.split('\n');
177
- const parts = (head ?? '').split(_FIELD);
178
- if (parts.length < 3) {
179
- continue;
180
- }
181
- const sha = parts[0]!.trim();
182
- const subject = parts[1]!;
183
- const bodyParts: string[] = [parts.slice(2).join(_FIELD)];
184
- const files: Array<{ status: string; path: string }> = [];
185
- for (const line of restLines) {
186
- const m = /^([A-Z]\d*)\t(.+)$/u.exec(line);
187
- if (m) {
188
- // Renames carry two paths; the last tab field is the new path,
189
- // the first the old — record both so a rename out of a public
190
- // tree still counts its origin path.
191
- const segs = m[2]!.split('\t');
192
- for (const p of segs) {
193
- files.push({ status: m[1]!, path: p });
194
- }
195
- } else {
196
- // %b is multi-line — everything that is not a name-status
197
- // line is body continuation (honest-null markers live there).
198
- bodyParts.push(line);
199
- }
200
- }
201
- const body = bodyParts.join('\n');
202
- commits.push({
203
- sha,
204
- subject,
205
- body,
206
- files,
207
- breaking: /^\w+(\([^)]*\))?!:/u.test(subject) || /BREAKING CHANGE/u.test(body),
208
- });
209
- }
210
- return commits;
211
- }
212
-
213
- function _git(args: string[]): string {
214
- const r = spawnSync('git', args, { encoding: 'utf-8', cwd: REPO_ROOT, maxBuffer: 64 * 1024 * 1024 });
215
- if (r.status !== 0) {
216
- process.stderr.write(`git ${args.join(' ')} failed: ${r.stderr}\n`);
217
- process.exit(2);
218
- }
219
- return r.stdout;
220
- }
221
-
222
- function _collect_span(from: string, to: string): SpanCommit[] {
223
- const raw = _git([
224
- 'log',
225
- `${from}..${to}`,
226
- '--no-merges',
227
- '--name-status',
228
- '--format=%x1e%H%x1f%s%x1f%b',
229
- ]);
230
- return _parse_git_log(raw);
231
- }
232
-
233
116
  function main(argv: readonly string[]): number {
234
117
  let version: string | null = null;
235
118
  let from: string | null = null;
@@ -251,7 +134,13 @@ function main(argv: readonly string[]): number {
251
134
  return 2;
252
135
  }
253
136
  if (!from) {
254
- from = _git(['describe', '--tags', '--abbrev=0', '--match', '[0-9]*.[0-9]*.[0-9]*', `${to}^`]).trim();
137
+ from = previous_release_tag(to, REPO_ROOT);
138
+ if (!from) {
139
+ process.stderr.write(
140
+ `no release tag reachable before ${to} — pass --from explicitly\n`,
141
+ );
142
+ return 2;
143
+ }
255
144
  }
256
145
  const section = extract_changelog_section(fs.readFileSync(changelogPath, 'utf-8'), version);
257
146
  if (!section) {
@@ -263,7 +152,26 @@ function main(argv: readonly string[]): number {
263
152
  process.stdout.write(`ℹ️ no curated head in the ${version} section — nothing to check\n`);
264
153
  return 0;
265
154
  }
266
- const derived = derive_categories(_collect_span(from, to));
155
+ let span: SpanCommit[];
156
+ try {
157
+ span = collect_span_commits(from, to, REPO_ROOT);
158
+ } catch (err) {
159
+ process.stderr.write(`${(err as Error).message}\n`);
160
+ return 2;
161
+ }
162
+ // A generator-derived line that nobody rewrote is a prose gap, never a
163
+ // contradiction: the line's evidence is true, it is just unpolished. Warn
164
+ // so the omission is visible, and keep the exit code owned solely by the
165
+ // `_none_` check — a warning that reds the build is the guaranteed-red
166
+ // failure mode this whole change exists to remove.
167
+ const drafts = stale_draft_labels(curated);
168
+ if (drafts.length > 0) {
169
+ process.stdout.write(
170
+ `⚠️ auto-derived head line(s) not yet rewritten for ${version}: ` +
171
+ `${drafts.join(', ')} — advisory, not blocking.\n`,
172
+ );
173
+ }
174
+ const derived = derive_categories(span);
267
175
  const contradictions = highlight_contradictions(curated, derived);
268
176
  if (contradictions.length === 0) {
269
177
  process.stdout.write(`✅ curated head plausible for ${version} (span ${from}..${to})\n`);
@@ -61,10 +61,17 @@ export { COMPILE_TIME_TOGGLES };
61
61
 
62
62
  // Maps legacy tier values to the router-canonical names. See
63
63
  // docs/contracts/rule-router.md § Backward compatibility.
64
+ // `2b` → tier-2 is a recorded decision (2026-08-04): the 21 rules tagged 2b
65
+ // are tier-2 deliberately — before this entry they reached tier-2 only via a
66
+ // silent fallthrough that also swallowed typos. `safety-floor` is deliberately
67
+ // NOT mapped: it is documentation-only on the always-typed trio (which
68
+ // short-circuits to kernel before this map is consulted); on any other rule it
69
+ // is a contract violation and must fail compilation.
64
70
  const LEGACY_TIER_MAP: Record<string, string> = {
65
71
  '1': 'tier-1',
66
72
  '2': 'tier-2',
67
73
  '2a': 'tier-2',
74
+ '2b': 'tier-2',
68
75
  '3': 'tier-1',
69
76
  'mechanical-already': 'tier-1',
70
77
  kernel: 'kernel',
@@ -93,11 +100,21 @@ function _parse_frontmatter(text: string): JsonObject {
93
100
  : {};
94
101
  }
95
102
 
96
- function _resolve_tier(rule_type: string, raw_tier: string): string {
103
+ export function _resolve_tier(rule_type: string, raw_tier: string, rule_id: string): string {
97
104
  if (rule_type === 'always') {
98
105
  return 'kernel';
99
106
  }
100
- return LEGACY_TIER_MAP[String(raw_tier)] ?? 'tier-2';
107
+ const mapped = LEGACY_TIER_MAP[String(raw_tier)];
108
+ if (mapped === undefined) {
109
+ // A typo'd (or unmapped) tier used to downgrade silently to tier-2 —
110
+ // a zero-injection failure nobody sees. Fail the compile instead.
111
+ throw new Error(
112
+ `compile_router: rule '${rule_id}' has unknown tier '${raw_tier}' — `
113
+ + `allowed values: ${Object.keys(LEGACY_TIER_MAP).sort().join(', ')} `
114
+ + `(or type: always, where tier is inert)`,
115
+ );
116
+ }
117
+ return mapped;
101
118
  }
102
119
 
103
120
  function _normalize_trigger(item: Json): JsonObject | null {
@@ -205,7 +222,7 @@ function _collect(): JsonObject {
205
222
  if (rule_type === 'manual') {
206
223
  continue;
207
224
  }
208
- const tier = _resolve_tier(rule_type, String(fm['tier'] ?? ''));
225
+ const tier = _resolve_tier(rule_type, String(fm['tier'] ?? ''), rule_id);
209
226
  if (!ALLOWED_TIERS.has(tier)) {
210
227
  continue;
211
228
  }