@event4u/agent-config 14.12.0 → 14.13.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 +234 -0
- package/CONTRIBUTING.md +38 -0
- package/CREDITS.md +135 -0
- package/NOTICE +13 -0
- package/README.md +8 -6
- package/dist/agent-src/commands/analyze/inbox.md +109 -2
- package/dist/agent-src/commands/feature/dev.md +7 -2
- package/dist/agent-src/commands/ghostwriter/write.md +5 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/orchestrate.md +2 -2
- package/dist/agent-src/commands/post-as/me.md +5 -1
- package/dist/agent-src/commands/pr/merge.md +19 -6
- package/dist/agent-src/commands/roadmap/process-full.md +19 -5
- package/dist/agent-src/commands/tdd/red.md +12 -2
- package/dist/agent-src/commands/work.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
- package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
- package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
- package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/code-provenance.md +4 -0
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +4 -0
- package/dist/agent-src/rules/domain-safety-retention.md +4 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
- package/dist/agent-src/rules/improve-before-implement.md +6 -8
- package/dist/agent-src/rules/laravel-routing.md +1 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +12 -34
- package/dist/agent-src/rules/symfony-routing.md +1 -1
- package/dist/agent-src/rules/token-efficiency.md +14 -0
- package/dist/agent-src/rules/tool-safety.md +4 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
- package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
- package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/dist/agent-src/scripts/stub_queue.ts +82 -0
- package/dist/agent-src/scripts/stubs_due.ts +400 -0
- package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
- package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
- package/dist/agent-src/skills/database/SKILL.md +8 -0
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
- package/dist/agent-src/skills/design-review/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
- package/dist/agent-src/skills/laravel/SKILL.md +35 -0
- package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
- package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
- package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
- package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
- package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +97 -3
- package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
- package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/dist/cli/commands/uiAudit.js +124 -5
- package/dist/cli/registry.js +2 -0
- package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
- package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
- package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
- package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
- package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
- package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
- package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
- package/dist/cli-delegate/cmd_adr_effective.js +102 -0
- package/dist/cli-delegate/cmd_conformance.js +42 -10
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +3 -2
- package/dist/cli-delegate/cmd_fleet.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +3 -2
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
- package/dist/cli-delegate/cmd_settings_set.js +2 -2
- package/dist/cli-delegate/cmd_sync.js +3 -2
- package/dist/cli-delegate/cmd_uninstall.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +3 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +57 -57
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1836 -712
- package/dist/install/claudeRuleRewrite.js +254 -0
- package/dist/install/detect.js +29 -16
- package/dist/install/detect_php_shape.js +159 -0
- package/dist/install/install.mjs +634 -428
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +3 -3
- package/dist/mcp/server.mjs +4818 -2645
- package/dist/server/schemas/settings.js +3 -0
- package/dist/ui/assets/index-D0jaCRPM.js +29 -0
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/THIRD-PARTY-NOTICES.md +25 -0
- package/docs/contracts/provider-lifecycle.md +1 -1
- package/docs/contracts/settings-classes.md +10 -4
- package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
- package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
- package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
- package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
- package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
- package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
- package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
- package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
- package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
- package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
- package/docs/guidelines/agent-infra/first-principles.md +2 -2
- package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
- package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
- package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
- package/docs/guidelines/agent-infra/layered-settings.md +10 -10
- package/docs/guidelines/agent-infra/memory-access.md +1 -1
- package/docs/guidelines/agent-infra/mental-models.md +3 -3
- package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
- package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
- package/docs/guidelines/agent-infra/role-contracts.md +2 -2
- package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
- package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
- package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
- package/docs/guidelines/agent-infra/six-hats.md +3 -3
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
- package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
- package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +6 -4
- package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
- package/docs/guidelines/cross-role-handoff.md +2 -2
- package/docs/guidelines/design-fidelity-mechanics.md +1 -1
- package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
- package/docs/guidelines/php/database.md +90 -7
- package/docs/guidelines/prompt-templates.md +7 -7
- package/llms.txt +2 -2
- package/package.json +5 -2
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
- package/src/agent-src/scripts/guarded_baseline.ts +328 -0
- package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/src/agent-src/scripts/stub_queue.ts +82 -0
- package/src/agent-src/scripts/stubs_due.ts +400 -0
- package/src/agent-src/scripts/ticket_bundles.ts +84 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
- package/src/agent-src/templates/scripts/check_memory.ts +258 -17
- package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/src/config/agent-settings.template.yml +32 -3
- package/src/config/assurance-capability-registry.json +21 -9
- package/src/config/canonical-terms.yml +119 -0
- package/src/config/capability-native-outcome-bars.json +81 -0
- package/src/config/ci-local-parity.yml +80 -0
- package/src/config/drafting-channels.yml +43 -0
- package/src/config/estate-count-budget.json +38 -36
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +579 -63
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +37 -19
- package/src/config/harness-evolution-budget.json +25 -0
- package/src/config/lapsed-beta-baseline.json +96 -0
- package/src/config/memory-twin-verdicts.yml +129 -0
- package/src/config/metric-registry.yml +124 -0
- package/src/config/pack-size-budget.json +16 -15
- package/src/config/preamble-payload-budget.json +8 -8
- package/src/config/profiles/balanced.ini +27 -0
- package/src/config/profiles/full.ini +27 -0
- package/src/config/profiles/minimal.ini +27 -0
- package/src/config/publish-surface.json +9 -2
- package/src/config/routing-coverage-seed.json +16 -2
- package/src/config/rule-stub-ceilings.json +126 -112
- package/src/config/turnaround-budget.json +66 -0
- package/src/install/claudeRuleRewrite.ts +288 -0
- package/src/install/detect.ts +60 -17
- package/src/install/detect_php_shape.ts +191 -0
- package/src/scripts/_cli/cmd_doctor.ts +27 -112
- package/src/scripts/_dispatch.bash +27 -0
- package/src/scripts/_lib/activation_ladder.ts +211 -0
- package/src/scripts/_lib/activation_states.ts +88 -0
- package/src/scripts/_lib/adherence_detectors.ts +143 -0
- package/src/scripts/_lib/arith_claims.ts +181 -0
- package/src/scripts/_lib/arm_ranking.ts +62 -0
- package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
- package/src/scripts/_lib/audit_field_provenance.ts +54 -0
- package/src/scripts/_lib/auto_dispatch.ts +32 -3
- package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
- package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
- package/src/scripts/_lib/candidate_proposer.ts +402 -0
- package/src/scripts/_lib/candidate_record.ts +601 -0
- package/src/scripts/_lib/capture_rate.ts +319 -0
- package/src/scripts/_lib/collector_denominator.ts +771 -0
- package/src/scripts/_lib/collector_record.ts +340 -0
- package/src/scripts/_lib/collector_store.ts +664 -0
- package/src/scripts/_lib/collector_supervision.ts +827 -0
- package/src/scripts/_lib/concern_estate.ts +77 -0
- package/src/scripts/_lib/config_chain.ts +477 -0
- package/src/scripts/_lib/config_cost.ts +209 -0
- package/src/scripts/_lib/council_settings_block.ts +6 -0
- package/src/scripts/_lib/curator_ops.ts +172 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
- package/src/scripts/_lib/delivery_criticality.ts +126 -0
- package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
- package/src/scripts/_lib/empty_cycles.ts +88 -0
- package/src/scripts/_lib/eval_publication.ts +354 -0
- package/src/scripts/_lib/evaluation_vector.ts +283 -0
- package/src/scripts/_lib/evaluator_promotion.ts +225 -0
- package/src/scripts/_lib/evidence_basis.ts +118 -0
- package/src/scripts/_lib/exec_evidence.ts +8 -0
- package/src/scripts/_lib/experience_card.ts +272 -0
- package/src/scripts/_lib/experience_report.ts +151 -0
- package/src/scripts/_lib/experiment_freeze.ts +112 -0
- package/src/scripts/_lib/generated_by.ts +66 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
- package/src/scripts/_lib/hook_effect_probe.ts +141 -0
- package/src/scripts/_lib/host_denominator.ts +687 -0
- package/src/scripts/_lib/host_projection_reach.ts +157 -0
- package/src/scripts/_lib/ignored_blocker.ts +148 -0
- package/src/scripts/_lib/install_reach_checks.ts +495 -0
- package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
- package/src/scripts/_lib/judge_hygiene.ts +228 -0
- package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
- package/src/scripts/_lib/loop_guards.ts +299 -0
- package/src/scripts/_lib/loss_class.ts +129 -0
- package/src/scripts/_lib/machine_wake.ts +51 -0
- package/src/scripts/_lib/md_prose_lines.ts +177 -0
- package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
- package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
- package/src/scripts/_lib/orchestration_record.ts +253 -5
- package/src/scripts/_lib/outcome_envelope.ts +227 -0
- package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
- package/src/scripts/_lib/paired_stats.ts +245 -0
- package/src/scripts/_lib/paired_verdict.ts +226 -0
- package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
- package/src/scripts/_lib/privacy_class.ts +47 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
- package/src/scripts/_lib/repeated_failure.ts +105 -0
- package/src/scripts/_lib/repo_root.ts +111 -0
- package/src/scripts/_lib/review_skipped_record.ts +37 -0
- package/src/scripts/_lib/role_split.ts +338 -0
- package/src/scripts/_lib/runtime_journal.ts +1499 -0
- package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
- package/src/scripts/_lib/skill_catalogue.ts +11 -1
- package/src/scripts/_lib/source_digest.ts +200 -0
- package/src/scripts/_lib/source_redact.ts +260 -0
- package/src/scripts/_lib/source_shape.ts +502 -0
- package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
- package/src/scripts/_lib/strip_comments.d.mts +8 -0
- package/src/scripts/_lib/strip_comments.mjs +65 -0
- package/src/scripts/_lib/test_red_state.ts +154 -0
- package/src/scripts/_lib/trigger_shift.ts +144 -0
- package/src/scripts/_lib/untrusted_content.ts +82 -7
- package/src/scripts/adoption_report.ts +1 -1
- package/src/scripts/adr/evidence_census.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +26 -2
- package/src/scripts/adr_cite_check.ts +164 -1
- package/src/scripts/ai_council/blind_review.ts +11 -1
- package/src/scripts/ai_council/clients.ts +4 -0
- package/src/scripts/ai_council/config.ts +3 -0
- package/src/scripts/ai_council/consensus.ts +28 -8
- package/src/scripts/ai_council/consensus_round.ts +226 -0
- package/src/scripts/ai_council/disagreement_signal.ts +338 -0
- package/src/scripts/ai_council/inline_findings.ts +340 -0
- package/src/scripts/ai_council/judge_position_bias.ts +197 -0
- package/src/scripts/ai_council/orchestrator.ts +16 -203
- package/src/scripts/ai_council/orchestrator_results.ts +23 -3
- package/src/scripts/ai_council/pricing.ts +106 -0
- package/src/scripts/ai_council/prompts.ts +74 -7
- package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
- package/src/scripts/ai_council/py_format.ts +14 -3
- package/src/scripts/ai_council/recouncil_guard.ts +293 -0
- package/src/scripts/ai_council/response_record.ts +50 -0
- package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
- package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
- package/src/scripts/asset_delivery_ledger.ts +157 -0
- package/src/scripts/attest_artifact.ts +193 -0
- package/src/scripts/audit_auto_rules.ts +2 -1
- package/src/scripts/audit_command_surface.ts +1 -1
- package/src/scripts/audit_mcp_tools.ts +2 -2
- package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
- package/src/scripts/audit_user_type_axis.ts +2 -1
- package/src/scripts/bench_ab_clone.ts +215 -10
- package/src/scripts/bench_ab_integrity.ts +119 -5
- package/src/scripts/bench_ab_v2_stats.ts +40 -213
- package/src/scripts/build_archive_index.ts +1 -1
- package/src/scripts/build_linear_digest.ts +1 -1
- package/src/scripts/build_proof.ts +11 -4
- package/src/scripts/build_rule_trigger_matrix.ts +1 -1
- package/src/scripts/build_source_digests.ts +157 -0
- package/src/scripts/cache_realization_report.ts +103 -0
- package/src/scripts/check_adr_frontmatter.ts +126 -0
- package/src/scripts/check_benchmark_report_fields.ts +207 -0
- package/src/scripts/check_beta_review_markers.ts +235 -6
- package/src/scripts/check_bundle_path_leakage.ts +34 -1
- package/src/scripts/check_claims.ts +576 -6
- package/src/scripts/check_composite_arming.ts +35 -0
- package/src/scripts/check_concern_admissions.ts +365 -0
- package/src/scripts/check_enforcement_coverage.ts +28 -0
- package/src/scripts/check_estate_count.ts +142 -1
- package/src/scripts/check_gate_reachability.ts +383 -0
- package/src/scripts/check_host_loadability.ts +104 -0
- package/src/scripts/check_loss_class_declared.ts +308 -0
- package/src/scripts/check_md_language.ts +15 -98
- package/src/scripts/check_memory_proposal.ts +18 -11
- package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
- package/src/scripts/check_no_external_sources.ts +281 -6
- package/src/scripts/check_pack_conformance_fixture.ts +11 -1
- package/src/scripts/check_pack_size.ts +59 -2
- package/src/scripts/check_preamble_payload_budget.ts +114 -3
- package/src/scripts/check_prefix_stable_mutation.ts +372 -0
- package/src/scripts/check_publish_surface.ts +10 -1
- package/src/scripts/check_references.ts +24 -1
- package/src/scripts/check_rule_evidence_declaration.ts +316 -0
- package/src/scripts/check_rule_projection_integrity.ts +14 -4
- package/src/scripts/check_score_contract.ts +26 -3
- package/src/scripts/check_static_parity.ts +285 -0
- package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
- package/src/scripts/check_suppression_hygiene.ts +15 -0
- package/src/scripts/ci_settle.ts +39 -2
- package/src/scripts/code_graph/build.ts +60 -3
- package/src/scripts/code_graph/extract.ts +44 -0
- package/src/scripts/code_graph/types.ts +24 -0
- package/src/scripts/collector_daemon.ts +714 -0
- package/src/scripts/config_cost_report.ts +302 -0
- package/src/scripts/consumer_matrix.ts +74 -1
- package/src/scripts/cost/budget.mjs +10 -3
- package/src/scripts/cost/track.mjs +10 -3
- package/src/scripts/council_cli.ts +37 -54
- package/src/scripts/dispatch_r2_reviewer.ts +46 -5
- package/src/scripts/evolution_lab.ts +980 -0
- package/src/scripts/external_sources_denylist.json +5 -18
- package/src/scripts/extract_audit_patterns.ts +21 -0
- package/src/scripts/fold_intake.ts +12 -1
- package/src/scripts/gen_discovery_baseline.ts +1 -1
- package/src/scripts/generate_capabilities_index.ts +12 -5
- package/src/scripts/generate_capability_matrix.ts +3 -3
- package/src/scripts/generate_command_flows.ts +2 -2
- package/src/scripts/generate_cookbook.ts +2 -2
- package/src/scripts/generate_index.ts +8 -1
- package/src/scripts/generate_knowledge_index.ts +2 -1
- package/src/scripts/generate_ownership_matrix.ts +2 -1
- package/src/scripts/generate_pack_manifests.ts +10 -2
- package/src/scripts/generate_role_experiences_catalog.ts +2 -2
- package/src/scripts/generate_settings_reference.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +22 -1
- package/src/scripts/grade_target_readiness.ts +48 -5
- package/src/scripts/hook_effect_doctor.ts +261 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +98 -11
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
- package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/dispatch_hook.ts +32 -0
- package/src/scripts/hooks/journal_record_hook.ts +345 -0
- package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
- package/src/scripts/hooks/run_continuation_hook.ts +44 -9
- package/src/scripts/hooks/shims/install.sh +61 -0
- package/src/scripts/hooks/shims/php +101 -0
- package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
- package/src/scripts/hot_context_hook.ts +16 -0
- package/src/scripts/install-hooks.sh +20 -5
- package/src/scripts/install.ts +17 -35
- package/src/scripts/inventory_frontmatter.ts +2 -1
- package/src/scripts/lint_adr_sweep_routing.ts +12 -0
- package/src/scripts/lint_canonical_terms.ts +604 -0
- package/src/scripts/lint_composition_review.ts +619 -0
- package/src/scripts/lint_consolidation_lineage.ts +666 -0
- package/src/scripts/lint_eval_specs.ts +593 -0
- package/src/scripts/lint_hook_manifest.ts +19 -0
- package/src/scripts/lint_host_portability.ts +373 -0
- package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
- package/src/scripts/lint_memory_twin_parity.ts +335 -0
- package/src/scripts/lint_metric_consumers.ts +355 -0
- package/src/scripts/lint_skill_descriptions.ts +18 -1
- package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
- package/src/scripts/lint_skill_link_reach.ts +252 -0
- package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
- package/src/scripts/lint_ticket_buildable.ts +17 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
- package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
- package/src/scripts/measure_docs_dead_links.ts +348 -0
- package/src/scripts/measure_host_capture.ts +461 -0
- package/src/scripts/migration_status.ts +3 -3
- package/src/scripts/model_rule_injection.ts +60 -0
- package/src/scripts/orchestration_record.ts +14 -0
- package/src/scripts/preamble_byte_census.ts +139 -10
- package/src/scripts/prepack-check.mjs +4 -1
- package/src/scripts/probe_turnaround.ts +384 -0
- package/src/scripts/probe_unblocked_ask.ts +279 -0
- package/src/scripts/render_benchmark_md.ts +1 -1
- package/src/scripts/rule_activation_census.ts +70 -9
- package/src/scripts/rule_backlinks.ts +1 -1
- package/src/scripts/run_lifecycle_suite.ts +208 -0
- package/src/scripts/run_skill_evals.ts +40 -0
- package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
- package/src/scripts/schemas/drafting-channels.schema.json +43 -0
- package/src/scripts/schemas/evals.schema.json +24 -1
- package/src/scripts/schemas/rule.schema.json +52 -1
- package/src/scripts/schemas/skill.schema.json +17 -2
- package/src/scripts/skill_overlap.ts +7 -1
- package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
- package/src/scripts/skill_usage_report.ts +2 -1
- package/src/scripts/stubs_due.ts +211 -0
- package/src/scripts/sweep_source_surfaces.ts +678 -0
- package/src/scripts/sync_pr_branch.ts +3 -3
- package/src/scripts/trigger_eval_grandfather.json +202 -222
- package/src/scripts/utilization_report.ts +22 -2
- package/src/server/schemas/settings.ts +5 -0
- package/src/templates/marketing-copy.yml +1 -1
- package/dist/ui/assets/index-Cxgy63kz.js +0 -26
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* collector_record — the supervised telemetry collector's data contract
|
|
3
|
+
* (`road-to-supervised-telemetry-collector` Phase 2.1).
|
|
4
|
+
*
|
|
5
|
+
* ## Why an allowlist and not a scrubber
|
|
6
|
+
*
|
|
7
|
+
* "No free-form field" is necessary and **not sufficient**. A council seat
|
|
8
|
+
* enumerated the leaks that *structured* fields still carry, and each one is
|
|
9
|
+
* defended against here by construction rather than by a cleaning pass:
|
|
10
|
+
*
|
|
11
|
+
* | Leak class | How this schema refuses it |
|
|
12
|
+
* |---|---|
|
|
13
|
+
* | Repository / worktree identifiers | No field can hold a path, a repo name, a branch or a remote. There is nothing to scrub. |
|
|
14
|
+
* | Command names and arguments | No field can hold a command. `event` is a closed enum of hook events, not an invocation. |
|
|
15
|
+
* | Error enums with interpolated values | `outcome` is a closed enum with no payload. An error carries its CLASS and never its text. |
|
|
16
|
+
* | Hashes stable enough to identify a user or repo | `machine_id` and `episode_id` are locally generated random ids, never derived from hostname, username, repo path or any host fact. A derived id is a pseudonym for the thing it derives from. |
|
|
17
|
+
* | Timestamps + a machine identifier | `occurred_on` is a UTC **date**, never a precise time. A per-second timestamp beside a stable machine id is a behavioural fingerprint — it reconstructs working hours, session lengths and idle gaps. |
|
|
18
|
+
*
|
|
19
|
+
* This is the same PII-exclusion-by-construction principle the package already
|
|
20
|
+
* applies to its telemetry events: a type that CANNOT hold a phone number needs
|
|
21
|
+
* no scrubber that might fail. Widening this record with a `payload`, `notes`,
|
|
22
|
+
* `context` or `extra: unknown` field would void the entire argument, and the
|
|
23
|
+
* unknown-key rejection below exists to make that impossible by accident.
|
|
24
|
+
*
|
|
25
|
+
* ## Unknown fields are REJECTED, never dropped
|
|
26
|
+
*
|
|
27
|
+
* Dropping is the dangerous default. A producer that adds `repo_path` and sees
|
|
28
|
+
* its records accepted has been told the field is fine; the leak then lives in
|
|
29
|
+
* the producer, where this schema cannot see it, and the next reader of the
|
|
30
|
+
* store finds a clean record and a dirty writer. Rejection turns that into a
|
|
31
|
+
* loud failure at the boundary, which is where it is cheap.
|
|
32
|
+
*
|
|
33
|
+
* ## What this module does NOT do
|
|
34
|
+
*
|
|
35
|
+
* It does not write, store, transmit or aggregate anything. It is the contract
|
|
36
|
+
* only. Deletion and opt-out are 2.3; the upgrade/rollback transitions are 2.4;
|
|
37
|
+
* the collector itself is Phase 4 and is default-off.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** Hook events, mirroring `dispatch_hook.EVENT_VOCABULARY`. Closed. */
|
|
41
|
+
export const COLLECTOR_EVENTS = [
|
|
42
|
+
'session_start',
|
|
43
|
+
'session_end',
|
|
44
|
+
'user_prompt_submit',
|
|
45
|
+
'pre_tool_use',
|
|
46
|
+
'post_tool_use',
|
|
47
|
+
'stop',
|
|
48
|
+
'pre_compact',
|
|
49
|
+
'agent_error',
|
|
50
|
+
'subagent_start',
|
|
51
|
+
'subagent_stop',
|
|
52
|
+
] as const;
|
|
53
|
+
export type CollectorEvent = (typeof COLLECTOR_EVENTS)[number];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Terminal states of a capture attempt. Closed, and deliberately three.
|
|
57
|
+
*
|
|
58
|
+
* Metric definition item 5 requires that a startup failure be distinguishable
|
|
59
|
+
* from a write loss: "a 40 % rate made of startup failures and a 40 % rate made
|
|
60
|
+
* of write losses call for different fixes and the single ratio cannot
|
|
61
|
+
* distinguish them". A single `ok: boolean` would collapse exactly that.
|
|
62
|
+
*/
|
|
63
|
+
export const COLLECTOR_OUTCOMES = ['captured', 'startup_failure', 'write_failure'] as const;
|
|
64
|
+
export type CollectorOutcome = (typeof COLLECTOR_OUTCOMES)[number];
|
|
65
|
+
|
|
66
|
+
/** Host platforms. Closed — a free string here would carry an arbitrary label. */
|
|
67
|
+
export const COLLECTOR_PLATFORMS = [
|
|
68
|
+
'augment',
|
|
69
|
+
'claude',
|
|
70
|
+
'cline',
|
|
71
|
+
'copilot',
|
|
72
|
+
'cowork',
|
|
73
|
+
'cursor',
|
|
74
|
+
'gemini',
|
|
75
|
+
'windsurf',
|
|
76
|
+
] as const;
|
|
77
|
+
export type CollectorPlatform = (typeof COLLECTOR_PLATFORMS)[number];
|
|
78
|
+
|
|
79
|
+
/** The current record schema version. Bumped by a 2.4 migration, never silently. */
|
|
80
|
+
export const COLLECTOR_SCHEMA_VERSION = 1;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* One capture record. Every field is listed in {@link FIELD_PURPOSE} with its
|
|
84
|
+
* purpose, its cardinality limit and why a coarser form does not suffice.
|
|
85
|
+
*
|
|
86
|
+
* There is no index signature, and adding one would defeat the schema.
|
|
87
|
+
*/
|
|
88
|
+
export interface CollectorRecord {
|
|
89
|
+
schema_version: number;
|
|
90
|
+
machine_id: string;
|
|
91
|
+
episode_id: string;
|
|
92
|
+
event: CollectorEvent;
|
|
93
|
+
sequence: number;
|
|
94
|
+
outcome: CollectorOutcome;
|
|
95
|
+
platform: CollectorPlatform;
|
|
96
|
+
occurred_on: string;
|
|
97
|
+
collector_version: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface FieldContract {
|
|
101
|
+
/** What the metric needs this field FOR. A field with no purpose is removed. */
|
|
102
|
+
purpose: string;
|
|
103
|
+
/** The bound on distinct values, and what enforces it. */
|
|
104
|
+
cardinality: string;
|
|
105
|
+
/** Why a coarser or absent form does not suffice. */
|
|
106
|
+
why_not_coarser: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The per-field contract. Step 2.1 requires every field to carry all three
|
|
111
|
+
* lines; `collector_record.test.ts` asserts the keys here are exactly the keys
|
|
112
|
+
* of the record, so a field cannot be added without stating its purpose.
|
|
113
|
+
*/
|
|
114
|
+
export const FIELD_PURPOSE: Readonly<Record<keyof CollectorRecord, FieldContract>> = {
|
|
115
|
+
schema_version: {
|
|
116
|
+
purpose: 'Selects the migration path when an older package meets a newer record (2.4).',
|
|
117
|
+
cardinality: 'One small integer per shipped schema. Currently 1.',
|
|
118
|
+
why_not_coarser:
|
|
119
|
+
'Absent, a rollback cannot tell a record it can read from one it must quarantine.',
|
|
120
|
+
},
|
|
121
|
+
machine_id: {
|
|
122
|
+
purpose:
|
|
123
|
+
'Satisfies the population floor and concentration cap of metric item 7 — at least ' +
|
|
124
|
+
'five distinct machines, no single machine over 40 % of the denominator.',
|
|
125
|
+
cardinality: 'One per machine per rotation. A locally generated random UUID.',
|
|
126
|
+
why_not_coarser:
|
|
127
|
+
'Without a per-machine key the concentration cap is unmeasurable, and a rate ' +
|
|
128
|
+
'measured on one laptop would report that laptop as the population. It is random ' +
|
|
129
|
+
'rather than derived precisely so it identifies a COUNTING UNIT and not a person: ' +
|
|
130
|
+
'a hash of hostname, username or repo path is a pseudonym for those things and ' +
|
|
131
|
+
'is re-identifiable by anyone holding the same inputs.',
|
|
132
|
+
},
|
|
133
|
+
episode_id: {
|
|
134
|
+
purpose: 'Part of the deduplication key of metric item 4; scopes `sequence`.',
|
|
135
|
+
cardinality: 'One per session. Locally generated random UUID, never reused.',
|
|
136
|
+
why_not_coarser:
|
|
137
|
+
'Without it, `sequence` has no scope and two sessions on one machine collide, ' +
|
|
138
|
+
'which would silently merge two episodes into one and under-count the denominator.',
|
|
139
|
+
},
|
|
140
|
+
event: {
|
|
141
|
+
purpose: 'Which (platform, event) cell the dispatch belonged to.',
|
|
142
|
+
cardinality: `Closed enum, ${COLLECTOR_EVENTS.length} values.`,
|
|
143
|
+
why_not_coarser:
|
|
144
|
+
'Per-cell capture is the whole point — an aggregate rate cannot show that one ' +
|
|
145
|
+
'event is never captured while the total looks healthy. It is an enum rather ' +
|
|
146
|
+
'than a string so no interpolated value can ride along inside it.',
|
|
147
|
+
},
|
|
148
|
+
sequence: {
|
|
149
|
+
purpose: 'Part of the deduplication key of metric item 4; orders records in an episode.',
|
|
150
|
+
cardinality: 'Monotonic non-negative integer within one episode.',
|
|
151
|
+
why_not_coarser:
|
|
152
|
+
'Deduplication happens at READ time by design, so a duplicate must remain ' +
|
|
153
|
+
'observable as a defect; without a sequence a retried write is indistinguishable ' +
|
|
154
|
+
'from a second real dispatch and would inflate the numerator.',
|
|
155
|
+
},
|
|
156
|
+
outcome: {
|
|
157
|
+
purpose: 'Metric item 5 — separates a missed capture from a failed start.',
|
|
158
|
+
cardinality: `Closed enum, ${COLLECTOR_OUTCOMES.length} values.`,
|
|
159
|
+
why_not_coarser:
|
|
160
|
+
'A boolean collapses the two failure modes the metric definition explicitly ' +
|
|
161
|
+
'requires to stay apart, because they call for different fixes. The enum carries ' +
|
|
162
|
+
'no payload, so an error class can never smuggle its message.',
|
|
163
|
+
},
|
|
164
|
+
platform: {
|
|
165
|
+
purpose:
|
|
166
|
+
'Per-platform reporting, and the row on which the lifecycle evidence of AC-8 is ' +
|
|
167
|
+
'either verified or explicitly unverified.',
|
|
168
|
+
cardinality: `Closed enum, ${COLLECTOR_PLATFORMS.length} values.`,
|
|
169
|
+
why_not_coarser:
|
|
170
|
+
'The council resolution on `lifecycle-ci-runner-provisioning` narrows the public ' +
|
|
171
|
+
'claim to the verified platform row, so a reading that cannot be attributed to a ' +
|
|
172
|
+
'platform cannot support or refute that claim.',
|
|
173
|
+
},
|
|
174
|
+
occurred_on: {
|
|
175
|
+
purpose: 'Attributes the record to a day inside the 21-day window of metric item 8.',
|
|
176
|
+
cardinality: 'One UTC calendar date, `YYYY-MM-DD`. At most 63 distinct values per window.',
|
|
177
|
+
why_not_coarser:
|
|
178
|
+
'The window is counted in days, so a day is exactly the resolution the metric ' +
|
|
179
|
+
'needs and no more. It is NOT a timestamp on purpose: a per-second time beside a ' +
|
|
180
|
+
'stable `machine_id` reconstructs working hours, session length and idle gaps, ' +
|
|
181
|
+
'which is the timestamp-plus-identifier leak class this schema refuses.',
|
|
182
|
+
},
|
|
183
|
+
collector_version: {
|
|
184
|
+
purpose: 'Distinguishes a capture loss caused by a released defect from a host cause.',
|
|
185
|
+
cardinality: 'One per released package version.',
|
|
186
|
+
why_not_coarser:
|
|
187
|
+
'Without it a regression in one release is averaged into the window and cannot ' +
|
|
188
|
+
'be isolated to the version that caused it.',
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/** Field names the record accepts. Derived from the contract, never hand-listed. */
|
|
193
|
+
export const ALLOWED_FIELDS: ReadonlySet<string> = new Set(Object.keys(FIELD_PURPOSE));
|
|
194
|
+
|
|
195
|
+
export interface ValidationResult {
|
|
196
|
+
ok: boolean;
|
|
197
|
+
/** Every problem found, so one round-trip reports all of them. */
|
|
198
|
+
errors: string[];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A date must be REAL, not merely date-SHAPED. `2026-99-99` matches the regex
|
|
205
|
+
* above and is not a day; letting it through would put a record in no window at
|
|
206
|
+
* all while looking well-formed. Round-tripping through `Date` is what
|
|
207
|
+
* distinguishes the two — `2026-02-30` normalises to March and fails to match.
|
|
208
|
+
*/
|
|
209
|
+
function isRealDate(value: string): boolean {
|
|
210
|
+
if (!DATE_RE.test(value)) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
const d = new Date(`${value}T00:00:00Z`);
|
|
214
|
+
return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === value;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* RFC-4122 **version 4** shape. The version nibble is pinned deliberately: a v1
|
|
218
|
+
* UUID embeds a MAC address and a timestamp, and a v5 UUID is a HASH of a name
|
|
219
|
+
* in a namespace — both are derived identifiers wearing a UUID's clothes, which
|
|
220
|
+
* is exactly the leak class `machine_id` exists to avoid.
|
|
221
|
+
*
|
|
222
|
+
* Stated honestly, because a review raised it and the answer is a real limit:
|
|
223
|
+
* **syntax cannot establish randomness.** A v4-shaped value can still be
|
|
224
|
+
* produced deterministically. What this check buys is the elimination of the
|
|
225
|
+
* two derived forms that are *identifiable by construction*; the remaining
|
|
226
|
+
* guarantee has to come from the generator being trusted code, and that is a
|
|
227
|
+
* property of the (not yet written) collector, not of this validator.
|
|
228
|
+
*/
|
|
229
|
+
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
230
|
+
|
|
231
|
+
/** A package version. Bounded and shaped so the field cannot carry prose. */
|
|
232
|
+
const VERSION_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]{1,32})?$/;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Validate a candidate record against the allowlist.
|
|
236
|
+
*
|
|
237
|
+
* An unknown key is an ERROR, never a silent drop — see the module docstring.
|
|
238
|
+
*/
|
|
239
|
+
export function validateRecord(candidate: unknown): ValidationResult {
|
|
240
|
+
const errors: string[] = [];
|
|
241
|
+
|
|
242
|
+
if (typeof candidate !== 'object' || candidate === null || Array.isArray(candidate)) {
|
|
243
|
+
return { ok: false, errors: ['record must be a JSON object'] };
|
|
244
|
+
}
|
|
245
|
+
// Reject anything that is not a PLAIN object. `Object.keys` sees only own
|
|
246
|
+
// keys while `in` and property reads see inherited ones, so an object whose
|
|
247
|
+
// PROTOTYPE carries `repo_path` would pass the unknown-key sweep below and
|
|
248
|
+
// still read that value downstream. Pinning the prototype closes the gap at
|
|
249
|
+
// the boundary rather than trying to out-think it field by field.
|
|
250
|
+
const proto = Object.getPrototypeOf(candidate) as unknown;
|
|
251
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
252
|
+
return {
|
|
253
|
+
ok: false,
|
|
254
|
+
errors: [
|
|
255
|
+
'record must be a plain object — a prototype can carry fields the ' +
|
|
256
|
+
'own-key scan cannot see',
|
|
257
|
+
],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const rec = candidate as Record<string, unknown>;
|
|
261
|
+
|
|
262
|
+
for (const key of Object.keys(rec)) {
|
|
263
|
+
if (!ALLOWED_FIELDS.has(key)) {
|
|
264
|
+
errors.push(
|
|
265
|
+
`unknown field '${key}' — REJECTED, not dropped. Every field must be declared ` +
|
|
266
|
+
`in FIELD_PURPOSE with a purpose, a cardinality limit and why a coarser ` +
|
|
267
|
+
`form does not suffice.`,
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const key of ALLOWED_FIELDS) {
|
|
272
|
+
// `key in rec` is TRUE for a key present with an `undefined` value, and
|
|
273
|
+
// every type guard below is `!== undefined`-gated — so testing presence
|
|
274
|
+
// alone let `{ platform: undefined }` through with no constraint applied
|
|
275
|
+
// at all. Explicit-undefined is treated as missing, which is what it is.
|
|
276
|
+
if (!(key in rec) || rec[key] === undefined) {
|
|
277
|
+
errors.push(`missing required field '${key}'`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (rec.schema_version !== undefined && rec.schema_version !== COLLECTOR_SCHEMA_VERSION) {
|
|
282
|
+
// Any-integer was too weak: -50 and 999999 both passed, and a record
|
|
283
|
+
// claiming an unshipped version is a migration decision, not a datum.
|
|
284
|
+
errors.push(
|
|
285
|
+
`schema_version must be ${COLLECTOR_SCHEMA_VERSION} — the only shipped schema. ` +
|
|
286
|
+
`A record naming another version is handled by the 2.4 migration path, ` +
|
|
287
|
+
`not accepted here.`,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
for (const key of ['machine_id', 'episode_id'] as const) {
|
|
291
|
+
const v = rec[key];
|
|
292
|
+
if (v !== undefined && (typeof v !== 'string' || !UUID_V4_RE.test(v))) {
|
|
293
|
+
errors.push(
|
|
294
|
+
`${key} must be a locally generated random UUID — a value derived from a ` +
|
|
295
|
+
`hostname, username or repository path is a pseudonym for it, not an ` +
|
|
296
|
+
`anonymous counting key`,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (rec.event !== undefined && !(COLLECTOR_EVENTS as readonly string[]).includes(rec.event as string)) {
|
|
301
|
+
errors.push(`event must be one of the ${COLLECTOR_EVENTS.length} declared hook events`);
|
|
302
|
+
}
|
|
303
|
+
if (rec.outcome !== undefined && !(COLLECTOR_OUTCOMES as readonly string[]).includes(rec.outcome as string)) {
|
|
304
|
+
errors.push(`outcome must be one of: ${COLLECTOR_OUTCOMES.join(', ')}`);
|
|
305
|
+
}
|
|
306
|
+
if (
|
|
307
|
+
rec.platform !== undefined &&
|
|
308
|
+
!(COLLECTOR_PLATFORMS as readonly string[]).includes(rec.platform as string)
|
|
309
|
+
) {
|
|
310
|
+
errors.push(`platform must be one of: ${COLLECTOR_PLATFORMS.join(', ')}`);
|
|
311
|
+
}
|
|
312
|
+
if (rec.sequence !== undefined && (!Number.isInteger(rec.sequence) || (rec.sequence as number) < 0)) {
|
|
313
|
+
errors.push('sequence must be a non-negative integer');
|
|
314
|
+
}
|
|
315
|
+
if (rec.occurred_on !== undefined && (typeof rec.occurred_on !== 'string' || !isRealDate(rec.occurred_on))) {
|
|
316
|
+
errors.push(
|
|
317
|
+
'occurred_on must be a UTC calendar date (YYYY-MM-DD). A precise timestamp beside ' +
|
|
318
|
+
'a stable machine_id is a behavioural fingerprint and is refused here.',
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
if (
|
|
322
|
+
rec.collector_version !== undefined &&
|
|
323
|
+
(typeof rec.collector_version !== 'string' || !VERSION_RE.test(rec.collector_version))
|
|
324
|
+
) {
|
|
325
|
+
// `typeof === 'string'` was an unrestricted leak channel in a schema
|
|
326
|
+
// whose entire claim is that no field can hold free-form content: a
|
|
327
|
+
// path, a command line or a paragraph all passed it.
|
|
328
|
+
errors.push(
|
|
329
|
+
'collector_version must be a bounded semver-shaped string — an unconstrained ' +
|
|
330
|
+
'string is a free-form field, which is the thing this schema refuses',
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return { ok: errors.length === 0, errors };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** The deduplication key of metric item 4. Read-time dedup; never write-time. */
|
|
338
|
+
export function dedupKey(rec: CollectorRecord): string {
|
|
339
|
+
return `${rec.machine_id}|${rec.episode_id}|${rec.event}|${rec.sequence}`;
|
|
340
|
+
}
|