@event4u/agent-config 9.36.0 → 10.1.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.
Files changed (89) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +117 -2
  3. package/agents/templates/.ai-council.yml.example +31 -51
  4. package/dist/agent-src/commands/analyze/conformance.md +15 -4
  5. package/dist/agent-src/rules/session-canary.md +28 -0
  6. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +17 -0
  7. package/dist/agent-src/skills/adr-create/SKILL.md +5 -0
  8. package/dist/agent-src/skills/check-refs/SKILL.md +5 -0
  9. package/dist/agent-src/skills/lint-skills/SKILL.md +5 -0
  10. package/dist/agent-src/skills/md-language-check/SKILL.md +5 -0
  11. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  12. package/dist/cli-delegate/{chunk-SFGARMAB.js → chunk-2H5SE7DU.js} +24 -4
  13. package/dist/cli-delegate/{chunk-U7CMAIOC.js → chunk-3JUTT26I.js} +1 -1
  14. package/dist/cli-delegate/{chunk-JP53LNVT.js → chunk-HJSKTMIF.js} +6 -14
  15. package/dist/cli-delegate/{chunk-QEEB4LHO.js → chunk-LRXJK6GN.js} +1 -1
  16. package/dist/cli-delegate/{chunk-NR7HSN3P.js → chunk-NX5AXSLD.js} +3 -3
  17. package/dist/cli-delegate/{chunk-AG47LAGQ.js → chunk-TVGXH7VA.js} +1 -1
  18. package/dist/cli-delegate/{chunk-55RI5UXK.js → chunk-XT2YTJCZ.js} +22 -18
  19. package/dist/cli-delegate/{chunk-JEJABGKB.js → chunk-XTC5ARB6.js} +16 -12
  20. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  21. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  22. package/dist/cli-delegate/cmd_conformance.js +1037 -196
  23. package/dist/cli-delegate/cmd_doctor.js +3 -3
  24. package/dist/cli-delegate/cmd_explain.js +2 -2
  25. package/dist/cli-delegate/cmd_export.js +4 -4
  26. package/dist/cli-delegate/cmd_handoff.js +3 -3
  27. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  28. package/dist/cli-delegate/cmd_migrate.js +2 -2
  29. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  30. package/dist/cli-delegate/cmd_prune.js +4 -4
  31. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  32. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  33. package/dist/cli-delegate/cmd_session_recycle.js +1 -1
  34. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  35. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  36. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  37. package/dist/cli-delegate/cmd_sync.js +4 -4
  38. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  39. package/dist/cli-delegate/cmd_update.js +1 -1
  40. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  41. package/dist/cli-delegate/cmd_validate.js +4 -4
  42. package/dist/cli-delegate/cmd_versions.js +1 -1
  43. package/dist/discovery/deprecation-report.md +1 -1
  44. package/dist/discovery/discovery-manifest.json +8 -8
  45. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  46. package/dist/discovery/discovery-manifest.summary.md +1 -1
  47. package/dist/discovery/dormancy-report.md +1 -1
  48. package/dist/discovery/orphan-report.md +1 -1
  49. package/dist/discovery/packs.json +2 -2
  50. package/dist/discovery/trust-report.md +1 -1
  51. package/dist/discovery/workspaces.json +2 -2
  52. package/dist/hooks/dispatch.js +125 -89
  53. package/dist/install/install.mjs +22 -26
  54. package/dist/mcp/registry-manifest.json +1 -1
  55. package/dist/mcp/server.json +2 -2
  56. package/dist/mcp/server.mjs +1579 -616
  57. package/dist/scripts/_lib/agent_settings.js +39 -25
  58. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  59. package/dist/scripts/condense.js +15 -2
  60. package/dist/scripts/condense.js.map +1 -1
  61. package/dist/server/routes/wizard.js +23 -3
  62. package/dist/server/routes/wizard.js.map +1 -1
  63. package/dist/server/schemas/settings.js +6 -6
  64. package/dist/server/schemas/settings.js.map +1 -1
  65. package/docs/contracts/settings-classes.md +14 -9
  66. package/package.json +1 -1
  67. package/src/agent-src/scripts/archive_completed_roadmaps.ts +17 -0
  68. package/src/config/agent-settings.template.yml +6 -36
  69. package/src/config/ci-local-parity.yml +44 -0
  70. package/src/scripts/_lib/agent_settings.ts +39 -25
  71. package/src/scripts/_lib/environment_detector.ts +52 -1
  72. package/src/scripts/_lib/untrusted_content.test.ts +175 -0
  73. package/src/scripts/_lib/untrusted_content.ts +184 -0
  74. package/src/scripts/ai_council/config.ts +62 -24
  75. package/src/scripts/before_complete_hook.ts +39 -0
  76. package/src/scripts/check_bridge_derivation.ts +89 -3
  77. package/src/scripts/check_ci_local_parity.ts +74 -0
  78. package/src/scripts/check_references.ts +15 -1
  79. package/src/scripts/condense.ts +16 -2
  80. package/src/scripts/conformance_scan.ts +200 -9
  81. package/src/scripts/council_cli.ts +95 -3
  82. package/src/scripts/hook_manifest.yaml +12 -6
  83. package/src/scripts/hooks/block_no_verify.ts +82 -9
  84. package/src/scripts/hooks/turn_end_gate_hook.ts +138 -105
  85. package/src/scripts/probe_promissory_closing.ts +180 -0
  86. package/src/scripts/probe_session_canary.ts +180 -0
  87. package/src/scripts/schemas/skill.schema.json +42 -0
  88. package/src/scripts/skill_linter.ts +57 -2
  89. package/src/server/schemas/settings.ts +6 -14
