@event4u/agent-config 9.13.0 → 9.15.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 +1 -1
- package/CHANGELOG.md +113 -67
- package/README.md +9 -1
- package/dist/agent-src/commands/agents/audit.md +7 -7
- package/dist/agent-src/commands/agents/optimize.md +1 -1
- package/dist/agent-src/commands/analyze/reference-repo.md +1 -1
- package/dist/agent-src/commands/chat-history.md +1 -0
- package/dist/agent-src/commands/context.md +1 -0
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/ghostwriter.md +1 -1
- package/dist/agent-src/commands/memory.md +2 -1
- package/dist/agent-src/commands/module.md +1 -0
- package/dist/agent-src/commands/optimize/agents-dir.md +1 -1
- package/dist/agent-src/commands/optimize/deep.md +150 -0
- package/dist/agent-src/commands/optimize/skills.md +5 -5
- package/dist/agent-src/commands/optimize.md +12 -6
- package/dist/agent-src/commands/override.md +1 -0
- package/dist/agent-src/commands/prediction-pool.md +4 -4
- package/dist/agent-src/commands/research/deep.md +1 -1
- package/dist/agent-src/commands/roadmap.md +2 -1
- package/dist/agent-src/commands/rule-compliance-audit.md +1 -1
- package/dist/agent-src/commands/tdd.md +1 -0
- package/dist/agent-src/commands/tests.md +1 -0
- package/dist/agent-src/commands/upstream-contribute.md +5 -5
- package/dist/agent-src/commands/video/from-script.md +1 -1
- package/dist/agent-src/commands/video/from-song.md +1 -1
- package/dist/agent-src/commands/video/scene.md +1 -1
- package/dist/agent-src/commands/video/stitch.md +1 -1
- package/dist/agent-src/commands/video/storyboard.md +1 -1
- package/dist/agent-src/commands/worktree/create.md +2 -1
- package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +5 -5
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -3
- package/dist/agent-src/contexts/contracts/emergency-triage-block.md +2 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +4 -3
- package/dist/agent-src/contexts/execution/subagent-routing.md +19 -0
- package/dist/agent-src/contexts/override-system.md +1 -1
- package/dist/agent-src/ghostwriter/fictional-fixture-v1.md +1 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +2 -1
- package/dist/agent-src/rules/brand-consistency.md +1 -0
- package/dist/agent-src/rules/brand-source-of-truth.md +1 -0
- package/dist/agent-src/rules/code-comment-discipline.md +2 -0
- package/dist/agent-src/rules/communication-through-line.md +1 -0
- package/dist/agent-src/rules/content-quoting-floor.md +1 -0
- package/dist/agent-src/rules/cross-source-consistency.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +1 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +1 -0
- package/dist/agent-src/rules/external-reference-deep-dive.md +1 -0
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/invite-challenge.md +1 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +4 -3
- package/dist/agent-src/rules/media-sync-ground-truth.md +1 -0
- package/dist/agent-src/rules/no-attribution-footers.md +1 -0
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +1 -0
- package/dist/agent-src/rules/no-pr-progress-comments.md +1 -0
- package/dist/agent-src/rules/onboarding-gate.md +1 -0
- package/dist/agent-src/rules/output-discipline.md +1 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +1 -0
- package/dist/agent-src/rules/preservation-guard.md +1 -0
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +1 -0
- package/dist/agent-src/rules/role-mode-adherence.md +1 -0
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +1 -0
- package/dist/agent-src/rules/session-canary.md +9 -2
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/source-of-truth.md +1 -0
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -0
- package/dist/agent-src/rules/think-before-action.md +1 -0
- package/dist/agent-src/rules/token-budget-discipline.md +1 -0
- package/dist/agent-src/rules/token-efficiency.md +1 -0
- package/dist/agent-src/rules/token-optimizer-maintenance.md +5 -5
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/skills/adr-create/SKILL.md +1 -1
- package/dist/agent-src/skills/check-refs/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +1 -1
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +1 -1
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/github-ci/SKILL.md +1 -0
- package/dist/agent-src/skills/guideline-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/lint-skills/SKILL.md +1 -1
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/roadmap-management/SKILL.md +8 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +4 -4
- package/dist/agent-src/skills/token-optimizer/SKILL.md +4 -4
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +6 -6
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +25 -0
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/command.md +1 -1
- package/dist/agent-src/templates/copilot-instructions.md +3 -3
- package/dist/agent-src/templates/rule.md +2 -2
- package/dist/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
- package/dist/agent-src/templates/skill-archive-note.md +5 -5
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/agent-config.js +66 -19
- package/dist/cli/agent-config.js.map +1 -1
- package/dist/cli/main.js +9 -4
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/python/workspace_drive.js +2 -0
- package/dist/cli/python/workspace_drive.js.map +1 -1
- package/dist/cli/python/workspace_drive_health.js +2 -0
- package/dist/cli/python/workspace_drive_health.js.map +1 -1
- package/dist/cli/python/workspace_hosts.js +2 -0
- package/dist/cli/python/workspace_hosts.js.map +1 -1
- package/dist/cli/python/workspace_sessions.js +2 -0
- package/dist/cli/python/workspace_sessions.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-A3HJ6NTI.js → chunk-63WSP6YZ.js} +2 -1
- package/dist/cli-delegate/{chunk-EJYIGZ3T.js → chunk-BKO2AZ7Z.js} +1 -1
- package/dist/cli-delegate/{chunk-QFKQLQ7X.js → chunk-H574KOUH.js} +340 -462
- package/dist/cli-delegate/chunk-NXFWFAYV.js +339 -0
- package/dist/cli-delegate/{chunk-TEGJU2JX.js → chunk-ZXXJLL5K.js} +2 -2
- package/dist/cli-delegate/cmd_conformance.js +29 -23
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +163 -103
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +729 -430
- package/dist/install/install.mjs +700 -625
- package/dist/install/rule_scope.js +18 -2
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +564 -424
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/claude_settings_hooks.js +30 -5
- package/dist/scripts/_lib/claude_settings_hooks.js.map +1 -1
- package/dist/scripts/_lib/scoped_projection.js +223 -0
- package/dist/scripts/_lib/scoped_projection.js.map +1 -0
- package/dist/scripts/_lib/surface_tiers.js +125 -0
- package/dist/scripts/_lib/surface_tiers.js.map +1 -0
- package/dist/scripts/_lib/token_count.js +166 -0
- package/dist/scripts/_lib/token_count.js.map +1 -0
- package/dist/scripts/_lib/trigger_eval_floors.js +8 -0
- package/dist/scripts/_lib/trigger_eval_floors.js.map +1 -1
- package/dist/scripts/condense.js +139 -9
- package/dist/scripts/condense.js.map +1 -1
- package/dist/scripts/project_thin_rules.js +450 -0
- package/dist/scripts/project_thin_rules.js.map +1 -0
- package/dist/server/routes/workspace.js +2 -0
- package/dist/server/routes/workspace.js.map +1 -1
- package/dist/server/schemas/settings.js +9 -3
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/ui/assets/index-DJY_vQVn.js +40 -0
- package/dist/ui/assets/index-DJY_vQVn.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/package.json +11 -11
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
- package/src/config/agent-settings.template.yml +59 -11
- package/src/config/ci-local-parity.yml +8 -0
- package/src/config/discovery/unassigned-artefacts.yml +23 -25
- package/src/config/evaluator-budgets.json +35 -5
- package/src/config/gate-coverage.yml +147 -0
- package/src/config/gate-violation-baselines.json +25 -0
- package/src/install/rule_scope.ts +27 -2
- package/src/scripts/_cli/cmd_conformance.ts +13 -24
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +30 -4
- package/src/scripts/_lib/exec_evidence.ts +5 -0
- package/src/scripts/_lib/gate_baseline.ts +213 -0
- package/src/scripts/_lib/scoped_projection.ts +262 -0
- package/src/scripts/_lib/tier_budget_routing.ts +234 -0
- package/src/scripts/_lib/tool_adapter_registry.ts +8 -1
- package/src/scripts/_lib/trigger_eval_floors.ts +9 -0
- package/src/scripts/_lib/trigger_routers.ts +17 -5
- package/src/scripts/adr/regenerate_index.ts +4 -3
- package/src/scripts/ai-video/lib/parse-blueprint.sh +1 -1
- package/src/scripts/ai_council/compile_corpus.ts +1 -1
- package/src/scripts/audit_cloud_compatibility.ts +37 -2
- package/src/scripts/audit_initial_context.ts +53 -19
- package/src/scripts/audit_likelihood.ts +31 -2
- package/src/scripts/audit_user_type_axis.ts +58 -11
- package/src/scripts/bench_hook_latency.ts +172 -41
- package/src/scripts/build_mcp_catalog.ts +12 -1
- package/src/scripts/check_always_budget.ts +122 -11
- package/src/scripts/check_artefact_count_messaging.ts +128 -15
- package/src/scripts/check_augment_description_cap.ts +24 -3
- package/src/scripts/check_ci_strict_superset.ts +150 -0
- package/src/scripts/check_cluster_patterns.ts +100 -0
- package/src/scripts/check_consumer_scope_flip.ts +26 -4
- package/src/scripts/check_evaluator_budgets.ts +198 -19
- package/src/scripts/check_gate_coverage.ts +337 -1
- package/src/scripts/check_generator_output_coverage.ts +2 -1
- package/src/scripts/check_iron_law_prominence.ts +1 -1
- package/src/scripts/check_kernel_rule_bundle.ts +1 -1
- package/src/scripts/check_no_new_legacy_path.ts +167 -3
- package/src/scripts/check_pack_size.ts +18 -4
- package/src/scripts/check_portability.ts +37 -7
- package/src/scripts/check_references.ts +19 -3
- package/src/scripts/check_release_pr_shape.ts +13 -0
- package/src/scripts/check_token_regression.ts +9 -2
- package/src/scripts/condense.ts +155 -12
- package/src/scripts/cost/budget.mjs +63 -2
- package/src/scripts/count_scoped_projection.ts +104 -0
- package/src/scripts/evaluator_umbrella.sh +34 -1
- package/src/scripts/generate_capability_matrix.ts +8 -0
- package/src/scripts/generate_router_coverage_from_matrix.ts +155 -0
- package/src/scripts/hook_manifest.yaml +17 -3
- package/src/scripts/hooks/block_config_weakening.ts +337 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/probe_throttle.ts +75 -0
- package/src/scripts/install-hooks.sh +24 -2
- package/src/scripts/install.ts +15 -92
- package/src/scripts/lint_agents_md.ts +9 -3
- package/src/scripts/lint_archived_skills.ts +1 -1
- package/src/scripts/lint_artefact_frontmatter.ts +185 -37
- package/src/scripts/lint_command_routing.ts +21 -52
- package/src/scripts/lint_command_verbs.ts +47 -28
- package/src/scripts/lint_context_spine_usage.ts +38 -12
- package/src/scripts/lint_framework_leakage.ts +25 -6
- package/src/scripts/lint_handoffs.ts +49 -2
- package/src/scripts/lint_media_policy_linkage.ts +62 -30
- package/src/scripts/lint_namespace.ts +92 -7
- package/src/scripts/lint_new_skill_gate.ts +39 -31
- package/src/scripts/lint_originality_shingles.ts +7 -1
- package/src/scripts/lint_override_kernel_guard.ts +21 -3
- package/src/scripts/lint_pack_boundaries.ts +461 -91
- package/src/scripts/lint_pack_dependencies.ts +24 -57
- package/src/scripts/lint_persona_governance.ts +1 -1
- package/src/scripts/lint_role_experiences.ts +34 -5
- package/src/scripts/lint_trigger_precision.ts +142 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +12 -201
- package/src/scripts/mcp_server/tools.ts +1 -1
- package/src/scripts/prepack-check.mjs +40 -1
- package/src/scripts/prepack_router_targets.d.mts +7 -0
- package/src/scripts/prepack_router_targets.mjs +93 -0
- package/src/scripts/print_required_checks.ts +72 -18
- package/src/scripts/profile_staleness_hook.ts +12 -0
- package/src/scripts/record_evaluator_measurements.mjs +105 -0
- package/src/scripts/recruit_preflight.sh +1 -1
- package/src/scripts/release.ts +105 -1
- package/src/scripts/router_target_paths.d.mts +4 -0
- package/src/scripts/router_target_paths.mjs +69 -0
- package/src/scripts/router_telemetry.ts +52 -1
- package/src/scripts/routing_doctor.ts +485 -0
- package/src/scripts/rule_trigger_eval.ts +403 -0
- package/src/scripts/schemas/rule.schema.json +5 -1
- package/src/scripts/session_canary_hook.ts +96 -5
- package/src/scripts/skill_linter.ts +90 -42
- package/src/scripts/smoke/skills.sh +1 -1
- package/src/scripts/sweep_dead_scan_roots.ts +356 -10
- package/src/scripts/trigger_coverage.ts +13 -2
- package/src/scripts/update_counts.ts +91 -12
- package/src/scripts/validate_telegraph_carveouts.ts +1 -1
- package/src/scripts/wrapper_freshness_hook.ts +14 -0
- package/src/server/schemas/settings.ts +19 -5
- package/dist/cli-delegate/chunk-TJIAM5FW.js +0 -133
- package/dist/ui/assets/index-BpSQt5vm.js +0 -40
- package/dist/ui/assets/index-BpSQt5vm.js.map +0 -1
|
@@ -183,6 +183,57 @@ function _fnmatch(name: string, pat: string): boolean {
|
|
|
183
183
|
// ── Trigger matching ─────────────────────────────────────────────────────
|
|
184
184
|
|
|
185
185
|
/** Apply one trigger to a prompt + context; return True on match. */
|
|
186
|
+
/** Unicode word character — letters, digits, underscore (incl. umlauts). */
|
|
187
|
+
const _WORD_CHAR = /[\p{L}\p{N}_]/u;
|
|
188
|
+
|
|
189
|
+
function _isWordChar(c: string | undefined): boolean {
|
|
190
|
+
return c !== undefined && _WORD_CHAR.test(c);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Word-boundary-anchored keyword match (road-to-tested-routing Phase 3).
|
|
195
|
+
*
|
|
196
|
+
* A `keyword` occurrence counts only when its word-character edges sit on
|
|
197
|
+
* word boundaries: `ac` no longer fires inside "black", `plan` no longer
|
|
198
|
+
* fires inside "planet". Two deliberate reliefs:
|
|
199
|
+
*
|
|
200
|
+
* - An edge that is itself a NON-word character (e.g. `__()`, `/image:`,
|
|
201
|
+
* `trans(`, an emoji) carries no boundary requirement on that side —
|
|
202
|
+
* punctuation-shaped keywords keep their exact substring semantics.
|
|
203
|
+
* - The right boundary accepts one optional plural `s` ("icons", "options",
|
|
204
|
+
* "secrets" still fire their singular keyword). Richer inflection (German
|
|
205
|
+
* verb endings: "implementiere", "committen") is a DOCUMENTED accepted
|
|
206
|
+
* recall cost of anchoring — the matrices carry standalone-token phrasings
|
|
207
|
+
* for those languages instead.
|
|
208
|
+
*
|
|
209
|
+
* `phrase` deliberately stays unanchored substring; since this change the
|
|
210
|
+
* two trigger kinds genuinely differ.
|
|
211
|
+
*/
|
|
212
|
+
export function keyword_matches_anchored(prompt_lower: string, kw_lower: string): boolean {
|
|
213
|
+
if (kw_lower === "") {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const needLeft = _isWordChar(kw_lower[0]);
|
|
217
|
+
const needRight = _isWordChar(kw_lower[kw_lower.length - 1]);
|
|
218
|
+
let idx = prompt_lower.indexOf(kw_lower);
|
|
219
|
+
while (idx !== -1) {
|
|
220
|
+
const leftOk = !needLeft || !_isWordChar(prompt_lower[idx - 1]);
|
|
221
|
+
let rightOk = true;
|
|
222
|
+
if (needRight) {
|
|
223
|
+
let end = idx + kw_lower.length;
|
|
224
|
+
if (prompt_lower[end] === "s") {
|
|
225
|
+
end += 1; // optional plural `s`
|
|
226
|
+
}
|
|
227
|
+
rightOk = !_isWordChar(prompt_lower[end]);
|
|
228
|
+
}
|
|
229
|
+
if (leftOk && rightOk) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
idx = prompt_lower.indexOf(kw_lower, idx + 1);
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
186
237
|
export function trigger_matches(
|
|
187
238
|
trigger: Trigger,
|
|
188
239
|
prompt: string,
|
|
@@ -191,7 +242,7 @@ export function trigger_matches(
|
|
|
191
242
|
): boolean {
|
|
192
243
|
const prompt_lower = prompt.toLowerCase();
|
|
193
244
|
if ("keyword" in trigger) {
|
|
194
|
-
return prompt_lower
|
|
245
|
+
return keyword_matches_anchored(prompt_lower, String(trigger["keyword"]).toLowerCase());
|
|
195
246
|
}
|
|
196
247
|
if ("phrase" in trigger) {
|
|
197
248
|
return prompt_lower.includes(String(trigger["phrase"]).toLowerCase());
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* routing:doctor — read-only, live-installation routing diagnosis.
|
|
4
|
+
*
|
|
5
|
+
* Answers, against the REAL installation (not fixtures), the question the
|
|
6
|
+
* session-canary incident exposed as untestable: "why did / didn't concern X
|
|
7
|
+
* fire on session start?" — plus the freshness facts a routing complaint
|
|
8
|
+
* needs ruled out first. Composes existing single-purpose surfaces instead
|
|
9
|
+
* of duplicating them:
|
|
10
|
+
*
|
|
11
|
+
* * `hooks_status.collect()` — per-platform bridge presence + bindings
|
|
12
|
+
* (the "is the dispatcher even registered in the host?" layer).
|
|
13
|
+
* * `dispatch_hook._resolve_concerns()` — the exact session_start concern
|
|
14
|
+
* chain the dispatcher would run for the platform.
|
|
15
|
+
* * `concern_registry.CONCERN_REGISTRY` — in-process gate PROBES for the
|
|
16
|
+
* read-only session_start concerns: each probe runs the concern's real
|
|
17
|
+
* `main()` with a synthetic session_start envelope and reports
|
|
18
|
+
* ACTIVE (context injected, with the concern's own `reason`) or
|
|
19
|
+
* INACTIVE (clean no-op). This is the live gate evaluation, not a
|
|
20
|
+
* simulation.
|
|
21
|
+
* * compile_router `--check` + `condense.sh --changed` — router and
|
|
22
|
+
* projection freshness (skippable via `--no-freshness`; auto-skipped
|
|
23
|
+
* when the source tree is absent, i.e. in a consumer install).
|
|
24
|
+
*
|
|
25
|
+
* PROBE SAFETY. Only concerns in `PROBE_SAFE` are invoked — verified to
|
|
26
|
+
* perform zero state writes on the session_start path (session-canary,
|
|
27
|
+
* onboarding-gate, profile-staleness). Stateful concerns (chat-history,
|
|
28
|
+
* hot-context, first-run-gate, wrapper-freshness, surface-probe) are listed
|
|
29
|
+
* with status `stateful` and NOT invoked; their last outcome is visible via
|
|
30
|
+
* `hooks:doctor` (dispatcher feedback files). Deeper diagnosis of a
|
|
31
|
+
* stateful concern stays a `hooks:doctor` job — this doctor never widens
|
|
32
|
+
* the probe set silently.
|
|
33
|
+
*
|
|
34
|
+
* Read-only contract: no file is created or modified; the only child
|
|
35
|
+
* processes are the two freshness checks, both themselves read-only.
|
|
36
|
+
*/
|
|
37
|
+
import fs from "node:fs";
|
|
38
|
+
import path from "node:path";
|
|
39
|
+
import { spawnSync } from "node:child_process";
|
|
40
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
41
|
+
|
|
42
|
+
import {
|
|
43
|
+
type JsonObject,
|
|
44
|
+
type JsonValue,
|
|
45
|
+
_load_yaml,
|
|
46
|
+
_resolve_concerns,
|
|
47
|
+
} from "./hooks/dispatch_hook.js";
|
|
48
|
+
import { CONCERN_REGISTRY } from "./hooks/concern_registry.js";
|
|
49
|
+
import {
|
|
50
|
+
clearHookStdinOverride,
|
|
51
|
+
setHookStdinOverride,
|
|
52
|
+
} from "./hooks/hook_stdin.js";
|
|
53
|
+
import * as hooks_status from "./hooks_status.js";
|
|
54
|
+
import { load_agent_settings } from "./_lib/agent_settings.js";
|
|
55
|
+
import {
|
|
56
|
+
normalizeHostManifest,
|
|
57
|
+
type HostCapabilityManifest,
|
|
58
|
+
} from "./_lib/host_capability.js";
|
|
59
|
+
import {
|
|
60
|
+
classifyLookup,
|
|
61
|
+
classifyTask,
|
|
62
|
+
type ActivationInputs,
|
|
63
|
+
} from "./_lib/auto_dispatch.js";
|
|
64
|
+
import { TIER_ORDER, readCooldowns } from "./_lib/tier_budget_routing.js";
|
|
65
|
+
|
|
66
|
+
const REPO_ROOT = path.resolve(
|
|
67
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
68
|
+
"..",
|
|
69
|
+
"..",
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const MANIFEST_PATH = path.join(REPO_ROOT, "src", "scripts", "hook_manifest.yaml");
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Concerns whose session_start `main()` performs zero state writes — the
|
|
76
|
+
* only ones the doctor may invoke live. Adding a concern here requires
|
|
77
|
+
* re-verifying its write-free path (grep for writeFileSync / appendFileSync /
|
|
78
|
+
* mkdirSync / renameSync on the session_start branch).
|
|
79
|
+
*/
|
|
80
|
+
export const PROBE_SAFE: ReadonlySet<string> = new Set([
|
|
81
|
+
"session-canary",
|
|
82
|
+
"onboarding-gate",
|
|
83
|
+
"profile-staleness",
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
export interface GateReport {
|
|
87
|
+
concern: string;
|
|
88
|
+
script: string;
|
|
89
|
+
status: "ACTIVE" | "INACTIVE" | "ERROR" | "stateful" | "unregistered";
|
|
90
|
+
reason: string;
|
|
91
|
+
injects_context: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface FreshnessReport {
|
|
95
|
+
router: "fresh" | "stale" | "skipped" | "unavailable";
|
|
96
|
+
projection: "clean" | "stale" | "skipped" | "unavailable";
|
|
97
|
+
projection_detail: string;
|
|
98
|
+
dispatch_bundle: "built" | "absent (tsx fallback path)";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface OrchestrationReport {
|
|
102
|
+
enabled: boolean;
|
|
103
|
+
auto: string;
|
|
104
|
+
downshift: boolean;
|
|
105
|
+
budget_routing: string;
|
|
106
|
+
/** cost.budgets.per_tier ceilings + live cool-down state per tier. */
|
|
107
|
+
tier_budgets: Record<string, { ceiling_usd: number | null; cooldown_until_ms: number }>;
|
|
108
|
+
host_manifest: HostCapabilityManifest;
|
|
109
|
+
/** Verdict of the real activation gate for a canonical delegable probe. */
|
|
110
|
+
activation: { action: string; reason: string };
|
|
111
|
+
cost_budgets: Record<string, unknown>;
|
|
112
|
+
ledger_present: boolean;
|
|
113
|
+
/** Optional --classify dry-run result. */
|
|
114
|
+
sample: {
|
|
115
|
+
prompt: string;
|
|
116
|
+
lookup_route: string;
|
|
117
|
+
lookup_primitive: string | null;
|
|
118
|
+
dispatch: string;
|
|
119
|
+
mode: string | null;
|
|
120
|
+
reason: string;
|
|
121
|
+
} | null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface DoctorReport {
|
|
125
|
+
platform: string;
|
|
126
|
+
chain: string[];
|
|
127
|
+
gates: GateReport[];
|
|
128
|
+
freshness: FreshnessReport;
|
|
129
|
+
orchestration: OrchestrationReport;
|
|
130
|
+
bridge_table: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Orchestration-routing state: settings gates, host capability, budget
|
|
135
|
+
* inputs, and (optionally) a dry-run classification for a sample prompt.
|
|
136
|
+
* Read-only — mirrors exactly what the delegation layer would resolve.
|
|
137
|
+
*/
|
|
138
|
+
export function collect_orchestration(
|
|
139
|
+
workspace_root: string,
|
|
140
|
+
sample_prompt: string | null,
|
|
141
|
+
): OrchestrationReport {
|
|
142
|
+
const settings = load_agent_settings({ cwd: workspace_root });
|
|
143
|
+
const sub = (settings["subagents"] ?? {}) as Record<string, unknown>;
|
|
144
|
+
const enabled = sub["enabled"] !== false;
|
|
145
|
+
const auto = typeof sub["auto"] === "string" ? (sub["auto"] as string) : "ask";
|
|
146
|
+
const downshift = sub["downshift"] !== false;
|
|
147
|
+
const host_manifest = normalizeHostManifest(sub["host_capabilities"]);
|
|
148
|
+
const activationInputs: ActivationInputs = {
|
|
149
|
+
enabled,
|
|
150
|
+
auto: (auto === "on" || auto === "off" ? auto : "ask") as ActivationInputs["auto"],
|
|
151
|
+
subagent_spawn: host_manifest.subagent_spawn,
|
|
152
|
+
};
|
|
153
|
+
// Canonical delegable probe: the gate verdict shows which activation
|
|
154
|
+
// layer (settings / host primitive) decides on THIS installation.
|
|
155
|
+
const probe = classifyTask(
|
|
156
|
+
{ size_estimate: 5, independent_slices: 3 },
|
|
157
|
+
activationInputs,
|
|
158
|
+
);
|
|
159
|
+
const cost = (settings["cost"] ?? {}) as Record<string, unknown>;
|
|
160
|
+
const cost_budgets = (cost["budgets"] ?? {}) as Record<string, unknown>;
|
|
161
|
+
const tracking_dir = path.join(workspace_root, "agents", "cost-tracking");
|
|
162
|
+
const ledger_present = fs.existsSync(path.join(tracking_dir, "sessions.jsonl"));
|
|
163
|
+
const budget_routing =
|
|
164
|
+
typeof sub["budget_routing"] === "string" ? (sub["budget_routing"] as string) : "ask";
|
|
165
|
+
const per_tier = (cost_budgets["per_tier"] ?? {}) as Record<string, unknown>;
|
|
166
|
+
const cooldowns = readCooldowns(tracking_dir);
|
|
167
|
+
const tier_budgets: OrchestrationReport["tier_budgets"] = {};
|
|
168
|
+
for (const t of TIER_ORDER) {
|
|
169
|
+
const v = per_tier[t];
|
|
170
|
+
tier_budgets[t] = {
|
|
171
|
+
ceiling_usd: typeof v === "number" && Number.isFinite(v) ? v : null,
|
|
172
|
+
cooldown_until_ms: cooldowns[t],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let sample: OrchestrationReport["sample"] = null;
|
|
177
|
+
if (sample_prompt) {
|
|
178
|
+
const lookup = classifyLookup(sample_prompt);
|
|
179
|
+
const cls = classifyTask({ size_estimate: 5 }, activationInputs);
|
|
180
|
+
sample = {
|
|
181
|
+
prompt: sample_prompt,
|
|
182
|
+
lookup_route: lookup.route,
|
|
183
|
+
lookup_primitive: lookup.primitive,
|
|
184
|
+
dispatch: lookup.route === "primitive" ? "primitive (no spawn)" : cls.action,
|
|
185
|
+
mode: cls.mode,
|
|
186
|
+
reason: lookup.route === "primitive" ? lookup.reason : cls.reason,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
enabled,
|
|
191
|
+
auto,
|
|
192
|
+
downshift,
|
|
193
|
+
budget_routing,
|
|
194
|
+
tier_budgets,
|
|
195
|
+
host_manifest,
|
|
196
|
+
activation: { action: probe.action, reason: probe.reason },
|
|
197
|
+
cost_budgets,
|
|
198
|
+
ledger_present,
|
|
199
|
+
sample,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Invoke one PROBE_SAFE concern's registered main() and observe its gate. */
|
|
204
|
+
export function probe_gate(
|
|
205
|
+
name: string,
|
|
206
|
+
script: string,
|
|
207
|
+
workspace_root: string,
|
|
208
|
+
): GateReport {
|
|
209
|
+
const main_fn = CONCERN_REGISTRY[script];
|
|
210
|
+
if (!main_fn) {
|
|
211
|
+
return {
|
|
212
|
+
concern: name,
|
|
213
|
+
script,
|
|
214
|
+
status: "unregistered",
|
|
215
|
+
reason: "no CONCERN_REGISTRY entry — dispatcher would use the slow tsx spawn path",
|
|
216
|
+
injects_context: false,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const envelope: JsonObject = {
|
|
220
|
+
event: "session_start",
|
|
221
|
+
workspace_root,
|
|
222
|
+
platform: "routing-doctor-probe",
|
|
223
|
+
};
|
|
224
|
+
let out = "";
|
|
225
|
+
const prevWrite = process.stdout.write;
|
|
226
|
+
type WriteFn = typeof process.stdout.write;
|
|
227
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
228
|
+
const capture: WriteFn = ((chunk: any, enc?: any, cb?: any): boolean => {
|
|
229
|
+
out += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf-8");
|
|
230
|
+
const callback = typeof enc === "function" ? enc : cb;
|
|
231
|
+
if (typeof callback === "function") callback();
|
|
232
|
+
return true;
|
|
233
|
+
}) as WriteFn;
|
|
234
|
+
|
|
235
|
+
let rc = 0;
|
|
236
|
+
setHookStdinOverride(JSON.stringify(envelope));
|
|
237
|
+
process.stdout.write = capture;
|
|
238
|
+
try {
|
|
239
|
+
const result = main_fn([]);
|
|
240
|
+
rc = typeof result === "number" ? result : 0;
|
|
241
|
+
} catch (exc) {
|
|
242
|
+
rc = 3;
|
|
243
|
+
out = "";
|
|
244
|
+
process.stdout.write = prevWrite;
|
|
245
|
+
return {
|
|
246
|
+
concern: name,
|
|
247
|
+
script,
|
|
248
|
+
status: "ERROR",
|
|
249
|
+
reason: exc instanceof Error ? exc.message : String(exc),
|
|
250
|
+
injects_context: false,
|
|
251
|
+
};
|
|
252
|
+
} finally {
|
|
253
|
+
process.stdout.write = prevWrite;
|
|
254
|
+
clearHookStdinOverride();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (rc !== 0) {
|
|
258
|
+
return {
|
|
259
|
+
concern: name,
|
|
260
|
+
script,
|
|
261
|
+
status: "ERROR",
|
|
262
|
+
reason: `probe exited rc=${rc}`,
|
|
263
|
+
injects_context: false,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const text = out.trim();
|
|
267
|
+
if (text === "") {
|
|
268
|
+
return {
|
|
269
|
+
concern: name,
|
|
270
|
+
script,
|
|
271
|
+
status: "INACTIVE",
|
|
272
|
+
reason: "gate closed — concern emitted nothing (clean no-op)",
|
|
273
|
+
injects_context: false,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
let reason = "gate open";
|
|
277
|
+
let injects = false;
|
|
278
|
+
try {
|
|
279
|
+
const parsed = JSON.parse(text) as JsonObject;
|
|
280
|
+
if (typeof parsed["reason"] === "string" && parsed["reason"] !== "") {
|
|
281
|
+
reason = parsed["reason"] as string;
|
|
282
|
+
}
|
|
283
|
+
injects = typeof parsed["context"] === "string" && parsed["context"] !== "";
|
|
284
|
+
} catch {
|
|
285
|
+
reason = "gate open (non-JSON stdout)";
|
|
286
|
+
}
|
|
287
|
+
return { concern: name, script, status: "ACTIVE", reason, injects_context: injects };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** session_start chain for the platform, from the real manifest. */
|
|
291
|
+
export function resolve_chain(
|
|
292
|
+
manifest: JsonObject,
|
|
293
|
+
platform: string,
|
|
294
|
+
): Array<{ name: string; script: string }> {
|
|
295
|
+
const concerns = _resolve_concerns(manifest, platform, "session_start");
|
|
296
|
+
return concerns.map((c) => ({
|
|
297
|
+
name: String((c as JsonObject)["name"] ?? "unknown"),
|
|
298
|
+
script: String((c as JsonObject)["script"] ?? ""),
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function _freshness(no_freshness: boolean): FreshnessReport {
|
|
303
|
+
const bundle = fs.existsSync(path.join(REPO_ROOT, "dist", "hooks", "dispatch.js"))
|
|
304
|
+
? ("built" as const)
|
|
305
|
+
: ("absent (tsx fallback path)" as const);
|
|
306
|
+
if (no_freshness) {
|
|
307
|
+
return { router: "skipped", projection: "skipped", projection_detail: "", dispatch_bundle: bundle };
|
|
308
|
+
}
|
|
309
|
+
const compiler = path.join(REPO_ROOT, "src", "scripts", "compile_router.ts");
|
|
310
|
+
let router: FreshnessReport["router"] = "unavailable";
|
|
311
|
+
if (fs.existsSync(compiler)) {
|
|
312
|
+
const r = spawnSync("npx", ["tsx", compiler, "--check"], {
|
|
313
|
+
cwd: REPO_ROOT,
|
|
314
|
+
encoding: "utf-8",
|
|
315
|
+
timeout: 120_000,
|
|
316
|
+
});
|
|
317
|
+
router = r.status === 0 ? "fresh" : "stale";
|
|
318
|
+
}
|
|
319
|
+
const condense = path.join(REPO_ROOT, "src", "scripts", "condense.sh");
|
|
320
|
+
let projection: FreshnessReport["projection"] = "unavailable";
|
|
321
|
+
let detail = "";
|
|
322
|
+
if (fs.existsSync(condense)) {
|
|
323
|
+
const r = spawnSync("bash", [condense, "--changed"], {
|
|
324
|
+
cwd: REPO_ROOT,
|
|
325
|
+
encoding: "utf-8",
|
|
326
|
+
timeout: 300_000,
|
|
327
|
+
});
|
|
328
|
+
const outText = `${r.stdout ?? ""}${r.stderr ?? ""}`;
|
|
329
|
+
if (outText.includes("Every .md projection matches")) {
|
|
330
|
+
projection = "clean";
|
|
331
|
+
} else {
|
|
332
|
+
projection = "stale";
|
|
333
|
+
detail = outText
|
|
334
|
+
.split("\n")
|
|
335
|
+
.filter((l) => l.trim().startsWith("rules/") || l.trim().startsWith("skills/") || l.trim().startsWith("commands/"))
|
|
336
|
+
.slice(0, 10)
|
|
337
|
+
.join("; ");
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return { router, projection, projection_detail: detail, dispatch_bundle: bundle };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function collect_report(options: {
|
|
344
|
+
platform: string;
|
|
345
|
+
workspace_root: string;
|
|
346
|
+
no_freshness: boolean;
|
|
347
|
+
classify?: string | null;
|
|
348
|
+
}): DoctorReport {
|
|
349
|
+
const manifest = _load_yaml(MANIFEST_PATH);
|
|
350
|
+
const chain = resolve_chain(manifest, options.platform);
|
|
351
|
+
const gates: GateReport[] = chain.map(({ name, script }) => {
|
|
352
|
+
if (!PROBE_SAFE.has(name)) {
|
|
353
|
+
return {
|
|
354
|
+
concern: name,
|
|
355
|
+
script,
|
|
356
|
+
status: "stateful" as const,
|
|
357
|
+
reason: "not probed (writes state) — see hooks:doctor last-feedback",
|
|
358
|
+
injects_context: false,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return probe_gate(name, script, options.workspace_root);
|
|
362
|
+
});
|
|
363
|
+
let bridge_table = "";
|
|
364
|
+
try {
|
|
365
|
+
const matrix = hooks_status.collect(options.workspace_root, manifest);
|
|
366
|
+
bridge_table = hooks_status._render_table(matrix);
|
|
367
|
+
} catch (exc) {
|
|
368
|
+
bridge_table = `bridge status unavailable: ${exc instanceof Error ? exc.message : String(exc)}`;
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
platform: options.platform,
|
|
372
|
+
chain: chain.map((c) => c.name),
|
|
373
|
+
gates,
|
|
374
|
+
freshness: _freshness(options.no_freshness),
|
|
375
|
+
orchestration: collect_orchestration(options.workspace_root, options.classify ?? null),
|
|
376
|
+
bridge_table,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function _render(report: DoctorReport): string {
|
|
381
|
+
const lines: string[] = [];
|
|
382
|
+
lines.push(`routing:doctor · platform=${report.platform} · event=session_start`);
|
|
383
|
+
lines.push("");
|
|
384
|
+
lines.push("Gate status (live probes, read-only):");
|
|
385
|
+
for (const g of report.gates) {
|
|
386
|
+
const marker =
|
|
387
|
+
g.status === "ACTIVE" ? "✅" : g.status === "ERROR" ? "❌" : g.status === "INACTIVE" ? "⚠️" : "·";
|
|
388
|
+
const ctx = g.injects_context ? " [injects context]" : "";
|
|
389
|
+
lines.push(` ${marker} ${g.concern.padEnd(20)} ${g.status.padEnd(10)} ${g.reason}${ctx}`);
|
|
390
|
+
}
|
|
391
|
+
lines.push("");
|
|
392
|
+
lines.push(
|
|
393
|
+
`Freshness: router=${report.freshness.router} · projection=${report.freshness.projection}` +
|
|
394
|
+
(report.freshness.projection_detail ? ` (${report.freshness.projection_detail})` : "") +
|
|
395
|
+
` · dispatch bundle=${report.freshness.dispatch_bundle}`,
|
|
396
|
+
);
|
|
397
|
+
lines.push("");
|
|
398
|
+
const o = report.orchestration;
|
|
399
|
+
lines.push(
|
|
400
|
+
`Orchestration: enabled=${o.enabled} · auto=${o.auto} · downshift=${o.downshift} · ` +
|
|
401
|
+
`budget_routing=${o.budget_routing} · subagent_spawn=${o.host_manifest.subagent_spawn} · ` +
|
|
402
|
+
`ledger=${o.ledger_present ? "present" : "absent"}`,
|
|
403
|
+
);
|
|
404
|
+
const tierBits = Object.entries(o.tier_budgets).map(([t, s]) => {
|
|
405
|
+
const cap = s.ceiling_usd === null ? "no cap" : `$${s.ceiling_usd}`;
|
|
406
|
+
const cool = s.cooldown_until_ms > 0 ? " COOLING" : "";
|
|
407
|
+
return `${t}=${cap}${cool}`;
|
|
408
|
+
});
|
|
409
|
+
lines.push(` tier budgets (rolling-24h): ${tierBits.join(" · ")}`);
|
|
410
|
+
lines.push(` activation probe: ${o.activation.action} — ${o.activation.reason}`);
|
|
411
|
+
if (o.sample) {
|
|
412
|
+
lines.push(
|
|
413
|
+
` dry-run "${o.sample.prompt.slice(0, 60)}": ${o.sample.dispatch}` +
|
|
414
|
+
(o.sample.mode ? ` (${o.sample.mode})` : "") +
|
|
415
|
+
(o.sample.lookup_primitive ? ` via ${o.sample.lookup_primitive}` : "") +
|
|
416
|
+
` — ${o.sample.reason}`,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
lines.push("");
|
|
420
|
+
lines.push("Host bridge / bindings:");
|
|
421
|
+
lines.push(report.bridge_table);
|
|
422
|
+
return lines.join("\n");
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function main(argv?: string[]): number {
|
|
426
|
+
const args = argv ?? process.argv.slice(2);
|
|
427
|
+
let platform = "claude";
|
|
428
|
+
let workspace_root = process.cwd();
|
|
429
|
+
let json = false;
|
|
430
|
+
let strict = false;
|
|
431
|
+
let no_freshness = false;
|
|
432
|
+
let classify: string | null = null;
|
|
433
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
434
|
+
const a = args[i];
|
|
435
|
+
if (a === "--platform" && args[i + 1]) {
|
|
436
|
+
platform = String(args[(i += 1)]);
|
|
437
|
+
} else if (a === "--workspace" && args[i + 1]) {
|
|
438
|
+
workspace_root = path.resolve(String(args[(i += 1)]));
|
|
439
|
+
} else if (a === "--classify" && args[i + 1]) {
|
|
440
|
+
classify = String(args[(i += 1)]);
|
|
441
|
+
} else if (a === "--json") {
|
|
442
|
+
json = true;
|
|
443
|
+
} else if (a === "--strict") {
|
|
444
|
+
strict = true;
|
|
445
|
+
} else if (a === "--no-freshness") {
|
|
446
|
+
no_freshness = true;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const report = collect_report({ platform, workspace_root, no_freshness, classify });
|
|
450
|
+
if (json) {
|
|
451
|
+
process.stdout.write(`${JSON.stringify(report as unknown as JsonValue, null, 2)}\n`);
|
|
452
|
+
} else {
|
|
453
|
+
process.stdout.write(`${_render(report)}\n`);
|
|
454
|
+
}
|
|
455
|
+
const red =
|
|
456
|
+
report.gates.some((g) => g.status === "ERROR" || g.status === "unregistered") ||
|
|
457
|
+
report.freshness.router === "stale" ||
|
|
458
|
+
report.freshness.projection === "stale";
|
|
459
|
+
return strict && red ? 1 : 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
|
|
463
|
+
function _isCliEntry(): boolean {
|
|
464
|
+
if (typeof __AGENT_CONFIG_BUNDLE__ !== "undefined" && __AGENT_CONFIG_BUNDLE__) {
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
if (process.argv[1] === undefined) {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
471
|
+
if (import.meta.url === argvUrl) {
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
476
|
+
const argv1 = fs.realpathSync(path.resolve(process.argv[1]));
|
|
477
|
+
return here === argv1;
|
|
478
|
+
} catch {
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (_isCliEntry()) {
|
|
484
|
+
process.exit(main());
|
|
485
|
+
}
|