@event4u/agent-config 16.1.0 → 16.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +98 -257
- package/README.md +14 -12
- package/dist/agent-src/commands/analyze/inbox.md +1 -1
- package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
- package/dist/agent-src/commands/bug/fix.md +17 -2
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +1 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +5 -5
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
- package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
- package/dist/agent-src/commands/roadmap.md +18 -4
- package/dist/agent-src/commands/tests/create.md +17 -3
- package/dist/agent-src/commands/tests/execute.md +22 -5
- package/dist/agent-src/commands/work.md +4 -0
- package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
- package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -0
- package/dist/agent-src/rules/broken-access-control.md +1 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
- package/dist/agent-src/rules/context-hygiene.md +1 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
- package/dist/agent-src/rules/design-fidelity.md +13 -16
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/domain-safety-retention.md +1 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +1 -0
- package/dist/agent-src/rules/git-history-discipline.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -2
- 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/media-governance-routing.md +14 -17
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
- package/dist/agent-src/rules/session-canary.md +8 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/dist/agent-src/scripts/deferral_carry.ts +339 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
- package/dist/agent-src/skills/design-review/SKILL.md +30 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
- package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
- package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +30 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/dist/cli/python/knowledge_ingest.js +1 -1
- package/dist/cli/python/workspace_drive.js +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
- package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
- package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
- package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
- package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
- package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
- package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
- package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
- package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +1862 -809
- package/dist/cli-delegate/cmd_doctor.js +13 -6
- package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
- package/dist/cli-delegate/cmd_explain.js +5 -5
- package/dist/cli-delegate/cmd_export.js +11 -8
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +10 -7
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +11 -8
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +8 -6
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +4 -3
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +11 -8
- package/dist/cli-delegate/cmd_uninstall.js +11 -8
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +11 -8
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +5 -5
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +132 -80
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +7972 -5186
- package/dist/hooks/dispatch.sha256 +1 -0
- package/dist/install/claudePathsPlan.js +47 -6
- package/dist/install/claudeRuleRewrite.js +7 -0
- package/dist/install/emit_host_rules_cli.js +39 -36
- package/dist/install/globalRuleScope.js +87 -0
- package/dist/install/host_rule_ownership.js +160 -0
- package/dist/install/install.mjs +2226 -1055
- package/dist/install/installThinLayer.js +261 -0
- package/dist/install/installedRuleLinks.js +176 -0
- package/dist/install/wizard-plan.js +24 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +40913 -34865
- package/dist/scripts/_lib/agent_settings.js +11 -0
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- package/dist/scripts/_lib/installed_layer.js +378 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- package/dist/scripts/_lib/rule_consequence_class.js +45 -0
- package/dist/scripts/_lib/rule_injection.js +67 -10
- package/dist/scripts/_lib/rule_law_section.js +122 -0
- package/dist/scripts/_lib/thin_rules.js +458 -0
- package/dist/scripts/_lib/windsurf_render.js +60 -0
- package/dist/scripts/condense.js +14 -26
- package/dist/scripts/project_thin_rules.js +14 -294
- package/dist/server/schemas/settings.js +29 -0
- package/dist/shared/skillRanking.js +74 -13
- package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
- package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
- package/dist/ui/index.html +2 -2
- package/docs/contracts/settings-classes.md +10 -6
- package/package.json +4 -4
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/src/agent-src/scripts/deferral_carry.ts +339 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/src/config/agent-settings.template.yml +91 -22
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/continuity-surface.json +9 -2
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +327 -3
- package/src/config/gate-violation-baselines.json +21 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +8 -3
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/routing-coverage-seed.json +38 -3
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-consequence-class.json +161 -0
- package/src/config/rule-law-ceilings.json +99 -0
- package/src/install/claudePathsPlan.ts +46 -4
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/emit_host_rules_cli.ts +43 -34
- package/src/install/globalRuleScope.ts +109 -0
- package/src/install/host_rule_ownership.ts +170 -0
- package/src/install/installThinLayer.ts +312 -0
- package/src/install/installedRuleLinks.ts +220 -0
- package/src/install/wizard-plan.ts +24 -0
- package/src/scripts/_cli/cmd_doctor.ts +28 -90
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_cli/doctor_execution.ts +100 -17
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/concern_sla_window.ts +200 -0
- package/src/scripts/_lib/estate_offsets.ts +241 -0
- package/src/scripts/_lib/exemption_shape.ts +143 -0
- package/src/scripts/_lib/fnv.ts +23 -0
- package/src/scripts/_lib/foreign_scan.ts +106 -0
- package/src/scripts/_lib/forge_protection.ts +114 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
- package/src/scripts/_lib/graph_feeder_record.ts +214 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +538 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
- package/src/scripts/_lib/obligations.ts +119 -8
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +2 -1
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- package/src/scripts/_lib/review_coverage.ts +134 -0
- package/src/scripts/_lib/rule_consequence_class.ts +71 -0
- package/src/scripts/_lib/rule_injection.ts +130 -10
- package/src/scripts/_lib/rule_law_section.ts +147 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
- package/src/scripts/_lib/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/skill_origin.ts +254 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/thin_rules.ts +540 -0
- package/src/scripts/_lib/touched_file_quality.ts +434 -0
- package/src/scripts/_lib/turn_end_refusals.ts +600 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/verification_command.ts +324 -0
- package/src/scripts/_lib/verification_evidence.ts +647 -0
- package/src/scripts/_lib/verify_clause.ts +280 -0
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- package/src/scripts/ai_council/cli_call_budget.ts +13 -5
- package/src/scripts/ai_council/clients.ts +26 -57
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +573 -25
- package/src/scripts/bench_hook_latency.ts +412 -5
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/cache_realization_report.ts +61 -1
- package/src/scripts/check_argument_hint.ts +287 -0
- package/src/scripts/check_claims.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +38 -9
- package/src/scripts/check_enforcement_matrix.ts +621 -22
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +138 -7
- package/src/scripts/check_generator_sync.ts +71 -0
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_host_docs_digest.ts +786 -0
- package/src/scripts/check_host_format_column.ts +559 -0
- package/src/scripts/check_input_references.ts +228 -0
- package/src/scripts/check_inputs_parity.ts +235 -0
- package/src/scripts/check_kernel_edit_ratified.ts +89 -9
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_holds.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +115 -1
- package/src/scripts/code_graph/detect.ts +127 -7
- package/src/scripts/code_graph/foreign.ts +194 -0
- package/src/scripts/code_graph/query.ts +217 -4
- package/src/scripts/code_graph/types.ts +26 -2
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +103 -0
- package/src/scripts/compile_hook_manifest.ts +90 -14
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +192 -14
- package/src/scripts/hooks/block_config_weakening.ts +294 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
- package/src/scripts/hooks/bundle_integrity.ts +291 -0
- package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
- package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/concern_timings.ts +94 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
- package/src/scripts/hooks/design_pass_hook.ts +100 -9
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +77 -71
- package/src/scripts/hooks/edit_shape_hook.ts +1 -2
- package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
- package/src/scripts/hooks/evidence_independence.ts +1 -2
- package/src/scripts/hooks/exit_codes.ts +129 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +146 -3
- package/src/scripts/hooks/host_lowering.yaml +262 -46
- package/src/scripts/hooks/host_semantics.ts +30 -2
- package/src/scripts/hooks/injection_budget.ts +9 -2
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
- package/src/scripts/hooks/journal_record_hook.ts +1 -2
- package/src/scripts/hooks/memory_recall_hook.ts +1 -2
- package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
- package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/permission_gate.ts +1 -2
- package/src/scripts/hooks/push_settle_hook.ts +1 -3
- package/src/scripts/hooks/replay_hook.ts +2 -1
- package/src/scripts/hooks/reread_guard_hook.ts +1 -2
- package/src/scripts/hooks/review_baseline_hook.ts +1 -2
- package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
- package/src/scripts/hooks/rule_inject_hook.ts +765 -68
- package/src/scripts/hooks/run_continuation_hook.ts +13 -15
- package/src/scripts/hooks/skill_route_hook.ts +1 -2
- package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
- package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
- package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
- package/src/scripts/hooks/table_fingerprint.ts +70 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +75 -189
- package/src/scripts/installed_layer_report.ts +103 -0
- package/src/scripts/language_mirror_hook.ts +15 -6
- package/src/scripts/learning_sidecar.ts +119 -8
- package/src/scripts/lint_deny_text.ts +419 -0
- package/src/scripts/lint_exit_codes.ts +262 -0
- package/src/scripts/lint_hook_manifest.ts +108 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_roadmap_blockers.ts +78 -12
- package/src/scripts/lint_rule_law_section.ts +517 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/lint_workflow_security.ts +161 -5
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/release_publication.ts +13 -1
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_skill_ranker_confusion.ts +442 -0
- package/src/scripts/report_standing_payload_by_host.ts +188 -15
- package/src/scripts/report_verification_record_coverage.ts +306 -0
- package/src/scripts/roadmap_verify_share.ts +213 -0
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/command.schema.json +44 -0
- package/src/scripts/schemas/review-findings.schema.json +7 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/self_review_gate.ts +421 -17
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/trigger_eval_grandfather.json +0 -7
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +156 -4
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +41 -0
- package/src/shared/skillRanking.ts +117 -11
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
- package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- package/dist/ui/assets/index-DH1xc62v.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Per rule: is the obligation already carried by a mechanism, and is there a
|
|
4
|
+
* slot that could carry it?
|
|
5
|
+
*
|
|
6
|
+
* Step 1.5 of `road-to-rule-triggers-and-links-that-hold`. It joins three
|
|
7
|
+
* instruments that already exist and had never been read together:
|
|
8
|
+
*
|
|
9
|
+
* · `check_enforcement_coverage --json` — the only place `enforced_by` and
|
|
10
|
+
* `obligation_frequency` are already resolved per rule, including what the
|
|
11
|
+
* declaration resolves TO (a wired validator, a bound hook, nothing).
|
|
12
|
+
* · `report_obligation_carriers` — how many artifacts restate the same
|
|
13
|
+
* obligation, which is a different question from whether one enforces it.
|
|
14
|
+
* · The `# obligation: line N` frontmatter marker — 107 of 121 rules carry
|
|
15
|
+
* one and nothing in the tree reads it, so this is its first reader.
|
|
16
|
+
*
|
|
17
|
+
* **Two columns, and conflating them would be the error worth avoiding.**
|
|
18
|
+
* `carried` is measured: a gate either refuses or it does not.
|
|
19
|
+
* `slot_exists` is NECESSARY, NEVER SUFFICIENT — it says a host event fires at
|
|
20
|
+
* the obligation's own frequency, so a carrier could at least be bound. It
|
|
21
|
+
* does not say the obligation is decidable from what that event sees, which is
|
|
22
|
+
* the actual question and is not answerable by a join. A rule whose body says
|
|
23
|
+
* `instruction-only` has usually already answered it in the other direction,
|
|
24
|
+
* and that answer is reproduced rather than overridden.
|
|
25
|
+
*
|
|
26
|
+
* Report only. Moving an obligation out of prose is a per-rule change with its
|
|
27
|
+
* own review, which this roadmap's scope section says in as many words.
|
|
28
|
+
*/
|
|
29
|
+
import { execFileSync } from 'node:child_process';
|
|
30
|
+
import * as fs from 'node:fs';
|
|
31
|
+
import * as path from 'node:path';
|
|
32
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
33
|
+
|
|
34
|
+
// ledger-exempt: a REPORTER, not a gate. Its only non-zero exit says an input
|
|
35
|
+
// instrument could not be run, which is a statement about the walk.
|
|
36
|
+
|
|
37
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
38
|
+
|
|
39
|
+
/** Frequencies a host event is known to fire at — the `slot_exists` test. */
|
|
40
|
+
const EVENT_BOUND_FREQUENCIES: ReadonlySet<string> = new Set([
|
|
41
|
+
'per-edit',
|
|
42
|
+
'per-file-write',
|
|
43
|
+
'per-commit',
|
|
44
|
+
'per-turn',
|
|
45
|
+
'per-session',
|
|
46
|
+
'per-event',
|
|
47
|
+
'per-task',
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
/** Resolutions where something can actually refuse. */
|
|
51
|
+
const REFUSING: ReadonlySet<string> = new Set(['validator', 'validator-local', 'test', 'hook']);
|
|
52
|
+
|
|
53
|
+
export interface MechanismRow {
|
|
54
|
+
rule: string;
|
|
55
|
+
tier: string;
|
|
56
|
+
marker_line: number | null;
|
|
57
|
+
frequency: string;
|
|
58
|
+
declared: number;
|
|
59
|
+
effective: string;
|
|
60
|
+
/** `gate` · `observer` · `declared-gap` · `undeclared`. */
|
|
61
|
+
carried: string;
|
|
62
|
+
/** A host event is known to fire at this frequency. Necessary, not sufficient. */
|
|
63
|
+
slot_exists: boolean;
|
|
64
|
+
/** Artifacts restating this rule's obligations, per the carrier census. */
|
|
65
|
+
restatements: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** `# obligation: line N` inside the frontmatter block. */
|
|
69
|
+
export function markerLine(content: string): number | null {
|
|
70
|
+
if (!content.startsWith('---')) return null;
|
|
71
|
+
const end = content.indexOf('\n---', 3);
|
|
72
|
+
const block = end === -1 ? content : content.slice(0, end);
|
|
73
|
+
const m = /^#\s*obligation:\s*line\s+(\d+)\s*$/m.exec(block);
|
|
74
|
+
return m ? Number.parseInt(m[1] as string, 10) : null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function run(root: string, script: string, args: readonly string[]): string {
|
|
78
|
+
return execFileSync(path.join(root, 'scripts-run'), [script, ...args], {
|
|
79
|
+
cwd: root,
|
|
80
|
+
encoding: 'utf8',
|
|
81
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
82
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface CoverageRule {
|
|
87
|
+
id: string;
|
|
88
|
+
tier?: string;
|
|
89
|
+
declared?: string[];
|
|
90
|
+
effective?: string;
|
|
91
|
+
obligation_frequency?: string | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function rows(root: string): MechanismRow[] {
|
|
95
|
+
const coverage = JSON.parse(run(root, 'src/scripts/check_enforcement_coverage', ['--json'])) as {
|
|
96
|
+
rules: CoverageRule[];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
run(root, 'src/scripts/report_obligation_carriers', ['--top', '1']);
|
|
100
|
+
const carriersPath = path.join(root, 'agents', 'runtime', 'reports', 'obligation-carriers.json');
|
|
101
|
+
const restatements = new Map<string, number>();
|
|
102
|
+
if (!fs.existsSync(carriersPath)) {
|
|
103
|
+
// Not a degradation to absorb: `agents/runtime/` is gitignored, so a
|
|
104
|
+
// fresh checkout reaches this, and a silent fallback would publish a
|
|
105
|
+
// uniformly-zero Restatements column with nothing saying it is empty.
|
|
106
|
+
// Every other input failure in this script exits 1; so does this one.
|
|
107
|
+
throw new Error(
|
|
108
|
+
`report_obligation_carriers wrote no census at ${carriersPath} — the ` +
|
|
109
|
+
'Restatements column would read 0 for every rule without saying so',
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
{
|
|
113
|
+
const census = JSON.parse(fs.readFileSync(carriersPath, 'utf8')) as {
|
|
114
|
+
rows: { carriers: { path: string; cls: string }[] }[];
|
|
115
|
+
};
|
|
116
|
+
for (const r of census.rows) {
|
|
117
|
+
// A row is one obligation; it counts for every RULE that carries it.
|
|
118
|
+
for (const c of r.carriers) {
|
|
119
|
+
if (c.cls !== 'rule') continue;
|
|
120
|
+
const id = path.basename(c.path, '.md');
|
|
121
|
+
restatements.set(id, (restatements.get(id) ?? 0) + r.carriers.length - 1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const out: MechanismRow[] = [];
|
|
127
|
+
for (const r of coverage.rules) {
|
|
128
|
+
const file = path.join(root, 'src', 'rules', `${r.id}.md`);
|
|
129
|
+
const content = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
130
|
+
const declared = r.declared ?? [];
|
|
131
|
+
const effective = r.effective ?? 'none';
|
|
132
|
+
const frequency = r.obligation_frequency ?? '—';
|
|
133
|
+
|
|
134
|
+
let carried: string;
|
|
135
|
+
if (REFUSING.has(effective)) carried = 'gate';
|
|
136
|
+
else if (effective === 'observer') carried = 'observer';
|
|
137
|
+
else if (declared.length > 0) carried = 'declared-gap';
|
|
138
|
+
else carried = 'undeclared';
|
|
139
|
+
|
|
140
|
+
out.push({
|
|
141
|
+
rule: r.id,
|
|
142
|
+
tier: r.tier ?? '—',
|
|
143
|
+
marker_line: markerLine(content),
|
|
144
|
+
frequency,
|
|
145
|
+
declared: declared.length,
|
|
146
|
+
effective,
|
|
147
|
+
carried,
|
|
148
|
+
slot_exists: EVENT_BOUND_FREQUENCIES.has(frequency),
|
|
149
|
+
restatements: restatements.get(r.id) ?? 0,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
out.sort((a, b) => a.rule.localeCompare(b.rule));
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function renderTable(data: readonly MechanismRow[]): string[] {
|
|
157
|
+
const L: string[] = [];
|
|
158
|
+
L.push('| Rule | Tier | Marker | Frequency | `enforced_by` | Resolves to | Carried | Slot exists | Restatements |');
|
|
159
|
+
L.push('|---|---|---:|---|---:|---|---|---|---:|');
|
|
160
|
+
for (const r of data) {
|
|
161
|
+
L.push(
|
|
162
|
+
`| \`${r.rule}\` | ${r.tier} | ${r.marker_line === null ? '—' : String(r.marker_line)} | ` +
|
|
163
|
+
`${r.frequency} | ${String(r.declared)} | \`${r.effective}\` | ${r.carried} | ` +
|
|
164
|
+
`${r.slot_exists ? 'yes' : 'no'} | ${String(r.restatements)} |`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return L;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const USAGE = 'usage: report_obligation_mechanism [--root DIR] [--json | --table]\n';
|
|
171
|
+
|
|
172
|
+
export function main(): number {
|
|
173
|
+
const argv = process.argv.slice(2);
|
|
174
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
175
|
+
process.stdout.write(USAGE);
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
for (const a of argv) {
|
|
179
|
+
if (a.startsWith('-') && !['--root', '--json', '--table'].includes(a)) {
|
|
180
|
+
process.stderr.write(`unknown argument: ${a}\n${USAGE}`);
|
|
181
|
+
return 2;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const i = argv.indexOf('--root');
|
|
185
|
+
const root = i >= 0 && i + 1 < argv.length ? (argv[i + 1] as string) : process.cwd();
|
|
186
|
+
|
|
187
|
+
let data: MechanismRow[];
|
|
188
|
+
try {
|
|
189
|
+
data = rows(root);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
process.stderr.write(`could not read an input instrument: ${String(e)}\n`);
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (argv.includes('--json')) {
|
|
196
|
+
process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
if (argv.includes('--table')) {
|
|
200
|
+
process.stdout.write(`${renderTable(data).join('\n')}\n`);
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const by = (k: string): number => data.filter((r) => r.carried === k).length;
|
|
205
|
+
const slotNoGate = data.filter((r) => r.carried !== 'gate' && r.slot_exists).length;
|
|
206
|
+
process.stdout.write(
|
|
207
|
+
`${String(data.length)} rule(s)\n` +
|
|
208
|
+
` carried by a gate that can refuse: ${String(by('gate'))}\n` +
|
|
209
|
+
` carried by an observer (fires, never refuses): ${String(by('observer'))}\n` +
|
|
210
|
+
` declared gap (the rule says instruction-only / none): ${String(by('declared-gap'))}\n` +
|
|
211
|
+
` no enforcement declaration at all: ${String(by('undeclared'))}\n` +
|
|
212
|
+
` not gated, but a host event fires at the obligation's frequency: ${String(slotNoGate)}\n` +
|
|
213
|
+
` carry no \`# obligation: line N\` marker: ${String(data.filter((r) => r.marker_line === null).length)}\n`,
|
|
214
|
+
);
|
|
215
|
+
return 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function _isCliEntry(): boolean {
|
|
219
|
+
if (process.argv[1] === undefined) return false;
|
|
220
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) return true;
|
|
221
|
+
try {
|
|
222
|
+
return fs.realpathSync(_HERE) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (_isCliEntry()) {
|
|
229
|
+
process.exit(main());
|
|
230
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* report_obligation_writer_split — which kind of tree wrote the obligation rows.
|
|
4
|
+
*
|
|
5
|
+
* WHAT QUESTION THIS ANSWERS, AND WHY IT NEEDED A TOOL.
|
|
6
|
+
* `obligation-settle-shadow-bar` is pre-registered against the shadow rows under
|
|
7
|
+
* `agents/runtime/state/obligations/`, and its own clause (7) says that corpus is
|
|
8
|
+
* one machine's runtime state. Until the rows carried a writer, that sentence was
|
|
9
|
+
* the ONLY place the fact lived: a reader holding the ledgers could count rows and
|
|
10
|
+
* could not separate them, so a reading that cleared the floor would have been
|
|
11
|
+
* quotable as evidence about a population nobody had measured. This prints the
|
|
12
|
+
* separation, from the rows themselves.
|
|
13
|
+
*
|
|
14
|
+
* IT REACHES NO VERDICT, AND THAT IS THE DESIGN. A split is an input to the corpus
|
|
15
|
+
* decision held in `road-to-an-obligation-row-that-names-its-writer`, not the
|
|
16
|
+
* decision — the three options there (accept the one-machine corpus and amend the
|
|
17
|
+
* bar, widen it deliberately, or file the window `resolved-null`) are owner-
|
|
18
|
+
* reserved, and all three name arming as owner-reserved too. So this exits 0 on
|
|
19
|
+
* every path, prints counts, and says nothing about whether anything may be armed.
|
|
20
|
+
* A reporter that graded the corpus would be handing the arming discussion a
|
|
21
|
+
* verdict wearing a number's clothes.
|
|
22
|
+
*
|
|
23
|
+
* `absent` IS REPORTED APART FROM `unknown`, and the distinction is load-bearing.
|
|
24
|
+
* `unknown` is a row whose writer WAS resolved and came back unresolvable; `absent`
|
|
25
|
+
* is a row written before the field existed. Folding them together would let the
|
|
26
|
+
* whole pre-field corpus read as "we looked and could not tell", which is a
|
|
27
|
+
* stronger claim than "we had not started looking". The ledger's own `parseRows`
|
|
28
|
+
* maps both to `unknown` — correct for a consumer that only needs a role — so this
|
|
29
|
+
* reads the JSON directly rather than through it, and uses `isWriterRole` for the
|
|
30
|
+
* vocabulary so the two cannot drift.
|
|
31
|
+
*
|
|
32
|
+
* PRIVACY, at the precision the code holds. Output is counts, plus the SCAN ROOT,
|
|
33
|
+
* which the caller supplied and which is the one thing a reader needs in order to
|
|
34
|
+
* know what was measured. Nothing else crosses: no session id, no ledger filename,
|
|
35
|
+
* no rule id, no timestamp. The scan reads those and keeps none of them.
|
|
36
|
+
*
|
|
37
|
+
* WRITES NOTHING. It opens files for reading and creates no directory, not even
|
|
38
|
+
* the ledger directory it looks for. A missing directory is a reported state, not
|
|
39
|
+
* a thing to fix.
|
|
40
|
+
*
|
|
41
|
+
* Exit: 0 always, except a usage error (1). Advisory — it gates nothing.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
import * as fs from 'node:fs';
|
|
45
|
+
import * as path from 'node:path';
|
|
46
|
+
import process from 'node:process';
|
|
47
|
+
import { fileURLToPath } from 'node:url';
|
|
48
|
+
|
|
49
|
+
import { OBLIGATION_STATE_DIR, WRITER_ROLES, isWriterRole } from './_lib/obligations.js';
|
|
50
|
+
|
|
51
|
+
/** The reported classes: the closed vocabulary, plus the pre-field case. */
|
|
52
|
+
export const REPORTED_CLASSES = [...WRITER_ROLES, 'absent'] as const;
|
|
53
|
+
export type ReportedClass = (typeof REPORTED_CLASSES)[number];
|
|
54
|
+
|
|
55
|
+
/** The three row arrays a ledger carries, named as the file names them. */
|
|
56
|
+
export const ROW_ARRAYS = ['delivered', 'discharged', 'shadow'] as const;
|
|
57
|
+
export type RowArray = (typeof ROW_ARRAYS)[number];
|
|
58
|
+
|
|
59
|
+
export type Tally = Record<ReportedClass, number>;
|
|
60
|
+
|
|
61
|
+
export interface WriterSplit {
|
|
62
|
+
/** The directory scanned, echoed so a reader knows what was measured. */
|
|
63
|
+
readonly store: string;
|
|
64
|
+
/** `false` when the ledger directory does not exist at all. */
|
|
65
|
+
readonly storeExists: boolean;
|
|
66
|
+
/** Ledger files opened and parsed. */
|
|
67
|
+
readonly ledgers: number;
|
|
68
|
+
/** Files present but unreadable or unparseable — reported, never silently dropped. */
|
|
69
|
+
readonly unreadable: number;
|
|
70
|
+
/** Per row array, the split by writer class. */
|
|
71
|
+
readonly byArray: Record<RowArray, Tally>;
|
|
72
|
+
/** Every array folded together. */
|
|
73
|
+
readonly total: Tally;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function emptyTally(): Tally {
|
|
77
|
+
return { package: 0, consumer: 0, unknown: 0, absent: 0 };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Classify one row's writer field.
|
|
82
|
+
*
|
|
83
|
+
* A field that is missing entirely is `absent`. A field that is present but
|
|
84
|
+
* outside the closed vocabulary is `unknown`, matching `parseRows`: a corrupt
|
|
85
|
+
* provenance label degrades, it never deletes the record of a real row.
|
|
86
|
+
*/
|
|
87
|
+
export function classifyRow(row: unknown): ReportedClass {
|
|
88
|
+
if (typeof row !== 'object' || row === null) return 'absent';
|
|
89
|
+
if (!('writer' in row)) return 'absent';
|
|
90
|
+
const writer = (row as { writer: unknown }).writer;
|
|
91
|
+
return isWriterRole(writer) ? writer : 'unknown';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Tally one ledger's arrays into an accumulator. */
|
|
95
|
+
function tallyLedger(doc: unknown, into: Record<RowArray, Tally>): void {
|
|
96
|
+
if (typeof doc !== 'object' || doc === null) return;
|
|
97
|
+
for (const name of ROW_ARRAYS) {
|
|
98
|
+
const rows = (doc as Record<string, unknown>)[name];
|
|
99
|
+
if (!Array.isArray(rows)) continue;
|
|
100
|
+
for (const row of rows) into[name][classifyRow(row)] += 1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Read every ledger under `root` and split its rows by writer class.
|
|
106
|
+
*
|
|
107
|
+
* Opens files for reading only. A file that will not parse increments
|
|
108
|
+
* `unreadable` rather than being skipped in silence — a corpus with unreadable
|
|
109
|
+
* members is a different corpus from a clean one, and a reader deciding whether
|
|
110
|
+
* a sample floor is met needs to know which they have.
|
|
111
|
+
*/
|
|
112
|
+
export function readWriterSplit(root: string): WriterSplit {
|
|
113
|
+
const store = path.join(root, OBLIGATION_STATE_DIR);
|
|
114
|
+
const byArray: Record<RowArray, Tally> = {
|
|
115
|
+
delivered: emptyTally(),
|
|
116
|
+
discharged: emptyTally(),
|
|
117
|
+
shadow: emptyTally(),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
let entries: string[];
|
|
121
|
+
try {
|
|
122
|
+
entries = fs.readdirSync(store).filter((f) => f.endsWith('.json'));
|
|
123
|
+
} catch {
|
|
124
|
+
return { store, storeExists: false, ledgers: 0, unreadable: 0, byArray, total: emptyTally() };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let ledgers = 0;
|
|
128
|
+
let unreadable = 0;
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
let doc: unknown;
|
|
131
|
+
try {
|
|
132
|
+
doc = JSON.parse(fs.readFileSync(path.join(store, entry), 'utf-8'));
|
|
133
|
+
} catch {
|
|
134
|
+
unreadable += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
ledgers += 1;
|
|
138
|
+
tallyLedger(doc, byArray);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const total = emptyTally();
|
|
142
|
+
for (const name of ROW_ARRAYS) {
|
|
143
|
+
for (const cls of REPORTED_CLASSES) total[cls] += byArray[name][cls];
|
|
144
|
+
}
|
|
145
|
+
return { store, storeExists: true, ledgers, unreadable, byArray, total };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const sum = (t: Tally): number => REPORTED_CLASSES.reduce((n, c) => n + t[c], 0);
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Render the split as text.
|
|
152
|
+
*
|
|
153
|
+
* The line a reader is most likely to quote is the shadow row, so it is named
|
|
154
|
+
* rather than left to be inferred from a table: the pre-registered bar counts
|
|
155
|
+
* shadow rows and nothing else, and a split over `delivered` answers a question
|
|
156
|
+
* the bar did not ask.
|
|
157
|
+
*/
|
|
158
|
+
export function render(split: WriterSplit): string {
|
|
159
|
+
const out: string[] = [];
|
|
160
|
+
out.push(`scanned: ${split.store}`);
|
|
161
|
+
if (!split.storeExists) {
|
|
162
|
+
out.push(' the ledger directory does not exist — nothing was measured.');
|
|
163
|
+
out.push(' This is not a reading of zero. It is the absence of a corpus.');
|
|
164
|
+
return `${out.join('\n')}\n`;
|
|
165
|
+
}
|
|
166
|
+
out.push(` ledgers: ${split.ledgers}${split.unreadable > 0 ? `, unreadable: ${split.unreadable}` : ''}`);
|
|
167
|
+
if (split.ledgers === 0) {
|
|
168
|
+
out.push(' no ledger files — the directory exists and holds nothing.');
|
|
169
|
+
return `${out.join('\n')}\n`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const width = Math.max(...ROW_ARRAYS.map((n) => n.length));
|
|
173
|
+
out.push('');
|
|
174
|
+
out.push(`${'rows'.padEnd(width)} ${REPORTED_CLASSES.map((c) => c.padStart(9)).join('')} total`);
|
|
175
|
+
for (const name of ROW_ARRAYS) {
|
|
176
|
+
const t = split.byArray[name];
|
|
177
|
+
const cells = REPORTED_CLASSES.map((c) => String(t[c]).padStart(9)).join('');
|
|
178
|
+
out.push(`${name.padEnd(width)} ${cells} ${String(sum(t)).padStart(7)}`);
|
|
179
|
+
}
|
|
180
|
+
const cells = REPORTED_CLASSES.map((c) => String(split.total[c]).padStart(9)).join('');
|
|
181
|
+
out.push(`${'all'.padEnd(width)} ${cells} ${String(sum(split.total)).padStart(7)}`);
|
|
182
|
+
|
|
183
|
+
out.push('');
|
|
184
|
+
out.push(
|
|
185
|
+
`shadow rows — the only array the pre-registered bar counts: ${sum(split.byArray.shadow)}`,
|
|
186
|
+
);
|
|
187
|
+
out.push(
|
|
188
|
+
'`absent` is a row written before the writer field existed; `unknown` is a row whose',
|
|
189
|
+
);
|
|
190
|
+
out.push('writer was resolved and came back unresolvable. They are not the same reading.');
|
|
191
|
+
out.push('');
|
|
192
|
+
out.push('This is a split, not a verdict. Whether the corpus is fit to read the bar off,');
|
|
193
|
+
out.push('and what follows for the detector, are owner decisions this tool does not make.');
|
|
194
|
+
return `${out.join('\n')}\n`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Read one flag's value, refusing a flag whose value is missing.
|
|
199
|
+
*
|
|
200
|
+
* A flag present as the last argv element must be a usage error and never a
|
|
201
|
+
* silent fall back to the default. The same slip in a sibling reporter measured
|
|
202
|
+
* the DEFAULT corpus while printing what read as a settled number — a confident
|
|
203
|
+
* figure from a tree nobody asked for is worse than no figure at all.
|
|
204
|
+
*/
|
|
205
|
+
function argValue(argv: string[], flag: string, fallback: string): string {
|
|
206
|
+
const i = argv.indexOf(flag);
|
|
207
|
+
if (i === -1) return fallback;
|
|
208
|
+
const value = argv[i + 1];
|
|
209
|
+
if (value === undefined || value.startsWith('--')) {
|
|
210
|
+
process.stderr.write(`report_obligation_writer_split: ${flag} needs a value\n`);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function main(argv: string[]): number {
|
|
217
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
218
|
+
process.stdout.write(
|
|
219
|
+
'usage: report_obligation_writer_split [--root <dir>] [--json]\n\n' +
|
|
220
|
+
' --root <dir> tree whose agents/runtime/state/obligations/ to read (default: cwd)\n' +
|
|
221
|
+
' --json emit the split as JSON instead of text\n\n' +
|
|
222
|
+
'Read-only. Writes nothing, gates nothing, exits 0.\n',
|
|
223
|
+
);
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
const root = argValue(argv, '--root', process.cwd());
|
|
227
|
+
const split = readWriterSplit(root);
|
|
228
|
+
process.stdout.write(argv.includes('--json') ? `${JSON.stringify(split, null, 2)}\n` : render(split));
|
|
229
|
+
return 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
233
|
+
|
|
234
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(_HERE)) {
|
|
235
|
+
process.exit(main(process.argv.slice(2)));
|
|
236
|
+
}
|