@@ -33,6 +33,48 @@
33
33
  "maxLength": 500,
34
34
  "description": "Agent-Skills spec field (optional): machine-readable declaration of environment requirements — system packages, network access, product/host constraints. Mirrors the public spec so media/doc skills can state requirements outside prose."
35
35
  },
36
+ "runtime_requires": {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "description": "Structured runtime prerequisites, in the form `doctor`/`preflight` can actually probe. The free-text `compatibility` field above states requirements for a human reader; this states them for a machine, and the two coexist deliberately — `compatibility` mirrors the public Agent-Skills spec and is not replaced here. Mandatory for an external `execution.handler` (shell/node/php), which cannot run without declared dependencies; meaningless for `internal`, which by definition needs no external binary. NOT named `requires`: that key is taken by ADR-015 pack-dependency edges (a list of pack ids, validated in build_discovery_manifest.ts), and reusing it makes every skill carrying one unassignable in the discovery manifest.",
40
+ "properties": {
41
+ "bins": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string",
45
+ "minLength": 1
46
+ },
47
+ "description": "Executables that must resolve on PATH (e.g. `python3`, `curl`). Probed by name, never by version — a version constraint belongs in the skill body where it can explain itself."
48
+ },
49
+ "env": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string",
53
+ "pattern": "^[A-Z][A-Z0-9_]*$"
54
+ },
55
+ "description": "Environment variable NAMES that must be set. Names only — a value here would be a credential in a tracked file (secret-vcs-guard)."
56
+ },
57
+ "primary_env": {
58
+ "type": "string",
59
+ "pattern": "^[A-Z][A-Z0-9_]*$",
60
+ "description": "The one variable from `env` whose absence makes the skill unusable rather than degraded, so a doctor report can distinguish a hard block from a partial one. Must also appear in `env`. HALF-ENFORCED, stated plainly: the `dependencies` keyword below requires `env` to be present whenever `primary_env` is, which is the part JSON Schema can express. That the named variable is a MEMBER of `env` is NOT checked anywhere — the linter reads frontmatter by regex, and a fragile pattern on a blocking rule is worse than an honest gap. Zero skills use the field today; the membership check belongs in the doctor wiring (Phase 1, gated on S0.3), where the value is parsed rather than matched."
61
+ },
62
+ "network": {
63
+ "type": "array",
64
+ "items": {
65
+ "type": "string",
66
+ "minLength": 1
67
+ },
68
+ "description": "Egress hostnames the skill contacts, checked against the egress allowlist. An empty array is a positive claim of no network access and is NOT the same as omitting the key."
69
+ }
70
+ },
71
+ "dependencies": {
72
+ "primary_env": [
73
+ "env"
74
+ ]
75
+ },
76
+ "$comment": "road-to-skill-ecosystem-executable-payloads Phase 1 (defect D2): `compatibility` is free text used by 2 skills, so cmd_doctor.ts / cmd_preflight.ts had nothing structured to verify. Named `runtime_requires` because `requires` is reserved for ADR-015 pack edges. The `dependencies` keyword closes the half of the primary_env invariant a schema can express; R2 review finding 1 flagged the fully-unenforced version as the same ADR-127 shape this roadmap is closing."
77
+ },
36
78
  "provenance": {
37
79
  "type": "string",
38
80
  "enum": [
@@ -230,6 +230,30 @@ const KERNEL_RULE_IDS = new Set([
230
230
  export const VALID_EXECUTION_TYPES = new Set(['manual', 'assisted', 'automated']);
231
231
  export const VALID_EXECUTION_HANDLERS = new Set(['none', 'shell', 'php', 'node', 'internal']);
232
232
  const VALID_EXECUTION_SAFETY_MODES = new Set(['strict']);
233
+ /**
234
+ * Handlers that shell out of this process and therefore depend on something the
235
+ * host must already have. `internal` is deliberately absent: it runs in-process
236
+ * and by definition needs no external binary, so demanding a `requires` block
237
+ * from it would produce a pro-forma declaration rather than a checkable fact.
238
+ */
239
+ const EXTERNAL_EXECUTION_HANDLERS = new Set(['shell', 'php', 'node']);
240
+ /**
241
+ * Top-level `runtime_requires:` declaration (sibling of `execution:`, not a field
242
+ * inside it). Deliberately NOT `requires:` — that key is ADR-015 pack-dependency
243
+ * edges (a list of pack ids), and a skill carrying an object there is rejected by
244
+ * `build_discovery_manifest.ts` as unassignable.
245
+ *
246
+ * Matches block style (`runtime_requires:` then indented keys) AND flow style
247
+ * (`runtime_requires: {bins: [...]}`). The block-only version was an R2 review
248
+ * finding: flow style is valid YAML and valid against the schema, so erroring on
249
+ * it told the author to add a declaration they already had, with no suppression
250
+ * path. The neighbouring `^execution:\s*$` is block-only by house convention, but
251
+ * its consequence is a silent skip rather than a hard error.
252
+ *
253
+ * `[ \t]*` rather than `\s*`: `\s` matches a newline, so the looser form could
254
+ * span lines and accept a bare key whose value sits somewhere below it.
255
+ */
256
+ const RUNTIME_REQUIRES_BLOCK_PATTERN = /^runtime_requires:[ \t]*(\{.*)?$/m;
233
257
  const VALID_EXECUTION_FIELDS = new Set([
234
258
  'type',
235
259
  'handler',
@@ -1264,7 +1288,14 @@ function lint_wing4_boundaries(text: string): Issue[] {
1264
1288
  return issues;
1265
1289
  }
1266
1290
 
1267
- function lint_execution_metadata(execution: ExecutionBlock): Issue[] {
1291
+ /**
1292
+ * `frontmatter` is required, not defaulted. An R2 review finding: with
1293
+ * `frontmatter = ''` an omitted argument makes the runtime-requires check
1294
+ * FABRICATE its error rather than skip it, which is the wrong failure direction
1295
+ * for an optional parameter — a future caller that forgets it gets a confident
1296
+ * error about a declaration it never looked for.
1297
+ */
1298
+ function lint_execution_metadata(execution: ExecutionBlock, frontmatter: string): Issue[] {
1268
1299
  const issues: Issue[] = [];
1269
1300
 
1270
1301
  const execType = execution.type;
@@ -1374,6 +1405,30 @@ function lint_execution_metadata(execution: ExecutionBlock): Issue[] {
1374
1405
  }
1375
1406
  }
1376
1407
 
1408
+ // An external handler that actually declares a command depends on binaries or
1409
+ // env the host may not have; without a `runtime_requires` block,
1410
+ // `doctor`/`preflight` have nothing to probe and the failure surfaces mid-run
1411
+ // instead. Gated on a declared `command:` on purpose — a `handler: shell` skill
1412
+ // with no command is advisory prose, and demanding requirements from it would be
1413
+ // a pro-forma field.
1414
+ if (
1415
+ typeof handler === 'string' &&
1416
+ EXTERNAL_EXECUTION_HANDLERS.has(handler) &&
1417
+ Array.isArray(command) &&
1418
+ command.length > 0 &&
1419
+ !RUNTIME_REQUIRES_BLOCK_PATTERN.test(frontmatter)
1420
+ ) {
1421
+ issues.push(
1422
+ new Issue(
1423
+ 'error',
1424
+ 'missing_runtime_requires',
1425
+ `execution.handler '${handler}' declares a command but the skill has no top-level ` +
1426
+ "'runtime_requires:' block — declare bins/env/network so doctor and preflight can " +
1427
+ 'verify the runtime before the command runs',
1428
+ ),
1429
+ );
1430
+ }
1431
+
1377
1432
  const unknown = Object.keys(execution).filter((k) => !VALID_EXECUTION_FIELDS.has(k));
1378
1433
  for (const field of unknown.sort()) {
1379
1434
  issues.push(
@@ -1530,7 +1585,7 @@ export function lint_skill(p: string, text: string, absPath: string | null = nul
1530
1585
 
1531
1586
  const execution = parseExecutionBlock(frontmatter);
1532
1587
  if (execution !== null) {
1533
- issues.push(...lint_execution_metadata(execution));
1588
+ issues.push(...lint_execution_metadata(execution, frontmatter));
1534
1589
  }
1535
1590
 
1536
1591
  const tierMatch = TIER_PATTERN.exec(frontmatter);
@@ -529,20 +529,12 @@ export const settingsSchema = z.object({
529
529
  'PreToolUse code-graph nudge (ADR-124 Phase 4). Default off. When on AND a native code-graph cache or a consumer-shipped graph.json/SCIP index is present, warns once per session (never blocks) as the agent is about to Grep/Glob or Read a source file — query the graph first for who-calls/where-used/impact questions (or rebuild if stale, build if absent). Source G’s strict block-first-read mode is deliberately un-ported.',
530
530
  ),
531
531
  }).default({}),
532
- turn_end_gate: z.object({
533
- enabled: z.boolean().default(false).describe(
534
- 'Stop-slot turn-end gate (road-to-conformance-round5 Phase 3). Default off, and it is the only concern that can REFUSE a turn-end rather than a tool call — so it soaks behind an explicit opt-in before it binds. Round 5 measured the reason: both blocking carriers reached zero violations, neither advisory carrier did, and 19 wrong-language replies survived a pin that had fired 26-35 seconds earlier. A refused turn continues in the SAME turn and is never refused twice.',
535
- ),
536
- promissory: z.boolean().default(true).describe(
537
- 'Detector A of the turn-end gate: refuse a turn whose closing paragraph promises work not yet performed while asking the user nothing (20 measured occurrences). No fire rate is quoted here on purpose: the measured rate moved twice while the instrument itself was being corrected, so a number in a shipped description would be a moving target. Re-derive it with `measure-turn-end-gate --store <transcript dir>` against your own corpus before arming the gate. Inert while hooks.turn_end_gate.enabled is false.',
538
- ),
539
- language: z.boolean().default(true).describe(
540
- 'Detector B of the turn-end gate: refuse a turn whose reply is not in the pinned language (19 measured occurrences). Fenced code, inline code, quoted tool output, tables, URLs and paths are stripped first, and the remainder is then scored LEAD-FIRST by the same classifier that sets the pin — so the verdict usually comes from the reply opening, not from all of it. Sharing that classifier is deliberate: it stops the pin and the detector disagreeing about a turn. Accepted opt-in spellings for the switches below include YAML true/false and yes/no/on/off. Inert while hooks.turn_end_gate.enabled is false.',
541
- ),
542
- verification: z.boolean().default(true).describe(
543
- 'Detector C of the turn-end gate: refuse a turn that changed a file and then ran nothing that could have checked it — no test, type-check, lint or build call follows the LAST edit. Ordering is the point: a run before the final edit did not exercise it, which is the freshness clause verify-before-complete states. Read off the turn tool calls, not the prose, because a reply cannot say whether an edit was verified. Deliberately narrow on what counts as verification — a missed detection costs one unguarded turn, a false refusal teaches you to switch the gate off. No fire rate is quoted: none has been measured yet. Inert while hooks.turn_end_gate.enabled is false.',
544
- ),
545
- }).default({}),
532
+ // `turn_end_gate` is deliberately ABSENT. The stop-slot turn-end gate is
533
+ // always armed (2026-08-12) and has no settings surface: whether it
534
+ // fires is decided by each detector's own trigger conditions, not by a
535
+ // flag. A leftover `hooks.turn_end_gate.*` block from an older install
536
+ // warns once on stderr and is ignored — see REMOVED_KEYS in
537
+ // `src/scripts/_lib/agent_settings.ts`.
546
538
  }),
547
539
  decision_engine: z.object({
548
540
  surface_traces: z.boolean().default(false).describe(