@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
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
LexicalIndex,
|
|
4
|
+
loadSqliteSync,
|
|
5
|
+
probeFts5Sync,
|
|
6
|
+
readUserVersion,
|
|
7
|
+
stampUserVersion,
|
|
8
|
+
tokenize
|
|
9
|
+
} from "./chunk-ZBZV2G5R.js";
|
|
10
|
+
import {
|
|
11
|
+
_classify
|
|
12
|
+
} from "./chunk-JQOM7TTM.js";
|
|
6
13
|
import {
|
|
7
14
|
require_dist
|
|
8
15
|
} from "./chunk-OY53J6II.js";
|
|
@@ -12,1102 +19,11 @@ import {
|
|
|
12
19
|
|
|
13
20
|
// src/scripts/memory_lookup.ts
|
|
14
21
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
15
|
-
import * as
|
|
16
|
-
import * as
|
|
22
|
+
import * as fs5 from "node:fs";
|
|
23
|
+
import * as path5 from "node:path";
|
|
17
24
|
import process5 from "node:process";
|
|
18
|
-
import { fileURLToPath as
|
|
19
|
-
import { createRequire
|
|
20
|
-
|
|
21
|
-
// src/scripts/lint_hidden_unicode.ts
|
|
22
|
-
import * as fs2 from "node:fs";
|
|
23
|
-
import * as path2 from "node:path";
|
|
24
|
-
import { spawnSync } from "node:child_process";
|
|
25
|
-
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
26
|
-
|
|
27
|
-
// src/scripts/_lib/security_lint.ts
|
|
28
|
-
import { createHash } from "node:crypto";
|
|
29
|
-
import * as fs from "node:fs";
|
|
30
|
-
import * as path from "node:path";
|
|
31
|
-
import { fileURLToPath } from "node:url";
|
|
32
|
-
var _HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
33
|
-
var ROOT = path.resolve(_HERE, "..", "..", "..");
|
|
34
|
-
var EXAMPLE_FENCE_LANG = "security-example";
|
|
35
|
-
var GUIDELINE = "docs/guidelines/agent-infra/security-lint-containment.md";
|
|
36
|
-
var GUIDELINE_EPILOG = `False-positive containment (fenced security-example block, confidence weighting, per-file \`security-lint: allow\` pragma \u2014 no global allowlist): see ${GUIDELINE}.`;
|
|
37
|
-
var DEFAULT_SCAN_ROOTS = [
|
|
38
|
-
"src/skills",
|
|
39
|
-
"src/rules",
|
|
40
|
-
"src/agent-src",
|
|
41
|
-
"src/domains",
|
|
42
|
-
"dist/agent-src"
|
|
43
|
-
];
|
|
44
|
-
var _EXAMPLE_PATH = /(^|\/)(docs|evals|tests?|fixtures?)(\/|$)|example|template|sample|\/_template/i;
|
|
45
|
-
var _PRAGMA = /<!--\s*security-lint:\s*allow\s+([A-Za-z0-9_-]+)\s+"([^"]+)"((?:\s+sha256:[0-9a-f]{64})*)\s*-->/g;
|
|
46
|
-
var _FENCE = /^(\s*)(`{3,}|~{3,})\s*([A-Za-z0-9_-]*)\s*$/;
|
|
47
|
-
var SEVERITY_RANK = { LOW: 1, MED: 2, HIGH: 3 };
|
|
48
|
-
var Finding = class {
|
|
49
|
-
path;
|
|
50
|
-
// repo-relative
|
|
51
|
-
line;
|
|
52
|
-
// 1-based; 0 = file-level
|
|
53
|
-
check;
|
|
54
|
-
// stable check id, also the pragma key
|
|
55
|
-
severity;
|
|
56
|
-
// HIGH | MED | LOW
|
|
57
|
-
message;
|
|
58
|
-
weight;
|
|
59
|
-
// 1.0 or 0.25
|
|
60
|
-
constructor(pathArg, line, check, severity, message, weight = 1) {
|
|
61
|
-
this.path = pathArg;
|
|
62
|
-
this.line = line;
|
|
63
|
-
this.check = check;
|
|
64
|
-
this.severity = severity;
|
|
65
|
-
this.message = message;
|
|
66
|
-
this.weight = weight;
|
|
67
|
-
}
|
|
68
|
-
/** A HIGH-severity, full-weight finding fails the build. */
|
|
69
|
-
get is_fail() {
|
|
70
|
-
return this.severity === "HIGH" && this.weight >= 1;
|
|
71
|
-
}
|
|
72
|
-
/** Mirror Python dataclass `__dict__` key order for `--json` parity. */
|
|
73
|
-
toDict() {
|
|
74
|
-
return {
|
|
75
|
-
path: this.path,
|
|
76
|
-
line: this.line,
|
|
77
|
-
check: this.check,
|
|
78
|
-
severity: this.severity,
|
|
79
|
-
message: this.message,
|
|
80
|
-
// float in Python → render integer-valued (1.0) as `1.0`.
|
|
81
|
-
weight: new PyFloat(this.weight)
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
function is_example_path(rel_path) {
|
|
86
|
-
return _EXAMPLE_PATH.test(rel_path);
|
|
87
|
-
}
|
|
88
|
-
function path_weight(rel_path) {
|
|
89
|
-
return is_example_path(rel_path) ? 0.25 : 1;
|
|
90
|
-
}
|
|
91
|
-
var PROJECTION_PREFIX = "dist/agent-src/";
|
|
92
|
-
var PROJECTION_SOURCE_LANES = [
|
|
93
|
-
// The guidelines lane copies `docs/guidelines/` (`_lib/guidelines_lane.ts`),
|
|
94
|
-
// not `src/guidelines/`, which does not exist. Without this row a projected
|
|
95
|
-
// guideline gets a DIFFERENT identity from its own source, so a bound
|
|
96
|
-
// pragma written in the source cannot suppress the projection's copy of the
|
|
97
|
-
// very same line — measured on
|
|
98
|
-
// `untrusted-input-spotlighting.md`, a defense guideline that quotes
|
|
99
|
-
// role-takeover phrases to teach refusal and carries three accepted
|
|
100
|
-
// fingerprints for exactly that.
|
|
101
|
-
["guidelines/", "docs/guidelines/"]
|
|
102
|
-
];
|
|
103
|
-
function source_identity(rel) {
|
|
104
|
-
if (!rel.startsWith(PROJECTION_PREFIX)) return rel;
|
|
105
|
-
const tail = rel.slice(PROJECTION_PREFIX.length);
|
|
106
|
-
for (const [lane, sourceRoot] of PROJECTION_SOURCE_LANES) {
|
|
107
|
-
if (tail.startsWith(lane)) return sourceRoot + tail.slice(lane.length);
|
|
108
|
-
}
|
|
109
|
-
return `src/${tail}`;
|
|
110
|
-
}
|
|
111
|
-
var ScannedFile = class {
|
|
112
|
-
path;
|
|
113
|
-
// absolute or as-given path
|
|
114
|
-
rel;
|
|
115
|
-
lines;
|
|
116
|
-
// per-line flags (1-based index → flag); index 0 unused
|
|
117
|
-
in_example_fence;
|
|
118
|
-
in_any_fence;
|
|
119
|
-
pragmas;
|
|
120
|
-
// check id → reason
|
|
121
|
-
/** check id → the sha256 fingerprints that pragma accepts. Empty = unbound. */
|
|
122
|
-
pragma_hashes;
|
|
123
|
-
weight;
|
|
124
|
-
constructor(pathArg, rel, lines, in_example_fence, in_any_fence, pragmas, weight, pragma_hashes = {}) {
|
|
125
|
-
this.path = pathArg;
|
|
126
|
-
this.rel = rel;
|
|
127
|
-
this.lines = lines;
|
|
128
|
-
this.in_example_fence = in_example_fence;
|
|
129
|
-
this.in_any_fence = in_any_fence;
|
|
130
|
-
this.pragmas = pragmas;
|
|
131
|
-
this.weight = weight;
|
|
132
|
-
this.pragma_hashes = pragma_hashes;
|
|
133
|
-
}
|
|
134
|
-
pragma_allows(check) {
|
|
135
|
-
return Object.prototype.hasOwnProperty.call(this.pragmas, check);
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Which form of pragma this file carries for `check`.
|
|
139
|
-
*
|
|
140
|
-
* `absent` — no pragma; scan normally.
|
|
141
|
-
* `legacy` — a pragma with no fingerprint. Suppresses the whole file, as it
|
|
142
|
-
* always did, and says so: a key lookup accepts whatever the
|
|
143
|
-
* line is later changed to say, which is the defect being paid
|
|
144
|
-
* down, not a mode anybody should choose.
|
|
145
|
-
* `bound` — a pragma listing fingerprints. Suppresses exactly the matches
|
|
146
|
-
* whose evidence hashes to one of them; anything else survives.
|
|
147
|
-
*/
|
|
148
|
-
pragma_form(check) {
|
|
149
|
-
if (!this.pragma_allows(check)) return "absent";
|
|
150
|
-
return (this.pragma_hashes[check] ?? []).length > 0 ? "bound" : "legacy";
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* The fingerprint one finding's evidence hashes to.
|
|
154
|
-
*
|
|
155
|
-
* WHAT IS HASHED, and each part earns its place:
|
|
156
|
-
* check id — the same line may legitimately be accepted for one check
|
|
157
|
-
* and not another.
|
|
158
|
-
* rel path — the location IDENTITY. Not the line NUMBER: an unrelated
|
|
159
|
-
* insert above would otherwise break every pragma in the
|
|
160
|
-
* file, and a suppression that breaks on unrelated edits
|
|
161
|
-
* gets deleted rather than re-derived. A `dist/agent-src/`
|
|
162
|
-
* path folds to its `src/` original first, because the
|
|
163
|
-
* projection is byte-exact by contract (ADR-201) and
|
|
164
|
-
* carries the pragma verbatim — without the fold, every
|
|
165
|
-
* migrated pragma would suppress the source and leave its
|
|
166
|
-
* own copy flagged, which is a gate that reds on a file
|
|
167
|
-
* nobody may edit.
|
|
168
|
-
* matched line, — the evidence. ASCII whitespace runs collapse so a reflow
|
|
169
|
-
* normalized does not invalidate the binding, `sha256:<hex>` tokens are
|
|
170
|
-
* removed, and NOTHING else is stripped: the zero-width
|
|
171
|
-
* characters this suite hunts are exactly what a wider
|
|
172
|
-
* normalizer would erase.
|
|
173
|
-
*
|
|
174
|
-
* WHY THE HASH TOKENS COME OUT. A pragma's own reason string can be the
|
|
175
|
-
* matched evidence — two in this tree are, because they quote the very
|
|
176
|
-
* phrases their check detects in order to explain themselves. Without this
|
|
177
|
-
* the fingerprint would have to be computed over a line that already
|
|
178
|
-
* contains it, which has no fixed point: writing the hash changes the line,
|
|
179
|
-
* which changes the hash. Stripping the tokens makes the fingerprint stable
|
|
180
|
-
* under the act of recording it, and costs nothing elsewhere — a `sha256:`
|
|
181
|
-
* token in ordinary prose is not evidence of anything a linter here checks.
|
|
182
|
-
*
|
|
183
|
-
* Deliberately NOT the whole file: incidental content elsewhere would make
|
|
184
|
-
* every unrelated edit re-fire the pragma, which is the noise that produces
|
|
185
|
-
* blanket suppressions.
|
|
186
|
-
*/
|
|
187
|
-
evidence_fingerprint(finding) {
|
|
188
|
-
const text = finding.line > 0 ? this.lines[finding.line - 1] ?? "" : "";
|
|
189
|
-
const normalized = text.replace(/\s*sha256:[0-9a-f]{64}/g, "").replace(/[ \t]+/g, " ").trim();
|
|
190
|
-
return createHash("sha256").update(`${finding.check}
|
|
191
|
-
${source_identity(this.rel)}
|
|
192
|
-
${normalized}`, "utf-8").digest("hex");
|
|
193
|
-
}
|
|
194
|
-
/** Drop the findings this file's BOUND pragma for `check` accepts. */
|
|
195
|
-
filter_bound_pragma(check, findings) {
|
|
196
|
-
const accepted = new Set(this.pragma_hashes[check] ?? []);
|
|
197
|
-
if (accepted.size === 0) return [...findings];
|
|
198
|
-
return findings.filter((f) => !accepted.has(this.evidence_fingerprint(f)));
|
|
199
|
-
}
|
|
200
|
-
/** Yield [lineno, text] honouring the fence masks (mirrors iter_lines). */
|
|
201
|
-
*iter_lines(opts = {}) {
|
|
202
|
-
const skip_example_fence = opts.skip_example_fence ?? true;
|
|
203
|
-
const skip_any_fence = opts.skip_any_fence ?? false;
|
|
204
|
-
for (let i = 1; i <= this.lines.length; i++) {
|
|
205
|
-
if (skip_example_fence && this.in_example_fence[i]) {
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
if (skip_any_fence && this.in_any_fence[i]) {
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
yield [i, this.lines[i - 1]];
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
function _splitlines(text) {
|
|
216
|
-
const out = [];
|
|
217
|
-
let buf = "";
|
|
218
|
-
const n = text.length;
|
|
219
|
-
let i = 0;
|
|
220
|
-
while (i < n) {
|
|
221
|
-
const ch = text[i];
|
|
222
|
-
const code = text.charCodeAt(i);
|
|
223
|
-
if (code === 13) {
|
|
224
|
-
out.push(buf);
|
|
225
|
-
buf = "";
|
|
226
|
-
if (i + 1 < n && text.charCodeAt(i + 1) === 10) {
|
|
227
|
-
i += 2;
|
|
228
|
-
} else {
|
|
229
|
-
i += 1;
|
|
230
|
-
}
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
if (code === 10 || code === 11 || code === 12 || code === 28 || code === 29 || code === 30 || code === 133 || code === 8232 || code === 8233) {
|
|
234
|
-
out.push(buf);
|
|
235
|
-
buf = "";
|
|
236
|
-
i += 1;
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
buf += ch;
|
|
240
|
-
i += 1;
|
|
241
|
-
}
|
|
242
|
-
if (buf !== "") {
|
|
243
|
-
out.push(buf);
|
|
244
|
-
}
|
|
245
|
-
return out;
|
|
246
|
-
}
|
|
247
|
-
function scan_file(filePath) {
|
|
248
|
-
let rel;
|
|
249
|
-
if (path.isAbsolute(filePath)) {
|
|
250
|
-
const root = path.resolve(ROOT);
|
|
251
|
-
const resolved = path.resolve(filePath);
|
|
252
|
-
if (resolved === root || resolved.startsWith(root + path.sep)) {
|
|
253
|
-
rel = path.relative(root, resolved).split(path.sep).join("/");
|
|
254
|
-
} else {
|
|
255
|
-
rel = path.basename(filePath);
|
|
256
|
-
}
|
|
257
|
-
} else {
|
|
258
|
-
rel = filePath.split(path.sep).join("/");
|
|
259
|
-
}
|
|
260
|
-
const raw = fs.readFileSync(filePath, "utf-8");
|
|
261
|
-
const lines = _splitlines(raw);
|
|
262
|
-
const n = lines.length;
|
|
263
|
-
const in_example = new Array(n + 1).fill(false);
|
|
264
|
-
const in_any = new Array(n + 1).fill(false);
|
|
265
|
-
let fence_open = false;
|
|
266
|
-
let fence_marker = "";
|
|
267
|
-
let fence_is_example = false;
|
|
268
|
-
for (let idx = 1; idx <= n; idx++) {
|
|
269
|
-
const text = lines[idx - 1];
|
|
270
|
-
const m = _FENCE.exec(text);
|
|
271
|
-
if (m && !fence_open) {
|
|
272
|
-
fence_open = true;
|
|
273
|
-
fence_marker = m[2][0];
|
|
274
|
-
fence_is_example = m[3] === EXAMPLE_FENCE_LANG;
|
|
275
|
-
in_any[idx] = true;
|
|
276
|
-
in_example[idx] = fence_is_example;
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
if (fence_open) {
|
|
280
|
-
in_any[idx] = true;
|
|
281
|
-
in_example[idx] = fence_is_example;
|
|
282
|
-
const cm = _FENCE.exec(text);
|
|
283
|
-
if (cm && cm[2][0] === fence_marker && cm[3] === "") {
|
|
284
|
-
fence_open = false;
|
|
285
|
-
fence_is_example = false;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
const pragmas = {};
|
|
290
|
-
const pragmaHashes = {};
|
|
291
|
-
for (const text of lines) {
|
|
292
|
-
_PRAGMA.lastIndex = 0;
|
|
293
|
-
let m;
|
|
294
|
-
while ((m = _PRAGMA.exec(text)) !== null) {
|
|
295
|
-
const check = m[1];
|
|
296
|
-
pragmas[check] = m[2];
|
|
297
|
-
const hashes = (m[3] ?? "").match(/sha256:([0-9a-f]{64})/g) ?? [];
|
|
298
|
-
pragmaHashes[check] = [
|
|
299
|
-
...pragmaHashes[check] ?? [],
|
|
300
|
-
...hashes.map((h) => h.slice("sha256:".length))
|
|
301
|
-
];
|
|
302
|
-
if (m.index === _PRAGMA.lastIndex) {
|
|
303
|
-
_PRAGMA.lastIndex += 1;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return new ScannedFile(
|
|
308
|
-
filePath,
|
|
309
|
-
rel,
|
|
310
|
-
lines,
|
|
311
|
-
in_example,
|
|
312
|
-
in_any,
|
|
313
|
-
pragmas,
|
|
314
|
-
path_weight(rel),
|
|
315
|
-
pragmaHashes
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
function scan_path(filePath, base) {
|
|
319
|
-
const sf = scan_file(filePath);
|
|
320
|
-
let rel;
|
|
321
|
-
const baseResolved = path.resolve(base);
|
|
322
|
-
const fileResolved = path.resolve(filePath);
|
|
323
|
-
if (fileResolved === baseResolved || fileResolved.startsWith(baseResolved + path.sep)) {
|
|
324
|
-
rel = path.relative(baseResolved, fileResolved).split(path.sep).join("/");
|
|
325
|
-
} else {
|
|
326
|
-
rel = path.basename(filePath);
|
|
327
|
-
}
|
|
328
|
-
return new ScannedFile(
|
|
329
|
-
sf.path,
|
|
330
|
-
rel,
|
|
331
|
-
sf.lines,
|
|
332
|
-
sf.in_example_fence,
|
|
333
|
-
sf.in_any_fence,
|
|
334
|
-
sf.pragmas,
|
|
335
|
-
path_weight(rel),
|
|
336
|
-
sf.pragma_hashes
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
function _rglobSorted(base) {
|
|
340
|
-
const found = [];
|
|
341
|
-
const walk = (dir) => {
|
|
342
|
-
let entries;
|
|
343
|
-
try {
|
|
344
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
345
|
-
} catch {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
for (const e of entries) {
|
|
349
|
-
const full = path.join(dir, e.name);
|
|
350
|
-
found.push(full);
|
|
351
|
-
if (e.isDirectory()) {
|
|
352
|
-
walk(full);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
walk(base);
|
|
357
|
-
found.sort((a, b) => _pathCmp(a, b));
|
|
358
|
-
return found;
|
|
359
|
-
}
|
|
360
|
-
function _pathCmp(a, b) {
|
|
361
|
-
const pa = a.split(path.sep);
|
|
362
|
-
const pb = b.split(path.sep);
|
|
363
|
-
const len = Math.min(pa.length, pb.length);
|
|
364
|
-
for (let i = 0; i < len; i++) {
|
|
365
|
-
if (pa[i] < pb[i]) return -1;
|
|
366
|
-
if (pa[i] > pb[i]) return 1;
|
|
367
|
-
}
|
|
368
|
-
if (pa.length < pb.length) return -1;
|
|
369
|
-
if (pa.length > pb.length) return 1;
|
|
370
|
-
return 0;
|
|
371
|
-
}
|
|
372
|
-
function* iter_corpus(roots = DEFAULT_SCAN_ROOTS, exts = [".md"], scanBase = ROOT) {
|
|
373
|
-
for (const root of roots) {
|
|
374
|
-
const base = path.join(scanBase, root);
|
|
375
|
-
if (!fs.existsSync(base)) {
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
for (const p of _rglobSorted(base)) {
|
|
379
|
-
let st;
|
|
380
|
-
try {
|
|
381
|
-
st = fs.statSync(p);
|
|
382
|
-
} catch {
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
if (st.isFile() && exts.includes(path.extname(p))) {
|
|
386
|
-
yield scan_path(p, scanBase);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
var LEGACY_PRAGMA_CHECK = "legacy-pragma";
|
|
392
|
-
function legacy_pragma_finding(sf, check) {
|
|
393
|
-
return new Finding(
|
|
394
|
-
sf.rel,
|
|
395
|
-
0,
|
|
396
|
-
LEGACY_PRAGMA_CHECK,
|
|
397
|
-
"LOW",
|
|
398
|
-
`unbound \`security-lint: allow ${check}\` pragma suppresses this whole file \u2014 it accepts whatever the matched text is later changed to say. Bind it with \`sha256:<hex>\` per accepted match.`,
|
|
399
|
-
sf.weight
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
var CHILD_SCANNED_PREFIX = "scanned: ";
|
|
403
|
-
function report_child_scanned(count) {
|
|
404
|
-
process.stderr.write(`${CHILD_SCANNED_PREFIX}${String(count)}
|
|
405
|
-
`);
|
|
406
|
-
}
|
|
407
|
-
function report(findings, opts) {
|
|
408
|
-
const check_label = opts.check_label;
|
|
409
|
-
if (findings.length === 0) {
|
|
410
|
-
process.stdout.write(`\u2705 ${check_label}: clean (${_corpus_note(opts.scanned_roots)}).
|
|
411
|
-
`);
|
|
412
|
-
return 0;
|
|
413
|
-
}
|
|
414
|
-
const fails = findings.filter((f) => f.is_fail);
|
|
415
|
-
const warns = findings.filter((f) => !f.is_fail);
|
|
416
|
-
const sorted = [...findings].sort((a, b) => {
|
|
417
|
-
const ra = -(SEVERITY_RANK[a.severity] ?? 0);
|
|
418
|
-
const rb = -(SEVERITY_RANK[b.severity] ?? 0);
|
|
419
|
-
if (ra !== rb) return ra - rb;
|
|
420
|
-
if (a.path < b.path) return -1;
|
|
421
|
-
if (a.path > b.path) return 1;
|
|
422
|
-
return a.line - b.line;
|
|
423
|
-
});
|
|
424
|
-
for (const f of sorted) {
|
|
425
|
-
const glyph = f.is_fail ? "\u{1F534}" : "\u26A0\uFE0F";
|
|
426
|
-
const loc = f.line ? `${f.path}:${f.line}` : f.path;
|
|
427
|
-
const wnote = f.weight >= 1 ? "" : ` (weight ${_pyG(f.weight)})`;
|
|
428
|
-
process.stdout.write(` ${glyph} [${f.severity}] ${f.check} \u2014 ${loc}${wnote}: ${f.message}
|
|
429
|
-
`);
|
|
430
|
-
}
|
|
431
|
-
process.stdout.write("\n");
|
|
432
|
-
if (fails.length > 0) {
|
|
433
|
-
process.stdout.write(
|
|
434
|
-
`\u274C ${check_label}: ${fails.length} blocking finding(s), ${warns.length} warning(s). Fix, or mark a true teaching example with a \`\`\`${EXAMPLE_FENCE_LANG} fence or a \`security-lint: allow\` pragma.
|
|
435
|
-
`
|
|
436
|
-
);
|
|
437
|
-
return 1;
|
|
438
|
-
}
|
|
439
|
-
process.stdout.write(`\u26A0\uFE0F ${check_label}: ${warns.length} warning(s), 0 blocking.
|
|
440
|
-
`);
|
|
441
|
-
return 0;
|
|
442
|
-
}
|
|
443
|
-
function _pyG(n) {
|
|
444
|
-
let s = n.toPrecision(6);
|
|
445
|
-
if (s.includes(".")) {
|
|
446
|
-
s = s.replace(/0+$/, "").replace(/\.$/, "");
|
|
447
|
-
}
|
|
448
|
-
return s;
|
|
449
|
-
}
|
|
450
|
-
function _corpus_note(scanned_roots) {
|
|
451
|
-
const roots = scanned_roots && scanned_roots.length > 0 ? scanned_roots : DEFAULT_SCAN_ROOTS;
|
|
452
|
-
return "scanned " + roots.join(", ");
|
|
453
|
-
}
|
|
454
|
-
var PyFloat = class {
|
|
455
|
-
constructor(value) {
|
|
456
|
-
this.value = value;
|
|
457
|
-
}
|
|
458
|
-
value;
|
|
459
|
-
};
|
|
460
|
-
function _isPlainObject(v) {
|
|
461
|
-
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof PyFloat);
|
|
462
|
-
}
|
|
463
|
-
function _pyJsonStr(s) {
|
|
464
|
-
let out = '"';
|
|
465
|
-
for (const ch of s) {
|
|
466
|
-
const code = ch.codePointAt(0);
|
|
467
|
-
switch (ch) {
|
|
468
|
-
case '"':
|
|
469
|
-
out += '\\"';
|
|
470
|
-
break;
|
|
471
|
-
case "\\":
|
|
472
|
-
out += "\\\\";
|
|
473
|
-
break;
|
|
474
|
-
case "\n":
|
|
475
|
-
out += "\\n";
|
|
476
|
-
break;
|
|
477
|
-
case "\r":
|
|
478
|
-
out += "\\r";
|
|
479
|
-
break;
|
|
480
|
-
case " ":
|
|
481
|
-
out += "\\t";
|
|
482
|
-
break;
|
|
483
|
-
case "\b":
|
|
484
|
-
out += "\\b";
|
|
485
|
-
break;
|
|
486
|
-
case "\f":
|
|
487
|
-
out += "\\f";
|
|
488
|
-
break;
|
|
489
|
-
default:
|
|
490
|
-
if (code < 32) {
|
|
491
|
-
out += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
492
|
-
} else {
|
|
493
|
-
out += ch;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return out + '"';
|
|
498
|
-
}
|
|
499
|
-
function _pyJsonFloat(n) {
|
|
500
|
-
if (!Number.isFinite(n)) {
|
|
501
|
-
if (Number.isNaN(n)) return "NaN";
|
|
502
|
-
return n > 0 ? "Infinity" : "-Infinity";
|
|
503
|
-
}
|
|
504
|
-
return Number.isInteger(n) ? `${n}.0` : String(n);
|
|
505
|
-
}
|
|
506
|
-
function _pyJsonScalar(value) {
|
|
507
|
-
if (value === null || value === void 0) return "null";
|
|
508
|
-
if (typeof value === "boolean") return value ? "true" : "false";
|
|
509
|
-
if (value instanceof PyFloat) return _pyJsonFloat(value.value);
|
|
510
|
-
if (typeof value === "number") {
|
|
511
|
-
if (!Number.isFinite(value)) {
|
|
512
|
-
if (Number.isNaN(value)) return "NaN";
|
|
513
|
-
return value > 0 ? "Infinity" : "-Infinity";
|
|
514
|
-
}
|
|
515
|
-
return String(value);
|
|
516
|
-
}
|
|
517
|
-
if (typeof value === "string") return _pyJsonStr(value);
|
|
518
|
-
return null;
|
|
519
|
-
}
|
|
520
|
-
function py_json_dumps_indent2(value, depth = 0) {
|
|
521
|
-
return _dumpIndent2(value, depth, true);
|
|
522
|
-
}
|
|
523
|
-
function _dumpIndent2(value, depth, ensureAscii) {
|
|
524
|
-
const scalar = ensureAscii ? _pyJsonScalarAscii(value) : _pyJsonScalar(value);
|
|
525
|
-
if (scalar !== null) {
|
|
526
|
-
return scalar;
|
|
527
|
-
}
|
|
528
|
-
const pad = " ".repeat(2 * (depth + 1));
|
|
529
|
-
const closePad = " ".repeat(2 * depth);
|
|
530
|
-
if (Array.isArray(value)) {
|
|
531
|
-
if (value.length === 0) return "[]";
|
|
532
|
-
const items = value.map((v) => pad + _dumpIndent2(v, depth + 1, ensureAscii));
|
|
533
|
-
return `[
|
|
534
|
-
${items.join(",\n")}
|
|
535
|
-
${closePad}]`;
|
|
536
|
-
}
|
|
537
|
-
if (_isPlainObject(value)) {
|
|
538
|
-
const keys = Object.keys(value);
|
|
539
|
-
if (keys.length === 0) return "{}";
|
|
540
|
-
const items = keys.map(
|
|
541
|
-
(k) => `${pad}${ensureAscii ? _pyJsonStrAscii(k) : _pyJsonStr(k)}: ${_dumpIndent2(value[k], depth + 1, ensureAscii)}`
|
|
542
|
-
);
|
|
543
|
-
return `{
|
|
544
|
-
${items.join(",\n")}
|
|
545
|
-
${closePad}}`;
|
|
546
|
-
}
|
|
547
|
-
return ensureAscii ? _pyJsonStrAscii(String(value)) : _pyJsonStr(String(value));
|
|
548
|
-
}
|
|
549
|
-
function _pyJsonStrAscii(s) {
|
|
550
|
-
let out = '"';
|
|
551
|
-
for (const ch of s) {
|
|
552
|
-
const code = ch.codePointAt(0);
|
|
553
|
-
switch (ch) {
|
|
554
|
-
case '"':
|
|
555
|
-
out += '\\"';
|
|
556
|
-
break;
|
|
557
|
-
case "\\":
|
|
558
|
-
out += "\\\\";
|
|
559
|
-
break;
|
|
560
|
-
case "\n":
|
|
561
|
-
out += "\\n";
|
|
562
|
-
break;
|
|
563
|
-
case "\r":
|
|
564
|
-
out += "\\r";
|
|
565
|
-
break;
|
|
566
|
-
case " ":
|
|
567
|
-
out += "\\t";
|
|
568
|
-
break;
|
|
569
|
-
case "\b":
|
|
570
|
-
out += "\\b";
|
|
571
|
-
break;
|
|
572
|
-
case "\f":
|
|
573
|
-
out += "\\f";
|
|
574
|
-
break;
|
|
575
|
-
default:
|
|
576
|
-
if (code < 32) {
|
|
577
|
-
out += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
578
|
-
} else if (code < 127) {
|
|
579
|
-
out += ch;
|
|
580
|
-
} else if (code <= 65535) {
|
|
581
|
-
out += `\\u${code.toString(16).padStart(4, "0")}`;
|
|
582
|
-
} else {
|
|
583
|
-
const cp = code - 65536;
|
|
584
|
-
const hi = 55296 + (cp >> 10);
|
|
585
|
-
const lo = 56320 + (cp & 1023);
|
|
586
|
-
out += `\\u${hi.toString(16).padStart(4, "0")}\\u${lo.toString(16).padStart(4, "0")}`;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
return out + '"';
|
|
591
|
-
}
|
|
592
|
-
function _pyJsonScalarAscii(value) {
|
|
593
|
-
if (typeof value === "string") return _pyJsonStrAscii(value);
|
|
594
|
-
return _pyJsonScalar(value);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// src/scripts/lint_hidden_unicode.ts
|
|
598
|
-
var CHECK = "hidden-unicode";
|
|
599
|
-
var _BIDI = /* @__PURE__ */ new Set([
|
|
600
|
-
8234,
|
|
601
|
-
8235,
|
|
602
|
-
8236,
|
|
603
|
-
8237,
|
|
604
|
-
8238,
|
|
605
|
-
8294,
|
|
606
|
-
8295,
|
|
607
|
-
8296,
|
|
608
|
-
8297,
|
|
609
|
-
8206,
|
|
610
|
-
8207,
|
|
611
|
-
1564
|
|
612
|
-
]);
|
|
613
|
-
var _ZERO_WIDTH = /* @__PURE__ */ new Set([8203, 8204, 8205, 8288, 65279, 173]);
|
|
614
|
-
var _DEPRECATED = /* @__PURE__ */ new Set([
|
|
615
|
-
8298,
|
|
616
|
-
8299,
|
|
617
|
-
8300,
|
|
618
|
-
8301,
|
|
619
|
-
8302,
|
|
620
|
-
8303,
|
|
621
|
-
65529,
|
|
622
|
-
65530,
|
|
623
|
-
65531
|
|
624
|
-
]);
|
|
625
|
-
function _classify(cp) {
|
|
626
|
-
if (_BIDI.has(cp)) {
|
|
627
|
-
return "bidi-control";
|
|
628
|
-
}
|
|
629
|
-
if (_ZERO_WIDTH.has(cp)) {
|
|
630
|
-
return "zero-width";
|
|
631
|
-
}
|
|
632
|
-
if (cp >= 917504 && cp <= 917631) {
|
|
633
|
-
return "unicode-tag";
|
|
634
|
-
}
|
|
635
|
-
if (_DEPRECATED.has(cp)) {
|
|
636
|
-
return "deprecated-format";
|
|
637
|
-
}
|
|
638
|
-
if (cp >= 57344 && cp <= 63743 || cp >= 983040 && cp <= 1048573 || cp >= 1048576 && cp <= 1114109) {
|
|
639
|
-
return "private-use-area";
|
|
640
|
-
}
|
|
641
|
-
if ((cp >= 0 && cp <= 31 || cp >= 127 && cp <= 159) && cp !== 9 && cp !== 10 && cp !== 13) {
|
|
642
|
-
return "control-char";
|
|
643
|
-
}
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
var _VS_LO = 917760;
|
|
647
|
-
var _VS_HI = 917999;
|
|
648
|
-
function _isVS(cp) {
|
|
649
|
-
return cp >= _VS_LO && cp <= _VS_HI;
|
|
650
|
-
}
|
|
651
|
-
var _CP_NAME = {
|
|
652
|
-
173: "SOFT HYPHEN",
|
|
653
|
-
1564: "ARABIC LETTER MARK",
|
|
654
|
-
8203: "ZERO WIDTH SPACE",
|
|
655
|
-
8204: "ZERO WIDTH NON-JOINER",
|
|
656
|
-
8205: "ZERO WIDTH JOINER",
|
|
657
|
-
8206: "LEFT-TO-RIGHT MARK",
|
|
658
|
-
8207: "RIGHT-TO-LEFT MARK",
|
|
659
|
-
8234: "LEFT-TO-RIGHT EMBEDDING",
|
|
660
|
-
8235: "RIGHT-TO-LEFT EMBEDDING",
|
|
661
|
-
8236: "POP DIRECTIONAL FORMATTING",
|
|
662
|
-
8237: "LEFT-TO-RIGHT OVERRIDE",
|
|
663
|
-
8238: "RIGHT-TO-LEFT OVERRIDE",
|
|
664
|
-
8288: "WORD JOINER",
|
|
665
|
-
8294: "LEFT-TO-RIGHT ISOLATE",
|
|
666
|
-
8295: "RIGHT-TO-LEFT ISOLATE",
|
|
667
|
-
8296: "FIRST STRONG ISOLATE",
|
|
668
|
-
8297: "POP DIRECTIONAL ISOLATE",
|
|
669
|
-
8298: "INHIBIT SYMMETRIC SWAPPING",
|
|
670
|
-
8299: "ACTIVATE SYMMETRIC SWAPPING",
|
|
671
|
-
8300: "INHIBIT ARABIC FORM SHAPING",
|
|
672
|
-
8301: "ACTIVATE ARABIC FORM SHAPING",
|
|
673
|
-
8302: "NATIONAL DIGIT SHAPES",
|
|
674
|
-
8303: "NOMINAL DIGIT SHAPES",
|
|
675
|
-
65279: "ZERO WIDTH NO-BREAK SPACE",
|
|
676
|
-
65529: "INTERLINEAR ANNOTATION ANCHOR",
|
|
677
|
-
65530: "INTERLINEAR ANNOTATION SEPARATOR",
|
|
678
|
-
65531: "INTERLINEAR ANNOTATION TERMINATOR",
|
|
679
|
-
917505: "LANGUAGE TAG",
|
|
680
|
-
917536: "TAG SPACE",
|
|
681
|
-
917537: "TAG EXCLAMATION MARK",
|
|
682
|
-
917538: "TAG QUOTATION MARK",
|
|
683
|
-
917539: "TAG NUMBER SIGN",
|
|
684
|
-
917540: "TAG DOLLAR SIGN",
|
|
685
|
-
917541: "TAG PERCENT SIGN",
|
|
686
|
-
917542: "TAG AMPERSAND",
|
|
687
|
-
917543: "TAG APOSTROPHE",
|
|
688
|
-
917544: "TAG LEFT PARENTHESIS",
|
|
689
|
-
917545: "TAG RIGHT PARENTHESIS",
|
|
690
|
-
917546: "TAG ASTERISK",
|
|
691
|
-
917547: "TAG PLUS SIGN",
|
|
692
|
-
917548: "TAG COMMA",
|
|
693
|
-
917549: "TAG HYPHEN-MINUS",
|
|
694
|
-
917550: "TAG FULL STOP",
|
|
695
|
-
917551: "TAG SOLIDUS",
|
|
696
|
-
917552: "TAG DIGIT ZERO",
|
|
697
|
-
917553: "TAG DIGIT ONE",
|
|
698
|
-
917554: "TAG DIGIT TWO",
|
|
699
|
-
917555: "TAG DIGIT THREE",
|
|
700
|
-
917556: "TAG DIGIT FOUR",
|
|
701
|
-
917557: "TAG DIGIT FIVE",
|
|
702
|
-
917558: "TAG DIGIT SIX",
|
|
703
|
-
917559: "TAG DIGIT SEVEN",
|
|
704
|
-
917560: "TAG DIGIT EIGHT",
|
|
705
|
-
917561: "TAG DIGIT NINE",
|
|
706
|
-
917562: "TAG COLON",
|
|
707
|
-
917563: "TAG SEMICOLON",
|
|
708
|
-
917564: "TAG LESS-THAN SIGN",
|
|
709
|
-
917565: "TAG EQUALS SIGN",
|
|
710
|
-
917566: "TAG GREATER-THAN SIGN",
|
|
711
|
-
917567: "TAG QUESTION MARK",
|
|
712
|
-
917568: "TAG COMMERCIAL AT",
|
|
713
|
-
917569: "TAG LATIN CAPITAL LETTER A",
|
|
714
|
-
917570: "TAG LATIN CAPITAL LETTER B",
|
|
715
|
-
917571: "TAG LATIN CAPITAL LETTER C",
|
|
716
|
-
917572: "TAG LATIN CAPITAL LETTER D",
|
|
717
|
-
917573: "TAG LATIN CAPITAL LETTER E",
|
|
718
|
-
917574: "TAG LATIN CAPITAL LETTER F",
|
|
719
|
-
917575: "TAG LATIN CAPITAL LETTER G",
|
|
720
|
-
917576: "TAG LATIN CAPITAL LETTER H",
|
|
721
|
-
917577: "TAG LATIN CAPITAL LETTER I",
|
|
722
|
-
917578: "TAG LATIN CAPITAL LETTER J",
|
|
723
|
-
917579: "TAG LATIN CAPITAL LETTER K",
|
|
724
|
-
917580: "TAG LATIN CAPITAL LETTER L",
|
|
725
|
-
917581: "TAG LATIN CAPITAL LETTER M",
|
|
726
|
-
917582: "TAG LATIN CAPITAL LETTER N",
|
|
727
|
-
917583: "TAG LATIN CAPITAL LETTER O",
|
|
728
|
-
917584: "TAG LATIN CAPITAL LETTER P",
|
|
729
|
-
917585: "TAG LATIN CAPITAL LETTER Q",
|
|
730
|
-
917586: "TAG LATIN CAPITAL LETTER R",
|
|
731
|
-
917587: "TAG LATIN CAPITAL LETTER S",
|
|
732
|
-
917588: "TAG LATIN CAPITAL LETTER T",
|
|
733
|
-
917589: "TAG LATIN CAPITAL LETTER U",
|
|
734
|
-
917590: "TAG LATIN CAPITAL LETTER V",
|
|
735
|
-
917591: "TAG LATIN CAPITAL LETTER W",
|
|
736
|
-
917592: "TAG LATIN CAPITAL LETTER X",
|
|
737
|
-
917593: "TAG LATIN CAPITAL LETTER Y",
|
|
738
|
-
917594: "TAG LATIN CAPITAL LETTER Z",
|
|
739
|
-
917595: "TAG LEFT SQUARE BRACKET",
|
|
740
|
-
917596: "TAG REVERSE SOLIDUS",
|
|
741
|
-
917597: "TAG RIGHT SQUARE BRACKET",
|
|
742
|
-
917598: "TAG CIRCUMFLEX ACCENT",
|
|
743
|
-
917599: "TAG LOW LINE",
|
|
744
|
-
917600: "TAG GRAVE ACCENT",
|
|
745
|
-
917601: "TAG LATIN SMALL LETTER A",
|
|
746
|
-
917602: "TAG LATIN SMALL LETTER B",
|
|
747
|
-
917603: "TAG LATIN SMALL LETTER C",
|
|
748
|
-
917604: "TAG LATIN SMALL LETTER D",
|
|
749
|
-
917605: "TAG LATIN SMALL LETTER E",
|
|
750
|
-
917606: "TAG LATIN SMALL LETTER F",
|
|
751
|
-
917607: "TAG LATIN SMALL LETTER G",
|
|
752
|
-
917608: "TAG LATIN SMALL LETTER H",
|
|
753
|
-
917609: "TAG LATIN SMALL LETTER I",
|
|
754
|
-
917610: "TAG LATIN SMALL LETTER J",
|
|
755
|
-
917611: "TAG LATIN SMALL LETTER K",
|
|
756
|
-
917612: "TAG LATIN SMALL LETTER L",
|
|
757
|
-
917613: "TAG LATIN SMALL LETTER M",
|
|
758
|
-
917614: "TAG LATIN SMALL LETTER N",
|
|
759
|
-
917615: "TAG LATIN SMALL LETTER O",
|
|
760
|
-
917616: "TAG LATIN SMALL LETTER P",
|
|
761
|
-
917617: "TAG LATIN SMALL LETTER Q",
|
|
762
|
-
917618: "TAG LATIN SMALL LETTER R",
|
|
763
|
-
917619: "TAG LATIN SMALL LETTER S",
|
|
764
|
-
917620: "TAG LATIN SMALL LETTER T",
|
|
765
|
-
917621: "TAG LATIN SMALL LETTER U",
|
|
766
|
-
917622: "TAG LATIN SMALL LETTER V",
|
|
767
|
-
917623: "TAG LATIN SMALL LETTER W",
|
|
768
|
-
917624: "TAG LATIN SMALL LETTER X",
|
|
769
|
-
917625: "TAG LATIN SMALL LETTER Y",
|
|
770
|
-
917626: "TAG LATIN SMALL LETTER Z",
|
|
771
|
-
917627: "TAG LEFT CURLY BRACKET",
|
|
772
|
-
917628: "TAG VERTICAL LINE",
|
|
773
|
-
917629: "TAG RIGHT CURLY BRACKET",
|
|
774
|
-
917630: "TAG TILDE",
|
|
775
|
-
917631: "CANCEL TAG"
|
|
776
|
-
};
|
|
777
|
-
function _cpName(cp) {
|
|
778
|
-
const n = _CP_NAME[cp];
|
|
779
|
-
return n !== void 0 ? n : "<unnamed>";
|
|
780
|
-
}
|
|
781
|
-
function _scan(sf) {
|
|
782
|
-
const pragmaForm = sf.pragma_form(CHECK);
|
|
783
|
-
if (pragmaForm === "legacy") {
|
|
784
|
-
return [legacy_pragma_finding(sf, CHECK)];
|
|
785
|
-
}
|
|
786
|
-
const finish = (hits) => pragmaForm === "bound" ? sf.filter_bound_pragma(CHECK, hits) : hits;
|
|
787
|
-
const out = [];
|
|
788
|
-
for (const [lineno, text] of sf.iter_lines({ skip_example_fence: true })) {
|
|
789
|
-
let vs_run = 0;
|
|
790
|
-
for (const ch of text) {
|
|
791
|
-
const cp = ch.codePointAt(0);
|
|
792
|
-
if (_isVS(cp)) {
|
|
793
|
-
vs_run += 1;
|
|
794
|
-
continue;
|
|
795
|
-
}
|
|
796
|
-
const kind = _classify(cp);
|
|
797
|
-
if (kind) {
|
|
798
|
-
const name = _cpName(cp);
|
|
799
|
-
out.push(
|
|
800
|
-
new Finding(
|
|
801
|
-
sf.rel,
|
|
802
|
-
lineno,
|
|
803
|
-
CHECK,
|
|
804
|
-
"HIGH",
|
|
805
|
-
`${kind} U+${cp.toString(16).toUpperCase().padStart(4, "0")} (${name})`,
|
|
806
|
-
sf.weight
|
|
807
|
-
)
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
if (vs_run >= 3) {
|
|
812
|
-
out.push(
|
|
813
|
-
new Finding(
|
|
814
|
-
sf.rel,
|
|
815
|
-
lineno,
|
|
816
|
-
CHECK,
|
|
817
|
-
"HIGH",
|
|
818
|
-
`variation-selector run x${vs_run} (steganography signature)`,
|
|
819
|
-
sf.weight
|
|
820
|
-
)
|
|
821
|
-
);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
return finish(out);
|
|
825
|
-
}
|
|
826
|
-
var _BINARY_EXT = /* @__PURE__ */ new Set([
|
|
827
|
-
"png",
|
|
828
|
-
"jpg",
|
|
829
|
-
"jpeg",
|
|
830
|
-
"gif",
|
|
831
|
-
"ico",
|
|
832
|
-
"webp",
|
|
833
|
-
"avif",
|
|
834
|
-
"bmp",
|
|
835
|
-
"tiff",
|
|
836
|
-
"pdf",
|
|
837
|
-
"woff",
|
|
838
|
-
"woff2",
|
|
839
|
-
"ttf",
|
|
840
|
-
"otf",
|
|
841
|
-
"eot",
|
|
842
|
-
"zip",
|
|
843
|
-
"gz",
|
|
844
|
-
"tgz",
|
|
845
|
-
"bz2",
|
|
846
|
-
"xz",
|
|
847
|
-
"zst",
|
|
848
|
-
"7z",
|
|
849
|
-
"rar",
|
|
850
|
-
"wasm",
|
|
851
|
-
"mp3",
|
|
852
|
-
"mp4",
|
|
853
|
-
"wav",
|
|
854
|
-
"ogg",
|
|
855
|
-
"webm",
|
|
856
|
-
"mov",
|
|
857
|
-
"avi",
|
|
858
|
-
"so",
|
|
859
|
-
"dylib",
|
|
860
|
-
"dll",
|
|
861
|
-
"node",
|
|
862
|
-
"a",
|
|
863
|
-
"o",
|
|
864
|
-
"exe",
|
|
865
|
-
"jar",
|
|
866
|
-
"class",
|
|
867
|
-
"pyc",
|
|
868
|
-
"pyo",
|
|
869
|
-
"db",
|
|
870
|
-
"sqlite",
|
|
871
|
-
"sqlite3",
|
|
872
|
-
"bin",
|
|
873
|
-
"dat",
|
|
874
|
-
"docx",
|
|
875
|
-
"xlsx",
|
|
876
|
-
"pptx",
|
|
877
|
-
"doc",
|
|
878
|
-
"xls",
|
|
879
|
-
"ppt",
|
|
880
|
-
"odt",
|
|
881
|
-
"ods",
|
|
882
|
-
"odp"
|
|
883
|
-
]);
|
|
884
|
-
var _GENERATED_PREFIXES = [
|
|
885
|
-
"dist/",
|
|
886
|
-
".augment/",
|
|
887
|
-
".claude/",
|
|
888
|
-
".cursor/",
|
|
889
|
-
".clinerules/",
|
|
890
|
-
// Verbatim captured tool output, not authored text. These are RECORDINGS:
|
|
891
|
-
// escaping a control byte inside one would falsify the record it exists to
|
|
892
|
-
// preserve. If a capture needs to stay grep-readable, the fix is to escape
|
|
893
|
-
// at capture time — never to edit the artifact afterwards.
|
|
894
|
-
"agents/evidence/analysis/",
|
|
895
|
-
// The frozen hostile-encoding corpus. Its positives ARE raw control
|
|
896
|
-
// characters — that is the thing under test, so flagging them would demand
|
|
897
|
-
// escaping the fixtures and thereby delete the test. The corpus has its own,
|
|
898
|
-
// stronger integrity controls: a sha256 freeze plus a scope-guard test that
|
|
899
|
-
// is itself falsified by an out-of-scope fixture. Excluded here because it
|
|
900
|
-
// is DATA, on the same principle as the captures above.
|
|
901
|
-
"internal/bench/corpora/encoding-channels/"
|
|
902
|
-
];
|
|
903
|
-
function _isGenerated(rel) {
|
|
904
|
-
return _GENERATED_PREFIXES.some((p) => rel.startsWith(p));
|
|
905
|
-
}
|
|
906
|
-
function _isRawControlCodepoint(cp) {
|
|
907
|
-
if (cp === 9 || cp === 10 || cp === 13) return false;
|
|
908
|
-
return cp <= 31 || cp >= 127 && cp <= 159;
|
|
909
|
-
}
|
|
910
|
-
function _extensionOf(rel) {
|
|
911
|
-
const base = rel.slice(rel.lastIndexOf("/") + 1);
|
|
912
|
-
const dot = base.lastIndexOf(".");
|
|
913
|
-
return dot <= 0 ? "" : base.slice(dot + 1).toLowerCase();
|
|
914
|
-
}
|
|
915
|
-
function _trackedFiles() {
|
|
916
|
-
const res = spawnSync("git", ["ls-files", "-z"], {
|
|
917
|
-
cwd: ROOT,
|
|
918
|
-
maxBuffer: 64 * 1024 * 1024
|
|
919
|
-
});
|
|
920
|
-
if (res.status !== 0 || res.stdout === null) return null;
|
|
921
|
-
return res.stdout.toString("utf-8").split("\0").filter((p) => p !== "");
|
|
922
|
-
}
|
|
923
|
-
function _eligibleSourceFiles() {
|
|
924
|
-
const tracked = _trackedFiles();
|
|
925
|
-
if (tracked === null) return null;
|
|
926
|
-
return tracked.filter((rel) => !_isGenerated(rel) && !_BINARY_EXT.has(_extensionOf(rel)));
|
|
927
|
-
}
|
|
928
|
-
function _scanSourceControlBytes(files = null) {
|
|
929
|
-
const tracked = files ?? _eligibleSourceFiles();
|
|
930
|
-
if (tracked === null) return [];
|
|
931
|
-
const out = [];
|
|
932
|
-
for (const rel of tracked) {
|
|
933
|
-
if (_isGenerated(rel)) continue;
|
|
934
|
-
if (_BINARY_EXT.has(_extensionOf(rel))) continue;
|
|
935
|
-
let data;
|
|
936
|
-
try {
|
|
937
|
-
data = fs2.readFileSync(path2.join(ROOT, rel));
|
|
938
|
-
} catch {
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
try {
|
|
942
|
-
new TextDecoder("utf-8", { fatal: true }).decode(data);
|
|
943
|
-
} catch {
|
|
944
|
-
continue;
|
|
945
|
-
}
|
|
946
|
-
let line = 1;
|
|
947
|
-
for (const ch of data.toString("utf-8")) {
|
|
948
|
-
const cp = ch.codePointAt(0);
|
|
949
|
-
if (cp === void 0) continue;
|
|
950
|
-
if (cp === 10) {
|
|
951
|
-
line += 1;
|
|
952
|
-
continue;
|
|
953
|
-
}
|
|
954
|
-
if (!_isRawControlCodepoint(cp)) continue;
|
|
955
|
-
const hex = cp.toString(16).toUpperCase().padStart(2, "0");
|
|
956
|
-
out.push(
|
|
957
|
-
new Finding(
|
|
958
|
-
rel,
|
|
959
|
-
line,
|
|
960
|
-
CHECK,
|
|
961
|
-
"HIGH",
|
|
962
|
-
`raw control character U+${hex} in a text source \u2014 makes grep/file(1)/git treat this file as binary and skip it silently; use the language escape (e.g. \\0, \\x7F) instead`,
|
|
963
|
-
1
|
|
964
|
-
)
|
|
965
|
-
);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
return out;
|
|
969
|
-
}
|
|
970
|
-
function _sanitize(filePath) {
|
|
971
|
-
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
972
|
-
let cleaned = "";
|
|
973
|
-
for (const ch of raw) {
|
|
974
|
-
const cp = ch.codePointAt(0);
|
|
975
|
-
if (_classify(cp) === null && !_isVS(cp)) {
|
|
976
|
-
cleaned += ch;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
cleaned = cleaned.normalize("NFKC");
|
|
980
|
-
const out = filePath + ".sanitized";
|
|
981
|
-
fs2.writeFileSync(out, cleaned, "utf-8");
|
|
982
|
-
return out;
|
|
983
|
-
}
|
|
984
|
-
function _argError(msg) {
|
|
985
|
-
process.stderr.write("usage: lint_hidden_unicode [-h] [--json] [--fix] [--root DIR]\n");
|
|
986
|
-
process.stderr.write(`lint_hidden_unicode: error: ${msg}
|
|
987
|
-
`);
|
|
988
|
-
process.exit(2);
|
|
989
|
-
}
|
|
990
|
-
function parse_args(argv) {
|
|
991
|
-
const out = { json: false, fix: false };
|
|
992
|
-
const extra = [];
|
|
993
|
-
let rootPending = false;
|
|
994
|
-
for (const a of argv) {
|
|
995
|
-
if (rootPending) {
|
|
996
|
-
out.root = a;
|
|
997
|
-
rootPending = false;
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
if (a === "-h" || a === "--help") {
|
|
1001
|
-
process.stdout.write("usage: lint_hidden_unicode [-h] [--json] [--fix] [--root DIR]\n");
|
|
1002
|
-
process.exit(0);
|
|
1003
|
-
} else if (a === "--json") {
|
|
1004
|
-
out.json = true;
|
|
1005
|
-
} else if (a === "--fix") {
|
|
1006
|
-
out.fix = true;
|
|
1007
|
-
} else if (a === "--root" || a.startsWith("--root=")) {
|
|
1008
|
-
const eq = a.indexOf("=");
|
|
1009
|
-
if (eq !== -1) {
|
|
1010
|
-
out.root = a.slice(eq + 1);
|
|
1011
|
-
} else {
|
|
1012
|
-
rootPending = true;
|
|
1013
|
-
}
|
|
1014
|
-
} else {
|
|
1015
|
-
extra.push(a);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
if (extra.length > 0) {
|
|
1019
|
-
_argError(`unrecognized arguments: ${extra.join(" ")}`);
|
|
1020
|
-
}
|
|
1021
|
-
return out;
|
|
1022
|
-
}
|
|
1023
|
-
function main(argv = null) {
|
|
1024
|
-
const args = parse_args(argv ?? process.argv.slice(2));
|
|
1025
|
-
const scanBase = args.root === void 0 ? ROOT : path2.resolve(args.root);
|
|
1026
|
-
const findings = [];
|
|
1027
|
-
const flagged = /* @__PURE__ */ new Set();
|
|
1028
|
-
let corpusFiles = 0;
|
|
1029
|
-
for (const sf of iter_corpus(DEFAULT_SCAN_ROOTS, [".md"], scanBase)) {
|
|
1030
|
-
corpusFiles += 1;
|
|
1031
|
-
const hits = _scan(sf);
|
|
1032
|
-
for (const h of hits) {
|
|
1033
|
-
findings.push(h);
|
|
1034
|
-
}
|
|
1035
|
-
if (hits.length > 0) {
|
|
1036
|
-
flagged.add(sf.path);
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
try {
|
|
1040
|
-
assertScanned({
|
|
1041
|
-
gate: "lint_hidden_unicode",
|
|
1042
|
-
scanned: corpusFiles,
|
|
1043
|
-
units: "corpus file(s)",
|
|
1044
|
-
roots: DEFAULT_SCAN_ROOTS
|
|
1045
|
-
});
|
|
1046
|
-
} catch (exc) {
|
|
1047
|
-
if (exc instanceof DeadScopeError) {
|
|
1048
|
-
process.stderr.write(`\u274C ${exc.message}
|
|
1049
|
-
`);
|
|
1050
|
-
return 1;
|
|
1051
|
-
}
|
|
1052
|
-
throw exc;
|
|
1053
|
-
}
|
|
1054
|
-
const sourceFiles = args.root === void 0 ? _eligibleSourceFiles() : [];
|
|
1055
|
-
for (const h of _scanSourceControlBytes(sourceFiles)) {
|
|
1056
|
-
findings.push(h);
|
|
1057
|
-
}
|
|
1058
|
-
if (!args.json) {
|
|
1059
|
-
const n = sourceFiles === null ? 0 : sourceFiles.length;
|
|
1060
|
-
process.stdout.write(
|
|
1061
|
-
sourceFiles === null ? " source pass: SKIPPED \u2014 `git ls-files` unavailable, 0 files read for raw control bytes\n" : ` source pass: ${n} tracked text file(s) read for raw C0 control bytes (generated trees + verbatim captures excluded)
|
|
1062
|
-
`
|
|
1063
|
-
);
|
|
1064
|
-
}
|
|
1065
|
-
if (args.fix) {
|
|
1066
|
-
for (const p of [...flagged].sort()) {
|
|
1067
|
-
const sanitized = _sanitize(p);
|
|
1068
|
-
const rel = path2.relative(path2.resolve(ROOT), path2.resolve(sanitized));
|
|
1069
|
-
process.stdout.write(` fixed \u2192 ${rel.split(path2.sep).join("/")}
|
|
1070
|
-
`);
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
if (args.json) {
|
|
1074
|
-
report_child_scanned(corpusFiles + (sourceFiles === null ? 0 : sourceFiles.length));
|
|
1075
|
-
}
|
|
1076
|
-
if (args.json) {
|
|
1077
|
-
const payload = py_json_dumps_indent2(findings.map((f) => f.toDict()));
|
|
1078
|
-
process.stdout.write(payload + "\n");
|
|
1079
|
-
return findings.some((f) => f.is_fail) ? 1 : 0;
|
|
1080
|
-
}
|
|
1081
|
-
return report(findings, { check_label: "hidden-unicode" });
|
|
1082
|
-
}
|
|
1083
|
-
function _isCliEntry() {
|
|
1084
|
-
if (true) {
|
|
1085
|
-
return false;
|
|
1086
|
-
}
|
|
1087
|
-
if (process.argv[1] === void 0) {
|
|
1088
|
-
return false;
|
|
1089
|
-
}
|
|
1090
|
-
const argvUrl = pathToFileURL(path2.resolve(process.argv[1])).href;
|
|
1091
|
-
if (import.meta.url === argvUrl) {
|
|
1092
|
-
return true;
|
|
1093
|
-
}
|
|
1094
|
-
try {
|
|
1095
|
-
const here = fs2.realpathSync(fileURLToPath2(import.meta.url));
|
|
1096
|
-
const argv = fs2.realpathSync(path2.resolve(process.argv[1]));
|
|
1097
|
-
return here === argv;
|
|
1098
|
-
} catch {
|
|
1099
|
-
return false;
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
if (_isCliEntry()) {
|
|
1103
|
-
process.exitCode = main();
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
// src/scripts/_lib/confusables.ts
|
|
1107
|
-
var _LATIN = new RegExp("\\p{Script=Latin}", "u");
|
|
1108
|
-
var _CYRILLIC = new RegExp("\\p{Script=Cyrillic}", "u");
|
|
1109
|
-
var _GREEK = new RegExp("\\p{Script=Greek}", "u");
|
|
1110
|
-
var _LETTER = new RegExp("\\p{L}", "u");
|
|
25
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
26
|
+
import { createRequire } from "node:module";
|
|
1111
27
|
|
|
1112
28
|
// src/scripts/_lib/retrieval_sanitize.ts
|
|
1113
29
|
var MAX_FIELD_CHARS = 8192;
|
|
@@ -1154,212 +70,22 @@ function _sanitize_value(v) {
|
|
|
1154
70
|
return v;
|
|
1155
71
|
}
|
|
1156
72
|
|
|
1157
|
-
// src/scripts/_lib/lexical_index.ts
|
|
1158
|
-
var BM25_K1 = 1.5;
|
|
1159
|
-
var BM25_B = 0.75;
|
|
1160
|
-
var MIN_TOKEN_LEN = 2;
|
|
1161
|
-
function tokenize(s) {
|
|
1162
|
-
const out = [];
|
|
1163
|
-
for (const raw of s.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
1164
|
-
if (raw.length >= MIN_TOKEN_LEN) out.push(raw);
|
|
1165
|
-
}
|
|
1166
|
-
return out;
|
|
1167
|
-
}
|
|
1168
|
-
function trigrams(s) {
|
|
1169
|
-
const norm = s.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
1170
|
-
const out = /* @__PURE__ */ new Set();
|
|
1171
|
-
if (norm.length < 3) {
|
|
1172
|
-
if (norm.length > 0) out.add(norm);
|
|
1173
|
-
return out;
|
|
1174
|
-
}
|
|
1175
|
-
for (let i = 0; i + 3 <= norm.length; i++) {
|
|
1176
|
-
out.add(norm.slice(i, i + 3));
|
|
1177
|
-
}
|
|
1178
|
-
return out;
|
|
1179
|
-
}
|
|
1180
|
-
var LexicalIndex = class {
|
|
1181
|
-
docs = /* @__PURE__ */ new Map();
|
|
1182
|
-
df = /* @__PURE__ */ new Map();
|
|
1183
|
-
n;
|
|
1184
|
-
avgdl;
|
|
1185
|
-
constructor(documents) {
|
|
1186
|
-
let totalLen = 0;
|
|
1187
|
-
for (const d of documents) {
|
|
1188
|
-
const tokens = tokenize(d.text);
|
|
1189
|
-
const tf = /* @__PURE__ */ new Map();
|
|
1190
|
-
for (const t of tokens) tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
1191
|
-
for (const t of tf.keys()) this.df.set(t, (this.df.get(t) ?? 0) + 1);
|
|
1192
|
-
this.docs.set(d.id, { id: d.id, len: tokens.length, tf, trigrams: trigrams(d.text) });
|
|
1193
|
-
totalLen += tokens.length;
|
|
1194
|
-
}
|
|
1195
|
-
this.n = documents.length;
|
|
1196
|
-
this.avgdl = this.n > 0 ? totalLen / this.n : 0;
|
|
1197
|
-
}
|
|
1198
|
-
/** Robertson–Spärck-Jones IDF, floored at 0 so common terms never subtract. */
|
|
1199
|
-
idf(term) {
|
|
1200
|
-
const df = this.df.get(term) ?? 0;
|
|
1201
|
-
if (df === 0) return 0;
|
|
1202
|
-
return Math.max(0, Math.log(1 + (this.n - df + 0.5) / (df + 0.5)));
|
|
1203
|
-
}
|
|
1204
|
-
/**
|
|
1205
|
-
* BM25 score of one document against the tokenised query terms, weighted by
|
|
1206
|
-
* **term coverage**: the raw BM25 sum is multiplied by `coverage²`, where
|
|
1207
|
-
* `coverage = distinct-query-terms-matched / distinct-query-terms`. This
|
|
1208
|
-
* stops a single generic, high-TF term match from outranking a document that
|
|
1209
|
-
* matches several rarer query terms once each (Phase 1 refinement). A
|
|
1210
|
-
* single-term query has `coverage == 1`, so its score is unchanged — the
|
|
1211
|
-
* weighting only re-orders genuinely multi-term queries.
|
|
1212
|
-
*/
|
|
1213
|
-
score(queryTerms, docId) {
|
|
1214
|
-
const doc = this.docs.get(docId);
|
|
1215
|
-
if (doc === void 0 || doc.len === 0) return 0;
|
|
1216
|
-
let s = 0;
|
|
1217
|
-
const matched = /* @__PURE__ */ new Set();
|
|
1218
|
-
for (const term of queryTerms) {
|
|
1219
|
-
const tf = doc.tf.get(term);
|
|
1220
|
-
if (tf === void 0) continue;
|
|
1221
|
-
const idf = this.idf(term);
|
|
1222
|
-
if (idf === 0) continue;
|
|
1223
|
-
const denom = tf + BM25_K1 * (1 - BM25_B + BM25_B * doc.len / (this.avgdl || 1));
|
|
1224
|
-
s += idf * (tf * (BM25_K1 + 1)) / denom;
|
|
1225
|
-
matched.add(term);
|
|
1226
|
-
}
|
|
1227
|
-
if (s === 0) return 0;
|
|
1228
|
-
const distinctQuery = new Set(queryTerms).size;
|
|
1229
|
-
const coverage = distinctQuery > 0 ? matched.size / distinctQuery : 1;
|
|
1230
|
-
return s * coverage * coverage;
|
|
1231
|
-
}
|
|
1232
|
-
/**
|
|
1233
|
-
* Rank documents for a set of query keys (phrases are tokenised). A
|
|
1234
|
-
* character-trigram prefilter selects candidates cheaply; the guard keeps
|
|
1235
|
-
* any doc sharing a query TOKEN even when no trigram overlaps, so the
|
|
1236
|
-
* prefilter never drops a genuine lexical match. Ties break by id for a
|
|
1237
|
-
* stable, deterministic order.
|
|
1238
|
-
*/
|
|
1239
|
-
rank(queryKeys) {
|
|
1240
|
-
const queryText = queryKeys.join(" ");
|
|
1241
|
-
const qTerms = tokenize(queryText);
|
|
1242
|
-
const qTermSet = new Set(qTerms);
|
|
1243
|
-
const qTrigrams = trigrams(queryText);
|
|
1244
|
-
const candidates = [];
|
|
1245
|
-
for (const [id, doc] of this.docs) {
|
|
1246
|
-
let hit = false;
|
|
1247
|
-
for (const t of qTrigrams) {
|
|
1248
|
-
if (doc.trigrams.has(t)) {
|
|
1249
|
-
hit = true;
|
|
1250
|
-
break;
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
if (!hit) {
|
|
1254
|
-
for (const t of qTermSet) {
|
|
1255
|
-
if (doc.tf.has(t)) {
|
|
1256
|
-
hit = true;
|
|
1257
|
-
break;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
if (hit) candidates.push(id);
|
|
1262
|
-
}
|
|
1263
|
-
const scored = candidates.map((id) => ({ id, score: this.score(qTerms, id) })).filter((r) => r.score > 0);
|
|
1264
|
-
scored.sort((a, b) => b.score - a.score || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
1265
|
-
return scored;
|
|
1266
|
-
}
|
|
1267
|
-
/** Document count — for the caller's tripwire / diagnostics. */
|
|
1268
|
-
get size() {
|
|
1269
|
-
return this.n;
|
|
1270
|
-
}
|
|
1271
|
-
};
|
|
1272
|
-
|
|
1273
73
|
// src/scripts/_lib/memory_fts_index.ts
|
|
1274
|
-
import * as
|
|
1275
|
-
import * as
|
|
1276
|
-
|
|
1277
|
-
// src/scripts/_lib/sqlite_guard.ts
|
|
1278
|
-
import { createRequire } from "node:module";
|
|
1279
|
-
var SqliteUnavailableError = class extends Error {
|
|
1280
|
-
constructor(callerName, cause) {
|
|
1281
|
-
super(
|
|
1282
|
-
`node:sqlite is unavailable in this runtime (${cause}). ${callerName} requires Node with the built-in SQLite module.`
|
|
1283
|
-
);
|
|
1284
|
-
this.name = "SqliteUnavailableError";
|
|
1285
|
-
}
|
|
1286
|
-
};
|
|
1287
|
-
var _sqliteWarningSilenced = false;
|
|
1288
|
-
function _silenceSqliteExperimentalWarning() {
|
|
1289
|
-
if (_sqliteWarningSilenced) return;
|
|
1290
|
-
_sqliteWarningSilenced = true;
|
|
1291
|
-
const orig = process.emitWarning.bind(process);
|
|
1292
|
-
process.emitWarning = ((warning, ...rest) => {
|
|
1293
|
-
const text = typeof warning === "string" ? warning : warning?.message ?? "";
|
|
1294
|
-
if (/SQLite is an experimental/i.test(text)) return;
|
|
1295
|
-
orig(warning, ...rest);
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
var _require;
|
|
1299
|
-
function _syncRequire() {
|
|
1300
|
-
if (_require === void 0) {
|
|
1301
|
-
_require = createRequire(import.meta.url);
|
|
1302
|
-
}
|
|
1303
|
-
return _require;
|
|
1304
|
-
}
|
|
1305
|
-
function loadSqliteSync(callerName) {
|
|
1306
|
-
_silenceSqliteExperimentalWarning();
|
|
1307
|
-
try {
|
|
1308
|
-
return _syncRequire()("node:sqlite");
|
|
1309
|
-
} catch (exc) {
|
|
1310
|
-
const message = exc instanceof Error ? exc.message : String(exc);
|
|
1311
|
-
throw new SqliteUnavailableError(callerName, message);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
function probeFts5Sync() {
|
|
1315
|
-
let sqlite;
|
|
1316
|
-
try {
|
|
1317
|
-
sqlite = loadSqliteSync("sqlite_guard.probeFts5Sync");
|
|
1318
|
-
} catch {
|
|
1319
|
-
return false;
|
|
1320
|
-
}
|
|
1321
|
-
let conn = null;
|
|
1322
|
-
try {
|
|
1323
|
-
conn = new sqlite.DatabaseSync(":memory:");
|
|
1324
|
-
conn.exec("CREATE VIRTUAL TABLE _fts5_probe USING fts5(body)");
|
|
1325
|
-
conn.exec("INSERT INTO _fts5_probe(body) VALUES ('probe')");
|
|
1326
|
-
const row = conn.prepare("SELECT body FROM _fts5_probe WHERE _fts5_probe MATCH 'probe'").get();
|
|
1327
|
-
return row !== void 0;
|
|
1328
|
-
} catch {
|
|
1329
|
-
return false;
|
|
1330
|
-
} finally {
|
|
1331
|
-
try {
|
|
1332
|
-
conn?.close();
|
|
1333
|
-
} catch {
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
function readUserVersion(conn) {
|
|
1338
|
-
const row = conn.prepare("PRAGMA user_version").get();
|
|
1339
|
-
const v = row?.["user_version"];
|
|
1340
|
-
if (typeof v === "bigint") return Number(v);
|
|
1341
|
-
if (typeof v === "number") return v;
|
|
1342
|
-
return 0;
|
|
1343
|
-
}
|
|
1344
|
-
function stampUserVersion(conn, version) {
|
|
1345
|
-
if (!Number.isInteger(version) || version < 0 || version > 2 ** 31 - 1) {
|
|
1346
|
-
throw new RangeError(`stampUserVersion: version out of range: ${version}`);
|
|
1347
|
-
}
|
|
1348
|
-
conn.exec(`PRAGMA user_version = ${version}`);
|
|
1349
|
-
}
|
|
74
|
+
import * as fs3 from "node:fs";
|
|
75
|
+
import * as path3 from "node:path";
|
|
1350
76
|
|
|
1351
77
|
// src/scripts/memory_report.ts
|
|
1352
78
|
var import_yaml = __toESM(require_dist(), 1);
|
|
1353
|
-
import * as
|
|
1354
|
-
import * as
|
|
79
|
+
import * as fs2 from "node:fs";
|
|
80
|
+
import * as path2 from "node:path";
|
|
1355
81
|
import process3 from "node:process";
|
|
1356
|
-
import { fileURLToPath as
|
|
82
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
1357
83
|
|
|
1358
84
|
// src/scripts/memory_status.ts
|
|
1359
85
|
import process2 from "node:process";
|
|
1360
|
-
import * as
|
|
1361
|
-
import * as
|
|
1362
|
-
import { fileURLToPath
|
|
86
|
+
import * as fs from "node:fs";
|
|
87
|
+
import * as path from "node:path";
|
|
88
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
1363
89
|
var CONTRACT_VERSION = 1;
|
|
1364
90
|
var _FILE_BACKEND_VERSION = "0.0.0-file";
|
|
1365
91
|
var _FILE_BACKEND_FEATURES = ["file-fallback"];
|
|
@@ -1471,7 +197,7 @@ function _parseArgs(argv) {
|
|
|
1471
197
|
}
|
|
1472
198
|
return args;
|
|
1473
199
|
}
|
|
1474
|
-
function
|
|
200
|
+
function main() {
|
|
1475
201
|
const args = _parseArgs(process2.argv.slice(2));
|
|
1476
202
|
if (args.health) {
|
|
1477
203
|
process2.stdout.write(`${_pyJsonDumps(health())}
|
|
@@ -1488,29 +214,29 @@ function main2() {
|
|
|
1488
214
|
}
|
|
1489
215
|
return 0;
|
|
1490
216
|
}
|
|
1491
|
-
function
|
|
217
|
+
function _isCliEntry() {
|
|
1492
218
|
if (true) {
|
|
1493
219
|
return false;
|
|
1494
220
|
}
|
|
1495
221
|
if (process2.argv[1] === void 0) {
|
|
1496
222
|
return false;
|
|
1497
223
|
}
|
|
1498
|
-
const argvUrl =
|
|
224
|
+
const argvUrl = pathToFileURL(path.resolve(process2.argv[1])).href;
|
|
1499
225
|
if (import.meta.url === argvUrl) {
|
|
1500
226
|
return true;
|
|
1501
227
|
}
|
|
1502
228
|
try {
|
|
1503
|
-
const here =
|
|
1504
|
-
const argv =
|
|
229
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
230
|
+
const argv = fs.realpathSync(path.resolve(process2.argv[1]));
|
|
1505
231
|
return here === argv;
|
|
1506
232
|
} catch {
|
|
1507
233
|
return false;
|
|
1508
234
|
}
|
|
1509
235
|
}
|
|
1510
|
-
var _isMain =
|
|
236
|
+
var _isMain = _isCliEntry();
|
|
1511
237
|
if (_isMain) {
|
|
1512
238
|
try {
|
|
1513
|
-
process2.exitCode =
|
|
239
|
+
process2.exitCode = main();
|
|
1514
240
|
} catch (e) {
|
|
1515
241
|
if (e instanceof _ExitError) {
|
|
1516
242
|
process2.exitCode = e.code;
|
|
@@ -1521,8 +247,8 @@ if (_isMain) {
|
|
|
1521
247
|
}
|
|
1522
248
|
|
|
1523
249
|
// src/scripts/memory_report.ts
|
|
1524
|
-
var MEMORY_ROOT =
|
|
1525
|
-
var INTAKE_ROOT =
|
|
250
|
+
var MEMORY_ROOT = path2.join("agents", "memory");
|
|
251
|
+
var INTAKE_ROOT = path2.join(MEMORY_ROOT, "intake");
|
|
1526
252
|
function _setMemoryRoot(p) {
|
|
1527
253
|
MEMORY_ROOT = p;
|
|
1528
254
|
}
|
|
@@ -1535,10 +261,10 @@ var CURATED_TYPES = [
|
|
|
1535
261
|
];
|
|
1536
262
|
var _MODE_MARKER_PATTERN = /<!--\s*role-mode:\s*([a-z0-9][a-z0-9-]*)\s*\|\s*contract:[^>]*-->/g;
|
|
1537
263
|
var _MODE_SCAN_DIRS = [
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
264
|
+
path2.join("agents", "sessions"),
|
|
265
|
+
path2.join("agents", "runtime", "reports"),
|
|
266
|
+
path2.join("agents", "handoffs"),
|
|
267
|
+
path2.join("agents", "learnings")
|
|
1542
268
|
];
|
|
1543
269
|
var _KNOWN_MODES = /* @__PURE__ */ new Set([
|
|
1544
270
|
"developer",
|
|
@@ -1559,31 +285,31 @@ var PyTimestamp = class {
|
|
|
1559
285
|
return this.pyStr;
|
|
1560
286
|
}
|
|
1561
287
|
};
|
|
1562
|
-
var
|
|
288
|
+
var PyFloat = class {
|
|
1563
289
|
constructor(value) {
|
|
1564
290
|
this.value = value;
|
|
1565
291
|
}
|
|
1566
292
|
value;
|
|
1567
293
|
};
|
|
1568
|
-
function
|
|
1569
|
-
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof PyTimestamp) && !(v instanceof
|
|
294
|
+
function _isPlainObject(v) {
|
|
295
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof PyTimestamp) && !(v instanceof PyFloat);
|
|
1570
296
|
}
|
|
1571
297
|
function _isFile(p) {
|
|
1572
298
|
try {
|
|
1573
|
-
return
|
|
299
|
+
return fs2.statSync(p).isFile();
|
|
1574
300
|
} catch {
|
|
1575
301
|
return false;
|
|
1576
302
|
}
|
|
1577
303
|
}
|
|
1578
304
|
function _isDir(p) {
|
|
1579
305
|
try {
|
|
1580
|
-
return
|
|
306
|
+
return fs2.statSync(p).isDirectory();
|
|
1581
307
|
} catch {
|
|
1582
308
|
return false;
|
|
1583
309
|
}
|
|
1584
310
|
}
|
|
1585
311
|
function _load_yaml(p) {
|
|
1586
|
-
const text =
|
|
312
|
+
const text = fs2.readFileSync(p, "utf-8");
|
|
1587
313
|
const doc = (0, import_yaml.parseDocument)(text, { version: "1.1", prettyErrors: false });
|
|
1588
314
|
if (doc.errors.length > 0) {
|
|
1589
315
|
const err = doc.errors[0];
|
|
@@ -1643,30 +369,30 @@ function _pyYamlDatetimeStr(raw) {
|
|
|
1643
369
|
function _iter_curated_entries() {
|
|
1644
370
|
const out = [];
|
|
1645
371
|
for (const mtype of CURATED_TYPES) {
|
|
1646
|
-
const single =
|
|
372
|
+
const single = path2.join(MEMORY_ROOT, `${mtype}.yml`);
|
|
1647
373
|
if (_isFile(single)) {
|
|
1648
374
|
const data = _load_yaml(single);
|
|
1649
375
|
const entries = data["entries"];
|
|
1650
376
|
if (Array.isArray(entries)) {
|
|
1651
377
|
for (const e of entries) {
|
|
1652
|
-
if (
|
|
378
|
+
if (_isPlainObject(e)) {
|
|
1653
379
|
out.push([single, mtype, e]);
|
|
1654
380
|
}
|
|
1655
381
|
}
|
|
1656
382
|
}
|
|
1657
383
|
}
|
|
1658
|
-
const type_dir =
|
|
384
|
+
const type_dir = path2.join(MEMORY_ROOT, mtype);
|
|
1659
385
|
if (_isDir(type_dir)) {
|
|
1660
386
|
for (const yml of _rglobYml(type_dir)) {
|
|
1661
387
|
const data = _load_yaml(yml) ?? {};
|
|
1662
388
|
const entries = data["entries"];
|
|
1663
389
|
if (Array.isArray(entries)) {
|
|
1664
390
|
for (const e of entries) {
|
|
1665
|
-
if (
|
|
391
|
+
if (_isPlainObject(e)) {
|
|
1666
392
|
out.push([yml, mtype, e]);
|
|
1667
393
|
}
|
|
1668
394
|
}
|
|
1669
|
-
} else if (
|
|
395
|
+
} else if (_isPlainObject(data) && data["id"]) {
|
|
1670
396
|
out.push([yml, mtype, data]);
|
|
1671
397
|
}
|
|
1672
398
|
}
|
|
@@ -1679,12 +405,12 @@ function _rglobYml(root) {
|
|
|
1679
405
|
const walk = (dir) => {
|
|
1680
406
|
let entries;
|
|
1681
407
|
try {
|
|
1682
|
-
entries =
|
|
408
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
1683
409
|
} catch {
|
|
1684
410
|
return;
|
|
1685
411
|
}
|
|
1686
412
|
for (const ent of entries) {
|
|
1687
|
-
const full =
|
|
413
|
+
const full = path2.join(dir, ent.name);
|
|
1688
414
|
if (ent.isDirectory()) {
|
|
1689
415
|
walk(full);
|
|
1690
416
|
} else if (ent.isFile() && ent.name.endsWith(".yml")) {
|
|
@@ -1699,11 +425,11 @@ function _rglobYml(root) {
|
|
|
1699
425
|
function _globJsonl(root) {
|
|
1700
426
|
let names;
|
|
1701
427
|
try {
|
|
1702
|
-
names =
|
|
428
|
+
names = fs2.readdirSync(root);
|
|
1703
429
|
} catch {
|
|
1704
430
|
return [];
|
|
1705
431
|
}
|
|
1706
|
-
return names.filter((n) => n.endsWith(".jsonl")).sort().map((n) =>
|
|
432
|
+
return names.filter((n) => n.endsWith(".jsonl")).sort().map((n) => path2.join(root, n));
|
|
1707
433
|
}
|
|
1708
434
|
function _intake_stats() {
|
|
1709
435
|
let total = 0;
|
|
@@ -1712,7 +438,7 @@ function _intake_stats() {
|
|
|
1712
438
|
let superseded = 0;
|
|
1713
439
|
if (_isDir(INTAKE_ROOT)) {
|
|
1714
440
|
for (const jsonl of _globJsonl(INTAKE_ROOT)) {
|
|
1715
|
-
const stem =
|
|
441
|
+
const stem = path2.basename(jsonl).replace(/\.jsonl$/, "");
|
|
1716
442
|
const month = stem.replace("signals-", "");
|
|
1717
443
|
for (const obj of _readJsonl(jsonl)) {
|
|
1718
444
|
if (obj["type"] === "supersede") {
|
|
@@ -1738,7 +464,7 @@ function _intake_stats() {
|
|
|
1738
464
|
function _readJsonl(p) {
|
|
1739
465
|
let text;
|
|
1740
466
|
try {
|
|
1741
|
-
text =
|
|
467
|
+
text = fs2.readFileSync(p, "utf-8");
|
|
1742
468
|
} catch {
|
|
1743
469
|
return [];
|
|
1744
470
|
}
|
|
@@ -1754,7 +480,7 @@ function _readJsonl(p) {
|
|
|
1754
480
|
} catch {
|
|
1755
481
|
continue;
|
|
1756
482
|
}
|
|
1757
|
-
if (
|
|
483
|
+
if (_isPlainObject(obj)) {
|
|
1758
484
|
out.push(obj);
|
|
1759
485
|
}
|
|
1760
486
|
}
|
|
@@ -1872,7 +598,7 @@ function _quarterly_stats() {
|
|
|
1872
598
|
return {
|
|
1873
599
|
accepted_by_quarter: _mapToObj(accepted),
|
|
1874
600
|
retired_by_quarter: _mapToObj(retired),
|
|
1875
|
-
staleness_rate: new
|
|
601
|
+
staleness_rate: new PyFloat(_pyRound3(rate)),
|
|
1876
602
|
curated_total: total,
|
|
1877
603
|
curated_overdue: overdue
|
|
1878
604
|
};
|
|
@@ -1901,7 +627,7 @@ function _role_mode_stats() {
|
|
|
1901
627
|
for (const md of _rglobMd(root)) {
|
|
1902
628
|
let text;
|
|
1903
629
|
try {
|
|
1904
|
-
text =
|
|
630
|
+
text = fs2.readFileSync(md, "utf-8");
|
|
1905
631
|
} catch {
|
|
1906
632
|
continue;
|
|
1907
633
|
}
|
|
@@ -1930,7 +656,7 @@ function _role_mode_stats() {
|
|
|
1930
656
|
}
|
|
1931
657
|
function _exists(p) {
|
|
1932
658
|
try {
|
|
1933
|
-
|
|
659
|
+
fs2.statSync(p);
|
|
1934
660
|
return true;
|
|
1935
661
|
} catch {
|
|
1936
662
|
return false;
|
|
@@ -1941,12 +667,12 @@ function _rglobMd(root) {
|
|
|
1941
667
|
const walk = (dir) => {
|
|
1942
668
|
let entries;
|
|
1943
669
|
try {
|
|
1944
|
-
entries =
|
|
670
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
1945
671
|
} catch {
|
|
1946
672
|
return;
|
|
1947
673
|
}
|
|
1948
674
|
for (const ent of entries) {
|
|
1949
|
-
const full =
|
|
675
|
+
const full = path2.join(dir, ent.name);
|
|
1950
676
|
if (ent.isDirectory()) {
|
|
1951
677
|
walk(full);
|
|
1952
678
|
} else if (ent.isFile() && ent.name.endsWith(".md")) {
|
|
@@ -1972,19 +698,19 @@ function build_report() {
|
|
|
1972
698
|
role_modes: _role_mode_stats()
|
|
1973
699
|
};
|
|
1974
700
|
}
|
|
1975
|
-
function _print_text(
|
|
701
|
+
function _print_text(report) {
|
|
1976
702
|
const out = [];
|
|
1977
|
-
const b =
|
|
703
|
+
const b = report.backend;
|
|
1978
704
|
out.push(`Backend: ${b.status} (backend=${b.backend})`);
|
|
1979
705
|
if (b.reason) {
|
|
1980
706
|
out.push(` reason: ${b.reason}`);
|
|
1981
707
|
}
|
|
1982
|
-
const intake =
|
|
708
|
+
const intake = report.intake;
|
|
1983
709
|
out.push(`Intake: ${intake.total_active} active, ${intake.superseded} superseded`);
|
|
1984
710
|
for (const [t, n] of _sortedEntries(intake.by_type)) {
|
|
1985
711
|
out.push(` - ${t}: ${n}`);
|
|
1986
712
|
}
|
|
1987
|
-
const stale =
|
|
713
|
+
const stale = report.staleness;
|
|
1988
714
|
if (stale.length === 0) {
|
|
1989
715
|
out.push("Staleness: no curated entries past review_after_days");
|
|
1990
716
|
} else {
|
|
@@ -1996,7 +722,7 @@ function _print_text(report2) {
|
|
|
1996
722
|
out.push(` (+${stale.length - 5} more)`);
|
|
1997
723
|
}
|
|
1998
724
|
}
|
|
1999
|
-
const q =
|
|
725
|
+
const q = report.quarterly;
|
|
2000
726
|
out.push(`Quarterly: staleness-rate=${_pyPercent1(q.staleness_rate.value)} (${q.curated_overdue}/${q.curated_total})`);
|
|
2001
727
|
if (Object.keys(q.accepted_by_quarter).length > 0) {
|
|
2002
728
|
const acc = _sortedEntries(q.accepted_by_quarter).map(([k, v]) => `${k}:${v}`).join(", ");
|
|
@@ -2006,7 +732,7 @@ function _print_text(report2) {
|
|
|
2006
732
|
const ret = _sortedEntries(q.retired_by_quarter).map(([k, v]) => `${k}:${v}`).join(", ");
|
|
2007
733
|
out.push(` retired: ${ret}`);
|
|
2008
734
|
}
|
|
2009
|
-
const rm =
|
|
735
|
+
const rm = report.role_modes;
|
|
2010
736
|
if (rm.files_scanned) {
|
|
2011
737
|
out.push(`Role modes: ${rm.total_markers} marker(s) in ${rm.files_scanned} file(s)`);
|
|
2012
738
|
if (Object.keys(rm.by_mode).length > 0) {
|
|
@@ -2047,7 +773,7 @@ function _dumpsIndent(value, indent, depth) {
|
|
|
2047
773
|
if (value instanceof PyTimestamp) {
|
|
2048
774
|
return _jsonStrAscii(value.pyStr);
|
|
2049
775
|
}
|
|
2050
|
-
if (value instanceof
|
|
776
|
+
if (value instanceof PyFloat) {
|
|
2051
777
|
return _jsonFloat(value.value);
|
|
2052
778
|
}
|
|
2053
779
|
if (Array.isArray(value)) {
|
|
@@ -2059,7 +785,7 @@ function _dumpsIndent(value, indent, depth) {
|
|
|
2059
785
|
${items.join(",\n")}
|
|
2060
786
|
${closePad}]`;
|
|
2061
787
|
}
|
|
2062
|
-
if (
|
|
788
|
+
if (_isPlainObject(value)) {
|
|
2063
789
|
const keys = Object.keys(value);
|
|
2064
790
|
if (keys.length === 0) {
|
|
2065
791
|
return "{}";
|
|
@@ -2141,7 +867,7 @@ function _escapeNonAscii2(s) {
|
|
|
2141
867
|
}
|
|
2142
868
|
var _PROG2 = "memory_report.py";
|
|
2143
869
|
var _USAGE2 = "usage: memory_report.py [-h] [--format {text,json}]\n";
|
|
2144
|
-
function
|
|
870
|
+
function _argError(msg) {
|
|
2145
871
|
process3.stderr.write(_USAGE2);
|
|
2146
872
|
process3.stderr.write(`${_PROG2}: error: ${msg}
|
|
2147
873
|
`);
|
|
@@ -2159,61 +885,61 @@ function _parseArgs2(argv) {
|
|
|
2159
885
|
process3.stdout.write(_USAGE2);
|
|
2160
886
|
process3.exit(0);
|
|
2161
887
|
} else {
|
|
2162
|
-
|
|
888
|
+
_argError(`unrecognized arguments: ${a}`);
|
|
2163
889
|
}
|
|
2164
890
|
}
|
|
2165
891
|
return args;
|
|
2166
892
|
}
|
|
2167
893
|
function _checkChoice(value, choices, flag) {
|
|
2168
894
|
if (value === void 0 || !choices.includes(value)) {
|
|
2169
|
-
|
|
895
|
+
_argError(
|
|
2170
896
|
`argument ${flag}: invalid choice: '${value ?? ""}' (choose from ${choices.map((c) => `'${c}'`).join(", ")})`
|
|
2171
897
|
);
|
|
2172
898
|
}
|
|
2173
899
|
return value;
|
|
2174
900
|
}
|
|
2175
|
-
function
|
|
901
|
+
function main2() {
|
|
2176
902
|
const args = _parseArgs2(process3.argv.slice(2));
|
|
2177
|
-
const
|
|
903
|
+
const report = build_report();
|
|
2178
904
|
if (args.format === "json") {
|
|
2179
|
-
process3.stdout.write(`${pyJsonDumps(
|
|
905
|
+
process3.stdout.write(`${pyJsonDumps(report, 2)}
|
|
2180
906
|
`);
|
|
2181
907
|
} else {
|
|
2182
|
-
_print_text(
|
|
908
|
+
_print_text(report);
|
|
2183
909
|
}
|
|
2184
910
|
return 0;
|
|
2185
911
|
}
|
|
2186
|
-
function
|
|
912
|
+
function _isCliEntry2() {
|
|
2187
913
|
if (true) {
|
|
2188
914
|
return false;
|
|
2189
915
|
}
|
|
2190
916
|
if (process3.argv[1] === void 0) {
|
|
2191
917
|
return false;
|
|
2192
918
|
}
|
|
2193
|
-
const argvUrl =
|
|
919
|
+
const argvUrl = pathToFileURL2(path2.resolve(process3.argv[1])).href;
|
|
2194
920
|
if (import.meta.url === argvUrl) {
|
|
2195
921
|
return true;
|
|
2196
922
|
}
|
|
2197
923
|
try {
|
|
2198
|
-
const here =
|
|
2199
|
-
const argv =
|
|
924
|
+
const here = fs2.realpathSync(fileURLToPath2(import.meta.url));
|
|
925
|
+
const argv = fs2.realpathSync(path2.resolve(process3.argv[1]));
|
|
2200
926
|
return here === argv;
|
|
2201
927
|
} catch {
|
|
2202
928
|
return false;
|
|
2203
929
|
}
|
|
2204
930
|
}
|
|
2205
|
-
var _isMain2 =
|
|
931
|
+
var _isMain2 = _isCliEntry2();
|
|
2206
932
|
if (_isMain2) {
|
|
2207
|
-
process3.exit(
|
|
933
|
+
process3.exit(main2());
|
|
2208
934
|
}
|
|
2209
935
|
|
|
2210
936
|
// src/scripts/_lib/memory_fts_index.ts
|
|
2211
|
-
var MEMORY_INDEX_REL =
|
|
937
|
+
var MEMORY_INDEX_REL = path3.join("agents", "runtime", "state", "memory-index-v1.sqlite3");
|
|
2212
938
|
var SCHEMA_VERSION = 1;
|
|
2213
939
|
var CURATED_STATUS_EXCLUDE = /* @__PURE__ */ new Set(["deprecated", "archived", "superseded"]);
|
|
2214
940
|
var INDEX_TEXT_FIELDS = ["path", "key", "symptom", "feature", "rule", "body"];
|
|
2215
941
|
function resolveIndexPath(consumerRoot) {
|
|
2216
|
-
return
|
|
942
|
+
return path3.join(consumerRoot ?? process.cwd(), MEMORY_INDEX_REL);
|
|
2217
943
|
}
|
|
2218
944
|
function _pyStr(v) {
|
|
2219
945
|
if (v === void 0 || v === null) return "";
|
|
@@ -2229,7 +955,7 @@ function _entryIndexText(entry) {
|
|
|
2229
955
|
}
|
|
2230
956
|
return parts.join(" | ");
|
|
2231
957
|
}
|
|
2232
|
-
function
|
|
958
|
+
function _isPlainObject2(v) {
|
|
2233
959
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2234
960
|
}
|
|
2235
961
|
function _collectCurated(memoryRoot) {
|
|
@@ -2252,11 +978,11 @@ function _collectCurated(memoryRoot) {
|
|
|
2252
978
|
function _globJsonl2(intakeRoot) {
|
|
2253
979
|
let names;
|
|
2254
980
|
try {
|
|
2255
|
-
names =
|
|
981
|
+
names = fs3.readdirSync(intakeRoot);
|
|
2256
982
|
} catch {
|
|
2257
983
|
return [];
|
|
2258
984
|
}
|
|
2259
|
-
return names.filter((n) => n.endsWith(".jsonl")).sort().map((n) =>
|
|
985
|
+
return names.filter((n) => n.endsWith(".jsonl")).sort().map((n) => path3.join(intakeRoot, n));
|
|
2260
986
|
}
|
|
2261
987
|
function _collectIntake(intakeRoot) {
|
|
2262
988
|
const out = [];
|
|
@@ -2265,7 +991,7 @@ function _collectIntake(intakeRoot) {
|
|
|
2265
991
|
const superseded = /* @__PURE__ */ new Set();
|
|
2266
992
|
let content;
|
|
2267
993
|
try {
|
|
2268
|
-
content =
|
|
994
|
+
content = fs3.readFileSync(jsonl, "utf-8");
|
|
2269
995
|
} catch {
|
|
2270
996
|
continue;
|
|
2271
997
|
}
|
|
@@ -2278,7 +1004,7 @@ function _collectIntake(intakeRoot) {
|
|
|
2278
1004
|
} catch {
|
|
2279
1005
|
continue;
|
|
2280
1006
|
}
|
|
2281
|
-
if (!
|
|
1007
|
+
if (!_isPlainObject2(obj)) continue;
|
|
2282
1008
|
if (obj["type"] === "supersede") {
|
|
2283
1009
|
const target = obj["supersedes"];
|
|
2284
1010
|
if (typeof target === "string") superseded.add(target);
|
|
@@ -2302,7 +1028,7 @@ function _sourcesMaxMtimeMs(memoryRoot, intakeRoot) {
|
|
|
2302
1028
|
let max = 0;
|
|
2303
1029
|
const bump = (p) => {
|
|
2304
1030
|
try {
|
|
2305
|
-
const st =
|
|
1031
|
+
const st = fs3.statSync(p);
|
|
2306
1032
|
if (st.mtimeMs > max) max = st.mtimeMs;
|
|
2307
1033
|
} catch {
|
|
2308
1034
|
}
|
|
@@ -2310,21 +1036,21 @@ function _sourcesMaxMtimeMs(memoryRoot, intakeRoot) {
|
|
|
2310
1036
|
const walk = (dir) => {
|
|
2311
1037
|
let entries;
|
|
2312
1038
|
try {
|
|
2313
|
-
entries =
|
|
1039
|
+
entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
2314
1040
|
} catch {
|
|
2315
1041
|
return;
|
|
2316
1042
|
}
|
|
2317
1043
|
for (const e of entries) {
|
|
2318
|
-
const full =
|
|
1044
|
+
const full = path3.join(dir, e.name);
|
|
2319
1045
|
if (e.isDirectory()) walk(full);
|
|
2320
1046
|
else if (e.isFile() && e.name.endsWith(".yml")) bump(full);
|
|
2321
1047
|
}
|
|
2322
1048
|
};
|
|
2323
1049
|
let memEntries;
|
|
2324
1050
|
try {
|
|
2325
|
-
memEntries =
|
|
1051
|
+
memEntries = fs3.readdirSync(memoryRoot, { withFileTypes: true });
|
|
2326
1052
|
for (const e of memEntries) {
|
|
2327
|
-
const full =
|
|
1053
|
+
const full = path3.join(memoryRoot, e.name);
|
|
2328
1054
|
if (e.isFile() && e.name.endsWith(".yml")) bump(full);
|
|
2329
1055
|
else if (e.isDirectory()) walk(full);
|
|
2330
1056
|
}
|
|
@@ -2335,7 +1061,7 @@ function _sourcesMaxMtimeMs(memoryRoot, intakeRoot) {
|
|
|
2335
1061
|
}
|
|
2336
1062
|
var META_KEY_SOURCES_MTIME = "sources_mtime_ms";
|
|
2337
1063
|
function isStale(indexPath, memoryRoot, intakeRoot) {
|
|
2338
|
-
if (!
|
|
1064
|
+
if (!fs3.existsSync(indexPath)) return true;
|
|
2339
1065
|
let sqlite;
|
|
2340
1066
|
try {
|
|
2341
1067
|
sqlite = loadSqliteSync("memory_fts_index.isStale");
|
|
@@ -2361,11 +1087,11 @@ function isStale(indexPath, memoryRoot, intakeRoot) {
|
|
|
2361
1087
|
}
|
|
2362
1088
|
}
|
|
2363
1089
|
function buildIndex(indexPath, memoryRoot, intakeRoot) {
|
|
2364
|
-
|
|
1090
|
+
fs3.mkdirSync(path3.dirname(indexPath), { recursive: true });
|
|
2365
1091
|
try {
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
1092
|
+
fs3.rmSync(indexPath, { force: true });
|
|
1093
|
+
fs3.rmSync(`${indexPath}-wal`, { force: true });
|
|
1094
|
+
fs3.rmSync(`${indexPath}-shm`, { force: true });
|
|
2369
1095
|
} catch {
|
|
2370
1096
|
}
|
|
2371
1097
|
const { DatabaseSync } = loadSqliteSync("memory_fts_index.buildIndex");
|
|
@@ -2449,39 +1175,40 @@ function queryIndex(indexPath, keys, types) {
|
|
|
2449
1175
|
}
|
|
2450
1176
|
|
|
2451
1177
|
// src/scripts/learning_sidecar.ts
|
|
2452
|
-
import { createHash
|
|
2453
|
-
import * as
|
|
2454
|
-
import * as
|
|
1178
|
+
import { createHash } from "node:crypto";
|
|
1179
|
+
import * as fs4 from "node:fs";
|
|
1180
|
+
import * as path4 from "node:path";
|
|
2455
1181
|
import process4 from "node:process";
|
|
2456
|
-
import { fileURLToPath as
|
|
1182
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2457
1183
|
var PROG = "learning_sidecar.ts";
|
|
2458
1184
|
var HALF_LIFE_DAYS = 30;
|
|
2459
1185
|
var MIN_CORROBORATIONS = 2;
|
|
2460
1186
|
var SIDECAR_NAME = ".agent-learning.json";
|
|
2461
1187
|
var LESSONS_NAME = "LESSONS.md";
|
|
2462
1188
|
var SCHEMA_VERSION2 = 1;
|
|
1189
|
+
var FORMATS = ["text", "json", "status"];
|
|
2463
1190
|
function _parseTsMs(ts) {
|
|
2464
1191
|
const t = Date.parse(ts);
|
|
2465
1192
|
return Number.isNaN(t) ? null : t;
|
|
2466
1193
|
}
|
|
2467
1194
|
function _bodyHash(body) {
|
|
2468
|
-
return
|
|
1195
|
+
return createHash("sha256").update(body.trim().toLowerCase()).digest("hex").slice(0, 12);
|
|
2469
1196
|
}
|
|
2470
1197
|
function _globSignalFiles(dir) {
|
|
2471
1198
|
let names;
|
|
2472
1199
|
try {
|
|
2473
|
-
names =
|
|
1200
|
+
names = fs4.readdirSync(dir);
|
|
2474
1201
|
} catch {
|
|
2475
1202
|
return [];
|
|
2476
1203
|
}
|
|
2477
|
-
return names.filter((n) => n.startsWith("signals-") && n.endsWith(".jsonl")).sort().map((n) =>
|
|
1204
|
+
return names.filter((n) => n.startsWith("signals-") && n.endsWith(".jsonl")).sort().map((n) => path4.join(dir, n));
|
|
2478
1205
|
}
|
|
2479
1206
|
function readSignals(intakeDir) {
|
|
2480
1207
|
const out = [];
|
|
2481
1208
|
for (const file of _globSignalFiles(intakeDir)) {
|
|
2482
1209
|
let content;
|
|
2483
1210
|
try {
|
|
2484
|
-
content =
|
|
1211
|
+
content = fs4.readFileSync(file, "utf-8");
|
|
2485
1212
|
} catch {
|
|
2486
1213
|
continue;
|
|
2487
1214
|
}
|
|
@@ -2572,9 +1299,11 @@ function aggregate(signals, nowMs) {
|
|
|
2572
1299
|
return lessons;
|
|
2573
1300
|
}
|
|
2574
1301
|
function buildSidecar(intakeDir, nowIso) {
|
|
1302
|
+
return buildSidecarFromSignals(readSignals(intakeDir), nowIso);
|
|
1303
|
+
}
|
|
1304
|
+
function buildSidecarFromSignals(signals, nowIso) {
|
|
2575
1305
|
const nowMs = _parseTsMs(nowIso) ?? 0;
|
|
2576
|
-
|
|
2577
|
-
return { schema_version: SCHEMA_VERSION2, generated_at: nowIso, lessons };
|
|
1306
|
+
return { schema_version: SCHEMA_VERSION2, generated_at: nowIso, lessons: aggregate(signals, nowMs) };
|
|
2578
1307
|
}
|
|
2579
1308
|
function renderLessonsMd(sidecar) {
|
|
2580
1309
|
const dead = sidecar.lessons.filter((l) => l.verdict === "dead_end");
|
|
@@ -2604,9 +1333,42 @@ function renderLessonsMd(sidecar) {
|
|
|
2604
1333
|
L.push("");
|
|
2605
1334
|
return L.join("\n");
|
|
2606
1335
|
}
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
1336
|
+
var STATUS_TOP_N = 5;
|
|
1337
|
+
var PROMOTION_HANDOFF = "Promote by hand: /memory:propose \xB7 src/skills/learning-to-rule-or-skill/SKILL.md";
|
|
1338
|
+
function renderStatus(sidecar) {
|
|
1339
|
+
const byVerdict = { preferred: 0, contested: 0, dead_end: 0 };
|
|
1340
|
+
for (const l of sidecar.lessons) byVerdict[l.verdict] += 1;
|
|
1341
|
+
const nowMs = _parseTsMs(sidecar.generated_at) ?? 0;
|
|
1342
|
+
const L = [];
|
|
1343
|
+
L.push(`${PROG}: ${String(sidecar.lessons.length)} lesson(s) as of ${sidecar.generated_at}`);
|
|
1344
|
+
L.push(
|
|
1345
|
+
`preferred: ${String(byVerdict.preferred)} \xB7 contested: ${String(byVerdict.contested)} \xB7 dead-end: ${String(byVerdict.dead_end)}`
|
|
1346
|
+
);
|
|
1347
|
+
L.push("");
|
|
1348
|
+
const preferred = sidecar.lessons.filter((l) => l.verdict === "preferred").sort((a, b) => b.score - a.score || (a.path < b.path ? -1 : 1)).slice(0, STATUS_TOP_N);
|
|
1349
|
+
L.push(`Top ${String(STATUS_TOP_N)} preferred:`);
|
|
1350
|
+
if (preferred.length === 0) {
|
|
1351
|
+
L.push(" (none \u2014 a lesson needs corroboration before it appears here)");
|
|
1352
|
+
} else {
|
|
1353
|
+
preferred.forEach((l, i) => {
|
|
1354
|
+
const ageDays = Math.max(0, Math.floor((nowMs - (_parseTsMs(l.last_ts) ?? nowMs)) / 864e5));
|
|
1355
|
+
L.push(
|
|
1356
|
+
` ${String(i + 1)}. ${l.entry_type} @ ${l.path} \u2014 ${String(l.corroborations)} origins, ${String(ageDays)}d old`
|
|
1357
|
+
);
|
|
1358
|
+
L.push(` ${l.body}`);
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
L.push("");
|
|
1362
|
+
L.push(
|
|
1363
|
+
`A lesson is promoted at ${String(MIN_CORROBORATIONS)} distinct origins, weighted by a ${String(HALF_LIFE_DAYS)}-day half-life; nothing here promotes itself.`
|
|
1364
|
+
);
|
|
1365
|
+
L.push(PROMOTION_HANDOFF);
|
|
1366
|
+
return `${L.join("\n")}
|
|
1367
|
+
`;
|
|
1368
|
+
}
|
|
1369
|
+
function main3(argv) {
|
|
1370
|
+
let intakeDir = path4.join("agents", "memory", "intake");
|
|
1371
|
+
let outDir = path4.join("agents", "memory");
|
|
2610
1372
|
let nowIso = "";
|
|
2611
1373
|
let write = false;
|
|
2612
1374
|
let format = "text";
|
|
@@ -2616,10 +1378,19 @@ function main4(argv) {
|
|
|
2616
1378
|
else if (a === "--out-dir") outDir = argv[++i] ?? outDir;
|
|
2617
1379
|
else if (a === "--now") nowIso = argv[++i] ?? "";
|
|
2618
1380
|
else if (a === "--write") write = true;
|
|
2619
|
-
else if (a === "--format")
|
|
2620
|
-
|
|
1381
|
+
else if (a === "--format") {
|
|
1382
|
+
const raw = argv[++i] ?? "";
|
|
1383
|
+
if (!FORMATS.includes(raw)) {
|
|
1384
|
+
process4.stderr.write(
|
|
1385
|
+
`${PROG}: error: argument --format: invalid choice: '${raw}' (choose from ${FORMATS.map((f) => `'${f}'`).join(", ")})
|
|
1386
|
+
`
|
|
1387
|
+
);
|
|
1388
|
+
return 2;
|
|
1389
|
+
}
|
|
1390
|
+
format = raw;
|
|
1391
|
+
} else if (a === "-h" || a === "--help") {
|
|
2621
1392
|
process4.stdout.write(
|
|
2622
|
-
`usage: ${PROG} [--intake-dir DIR] [--out-dir DIR] [--now ISO] [--write] [--format
|
|
1393
|
+
`usage: ${PROG} [--intake-dir DIR] [--out-dir DIR] [--now ISO] [--write] [--format ${FORMATS.join("|")}]
|
|
2623
1394
|
`
|
|
2624
1395
|
);
|
|
2625
1396
|
return 0;
|
|
@@ -2629,6 +1400,11 @@ function main4(argv) {
|
|
|
2629
1400
|
return 2;
|
|
2630
1401
|
}
|
|
2631
1402
|
}
|
|
1403
|
+
if (format === "status" && write) {
|
|
1404
|
+
process4.stderr.write(`${PROG}: error: --format status is read-only; drop --write
|
|
1405
|
+
`);
|
|
1406
|
+
return 2;
|
|
1407
|
+
}
|
|
2632
1408
|
if (!nowIso) {
|
|
2633
1409
|
nowIso = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
2634
1410
|
}
|
|
@@ -2641,14 +1417,18 @@ function main4(argv) {
|
|
|
2641
1417
|
return 3;
|
|
2642
1418
|
}
|
|
2643
1419
|
if (write) {
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
1420
|
+
fs4.mkdirSync(outDir, { recursive: true });
|
|
1421
|
+
fs4.writeFileSync(path4.join(outDir, SIDECAR_NAME), JSON.stringify(sidecar, null, 2) + "\n");
|
|
1422
|
+
fs4.writeFileSync(path4.join(outDir, LESSONS_NAME), renderLessonsMd(sidecar));
|
|
2647
1423
|
}
|
|
2648
1424
|
if (format === "json") {
|
|
2649
1425
|
process4.stdout.write(JSON.stringify(sidecar, null, 2) + "\n");
|
|
2650
1426
|
return 0;
|
|
2651
1427
|
}
|
|
1428
|
+
if (format === "status") {
|
|
1429
|
+
process4.stdout.write(renderStatus(sidecar));
|
|
1430
|
+
return 0;
|
|
1431
|
+
}
|
|
2652
1432
|
const byVerdict = { preferred: 0, contested: 0, dead_end: 0 };
|
|
2653
1433
|
for (const l of sidecar.lessons) byVerdict[l.verdict] += 1;
|
|
2654
1434
|
process4.stdout.write(
|
|
@@ -2658,8 +1438,8 @@ function main4(argv) {
|
|
|
2658
1438
|
return 0;
|
|
2659
1439
|
}
|
|
2660
1440
|
var _bundled = true;
|
|
2661
|
-
if (!_bundled &&
|
|
2662
|
-
process4.exit(
|
|
1441
|
+
if (!_bundled && fileURLToPath3(import.meta.url) === path4.resolve(process4.argv[1] ?? "")) {
|
|
1442
|
+
process4.exit(main3(process4.argv.slice(2)));
|
|
2663
1443
|
}
|
|
2664
1444
|
|
|
2665
1445
|
// src/scripts/memory_lookup.ts
|
|
@@ -2674,15 +1454,15 @@ var PyTimestamp2 = class {
|
|
|
2674
1454
|
return this.pyStr;
|
|
2675
1455
|
}
|
|
2676
1456
|
};
|
|
2677
|
-
var
|
|
1457
|
+
var PyFloat2 = class {
|
|
2678
1458
|
constructor(value) {
|
|
2679
1459
|
this.value = value;
|
|
2680
1460
|
}
|
|
2681
1461
|
value;
|
|
2682
1462
|
};
|
|
2683
|
-
var MEMORY_ROOT2 =
|
|
2684
|
-
var INTAKE_ROOT2 =
|
|
2685
|
-
var KNOWLEDGE_ROOT =
|
|
1463
|
+
var MEMORY_ROOT2 = path5.join("agents", "memory");
|
|
1464
|
+
var INTAKE_ROOT2 = path5.join(MEMORY_ROOT2, "intake");
|
|
1465
|
+
var KNOWLEDGE_ROOT = path5.join(MEMORY_ROOT2, "knowledge");
|
|
2686
1466
|
var _LEX_TYPE_FILES_MAX = 200;
|
|
2687
1467
|
var _LEX_CORPUS_FILES_MAX = 500;
|
|
2688
1468
|
var _LEX_SOURCE_FACTOR = { curated: 1, intake: 0.9, knowledge: 0.85 };
|
|
@@ -2691,17 +1471,17 @@ var _corpusFileCounts = null;
|
|
|
2691
1471
|
var _learningOverlay;
|
|
2692
1472
|
function _loadLearningOverlay() {
|
|
2693
1473
|
if (_learningOverlay !== void 0) return _learningOverlay;
|
|
2694
|
-
const file =
|
|
1474
|
+
const file = path5.join(MEMORY_ROOT2, SIDECAR_NAME);
|
|
2695
1475
|
try {
|
|
2696
|
-
const parsed = JSON.parse(
|
|
2697
|
-
const lessons =
|
|
1476
|
+
const parsed = JSON.parse(fs5.readFileSync(file, "utf-8"));
|
|
1477
|
+
const lessons = _isPlainObject3(parsed) ? parsed["lessons"] : null;
|
|
2698
1478
|
if (!Array.isArray(lessons)) {
|
|
2699
1479
|
_learningOverlay = null;
|
|
2700
1480
|
return null;
|
|
2701
1481
|
}
|
|
2702
1482
|
const map = /* @__PURE__ */ new Map();
|
|
2703
1483
|
for (const l of lessons) {
|
|
2704
|
-
if (!
|
|
1484
|
+
if (!_isPlainObject3(l)) continue;
|
|
2705
1485
|
const t = l["entry_type"];
|
|
2706
1486
|
const p = l["path"];
|
|
2707
1487
|
const v = l["verdict"];
|
|
@@ -2761,30 +1541,30 @@ var Hit = class {
|
|
|
2761
1541
|
source: this.source,
|
|
2762
1542
|
path: this.path,
|
|
2763
1543
|
// score is a Python float — render `0.0` not `0` for whole numbers.
|
|
2764
|
-
score: new
|
|
1544
|
+
score: new PyFloat2(this.score),
|
|
2765
1545
|
entry: this.entry
|
|
2766
1546
|
};
|
|
2767
1547
|
}
|
|
2768
1548
|
};
|
|
2769
|
-
function
|
|
2770
|
-
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof PyTimestamp2) && !(v instanceof
|
|
1549
|
+
function _isPlainObject3(v) {
|
|
1550
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof PyTimestamp2) && !(v instanceof PyFloat2);
|
|
2771
1551
|
}
|
|
2772
1552
|
function _isFile2(p) {
|
|
2773
1553
|
try {
|
|
2774
|
-
return
|
|
1554
|
+
return fs5.statSync(p).isFile();
|
|
2775
1555
|
} catch {
|
|
2776
1556
|
return false;
|
|
2777
1557
|
}
|
|
2778
1558
|
}
|
|
2779
1559
|
function _isDir2(p) {
|
|
2780
1560
|
try {
|
|
2781
|
-
return
|
|
1561
|
+
return fs5.statSync(p).isDirectory();
|
|
2782
1562
|
} catch {
|
|
2783
1563
|
return false;
|
|
2784
1564
|
}
|
|
2785
1565
|
}
|
|
2786
1566
|
function _load_yaml2(p) {
|
|
2787
|
-
const text =
|
|
1567
|
+
const text = fs5.readFileSync(p, "utf-8");
|
|
2788
1568
|
const doc = (0, import_yaml2.parseDocument)(text, { version: "1.1", prettyErrors: false });
|
|
2789
1569
|
if (doc.errors.length > 0) {
|
|
2790
1570
|
const err = doc.errors[0];
|
|
@@ -2842,13 +1622,13 @@ function _pad22(v) {
|
|
|
2842
1622
|
return v.length === 1 ? `0${v}` : v;
|
|
2843
1623
|
}
|
|
2844
1624
|
function* _iter_curated_entries2(mtype) {
|
|
2845
|
-
const type_dir =
|
|
2846
|
-
const single_file =
|
|
1625
|
+
const type_dir = path5.join(MEMORY_ROOT2, mtype);
|
|
1626
|
+
const single_file = path5.join(MEMORY_ROOT2, `${mtype}.yml`);
|
|
2847
1627
|
if (_isFile2(single_file)) {
|
|
2848
1628
|
const data = _load_yaml2(single_file);
|
|
2849
|
-
const entries =
|
|
1629
|
+
const entries = _isPlainObject3(data) ? data["entries"] : null;
|
|
2850
1630
|
for (const e of Array.isArray(entries) ? entries : []) {
|
|
2851
|
-
if (
|
|
1631
|
+
if (_isPlainObject3(e)) {
|
|
2852
1632
|
if (_statusExcluded(e)) {
|
|
2853
1633
|
continue;
|
|
2854
1634
|
}
|
|
@@ -2860,17 +1640,17 @@ function* _iter_curated_entries2(mtype) {
|
|
|
2860
1640
|
for (const yml of _rglobYmlSorted(type_dir)) {
|
|
2861
1641
|
const dataRaw = _load_yaml2(yml);
|
|
2862
1642
|
const data = dataRaw == null ? {} : dataRaw;
|
|
2863
|
-
const entries =
|
|
1643
|
+
const entries = _isPlainObject3(data) ? data["entries"] : void 0;
|
|
2864
1644
|
if (Array.isArray(entries)) {
|
|
2865
1645
|
for (const e of entries) {
|
|
2866
|
-
if (
|
|
1646
|
+
if (_isPlainObject3(e)) {
|
|
2867
1647
|
if (_statusExcluded(e)) {
|
|
2868
1648
|
continue;
|
|
2869
1649
|
}
|
|
2870
1650
|
yield [yml, e];
|
|
2871
1651
|
}
|
|
2872
1652
|
}
|
|
2873
|
-
} else if (
|
|
1653
|
+
} else if (_isPlainObject3(data) && data["id"]) {
|
|
2874
1654
|
if (_statusExcluded(data)) {
|
|
2875
1655
|
continue;
|
|
2876
1656
|
}
|
|
@@ -2880,13 +1660,13 @@ function* _iter_curated_entries2(mtype) {
|
|
|
2880
1660
|
}
|
|
2881
1661
|
}
|
|
2882
1662
|
function* _iter_curated_entries_all(mtype) {
|
|
2883
|
-
const type_dir =
|
|
2884
|
-
const single_file =
|
|
1663
|
+
const type_dir = path5.join(MEMORY_ROOT2, mtype);
|
|
1664
|
+
const single_file = path5.join(MEMORY_ROOT2, `${mtype}.yml`);
|
|
2885
1665
|
if (_isFile2(single_file)) {
|
|
2886
1666
|
const data = _load_yaml2(single_file);
|
|
2887
|
-
const entries =
|
|
1667
|
+
const entries = _isPlainObject3(data) ? data["entries"] : null;
|
|
2888
1668
|
for (const e of Array.isArray(entries) ? entries : []) {
|
|
2889
|
-
if (
|
|
1669
|
+
if (_isPlainObject3(e)) {
|
|
2890
1670
|
yield [single_file, e];
|
|
2891
1671
|
}
|
|
2892
1672
|
}
|
|
@@ -2895,14 +1675,14 @@ function* _iter_curated_entries_all(mtype) {
|
|
|
2895
1675
|
for (const yml of _rglobYmlSorted(type_dir)) {
|
|
2896
1676
|
const dataRaw = _load_yaml2(yml);
|
|
2897
1677
|
const data = dataRaw == null ? {} : dataRaw;
|
|
2898
|
-
const entries =
|
|
1678
|
+
const entries = _isPlainObject3(data) ? data["entries"] : void 0;
|
|
2899
1679
|
if (Array.isArray(entries)) {
|
|
2900
1680
|
for (const e of entries) {
|
|
2901
|
-
if (
|
|
1681
|
+
if (_isPlainObject3(e)) {
|
|
2902
1682
|
yield [yml, e];
|
|
2903
1683
|
}
|
|
2904
1684
|
}
|
|
2905
|
-
} else if (
|
|
1685
|
+
} else if (_isPlainObject3(data) && data["id"]) {
|
|
2906
1686
|
yield [yml, data];
|
|
2907
1687
|
}
|
|
2908
1688
|
}
|
|
@@ -2915,7 +1695,7 @@ function* _iter_intake_entries(mtype) {
|
|
|
2915
1695
|
for (const jsonl of _globJsonlSorted(INTAKE_ROOT2)) {
|
|
2916
1696
|
const by_id = /* @__PURE__ */ new Map();
|
|
2917
1697
|
const superseded = /* @__PURE__ */ new Set();
|
|
2918
|
-
const content =
|
|
1698
|
+
const content = fs5.readFileSync(jsonl, "utf-8");
|
|
2919
1699
|
for (let line of content.split(/\n/)) {
|
|
2920
1700
|
line = line.trim();
|
|
2921
1701
|
if (!line) {
|
|
@@ -2927,7 +1707,7 @@ function* _iter_intake_entries(mtype) {
|
|
|
2927
1707
|
} catch {
|
|
2928
1708
|
continue;
|
|
2929
1709
|
}
|
|
2930
|
-
if (!
|
|
1710
|
+
if (!_isPlainObject3(obj)) {
|
|
2931
1711
|
continue;
|
|
2932
1712
|
}
|
|
2933
1713
|
if (obj["type"] === "supersede") {
|
|
@@ -2961,27 +1741,27 @@ function* _iter_knowledge_entries() {
|
|
|
2961
1741
|
if (!_isDir2(ingest_dir)) {
|
|
2962
1742
|
continue;
|
|
2963
1743
|
}
|
|
2964
|
-
const manifest_path =
|
|
1744
|
+
const manifest_path = path5.join(ingest_dir, "manifest.json");
|
|
2965
1745
|
let manifest = {};
|
|
2966
1746
|
if (_isFile2(manifest_path)) {
|
|
2967
1747
|
try {
|
|
2968
|
-
const parsed = JSON.parse(
|
|
2969
|
-
manifest =
|
|
1748
|
+
const parsed = JSON.parse(fs5.readFileSync(manifest_path, "utf-8"));
|
|
1749
|
+
manifest = _isPlainObject3(parsed) ? parsed : {};
|
|
2970
1750
|
} catch {
|
|
2971
1751
|
manifest = {};
|
|
2972
1752
|
}
|
|
2973
1753
|
}
|
|
2974
|
-
const ingest_id = String(manifest["ingest_id"] ||
|
|
1754
|
+
const ingest_id = String(manifest["ingest_id"] || path5.basename(ingest_dir));
|
|
2975
1755
|
const source = String(manifest["source"] || "");
|
|
2976
1756
|
const pinned = Boolean(manifest["pinned"] ?? false);
|
|
2977
|
-
const chunks_dir =
|
|
1757
|
+
const chunks_dir = path5.join(ingest_dir, "chunks");
|
|
2978
1758
|
if (!_isDir2(chunks_dir)) {
|
|
2979
1759
|
continue;
|
|
2980
1760
|
}
|
|
2981
1761
|
for (const chunk of _globMdSorted(chunks_dir)) {
|
|
2982
1762
|
let body;
|
|
2983
1763
|
try {
|
|
2984
|
-
body =
|
|
1764
|
+
body = fs5.readFileSync(chunk, "utf-8");
|
|
2985
1765
|
} catch {
|
|
2986
1766
|
continue;
|
|
2987
1767
|
}
|
|
@@ -3083,7 +1863,7 @@ function _entry_id(mtype, file, entry, ordinals) {
|
|
|
3083
1863
|
if (own !== void 0 && own !== null && String(own).trim() !== "") {
|
|
3084
1864
|
return String(own);
|
|
3085
1865
|
}
|
|
3086
|
-
return `${mtype}:${
|
|
1866
|
+
return `${mtype}:${path5.basename(file)}:${ordinal}`;
|
|
3087
1867
|
}
|
|
3088
1868
|
function _entry_title(entry, id) {
|
|
3089
1869
|
for (const field of ["title", "key", "path"]) {
|
|
@@ -3108,7 +1888,7 @@ var _tokenizer;
|
|
|
3108
1888
|
function _lazy_tokenizer() {
|
|
3109
1889
|
if (_tokenizer === void 0) {
|
|
3110
1890
|
try {
|
|
3111
|
-
const req =
|
|
1891
|
+
const req = createRequire(import.meta.url);
|
|
3112
1892
|
_tokenizer = req("./_lib/token_count.js");
|
|
3113
1893
|
} catch {
|
|
3114
1894
|
_tokenizer = null;
|
|
@@ -3127,13 +1907,13 @@ function _entry_tokens_estimate(envelope_entry) {
|
|
|
3127
1907
|
function _countMdFiles(dir) {
|
|
3128
1908
|
let entries;
|
|
3129
1909
|
try {
|
|
3130
|
-
entries =
|
|
1910
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
3131
1911
|
} catch {
|
|
3132
1912
|
return 0;
|
|
3133
1913
|
}
|
|
3134
1914
|
let n = 0;
|
|
3135
1915
|
for (const e of entries) {
|
|
3136
|
-
if (e.isDirectory()) n += _countMdFiles(
|
|
1916
|
+
if (e.isDirectory()) n += _countMdFiles(path5.join(dir, e.name));
|
|
3137
1917
|
else if (e.isFile() && e.name.endsWith(".md")) n += 1;
|
|
3138
1918
|
}
|
|
3139
1919
|
return n;
|
|
@@ -3143,7 +1923,7 @@ function _countCorpusFiles() {
|
|
|
3143
1923
|
const perType = /* @__PURE__ */ new Map();
|
|
3144
1924
|
let total = 0;
|
|
3145
1925
|
for (const t of CURATED_TYPES2) {
|
|
3146
|
-
const exists =
|
|
1926
|
+
const exists = fs5.existsSync(path5.join(MEMORY_ROOT2, `${t}.yml`));
|
|
3147
1927
|
const c = exists ? 1 : 0;
|
|
3148
1928
|
perType.set(t, c);
|
|
3149
1929
|
total += c;
|
|
@@ -3152,7 +1932,7 @@ function _countCorpusFiles() {
|
|
|
3152
1932
|
perType.set(KNOWLEDGE_TYPE, kn);
|
|
3153
1933
|
total += kn;
|
|
3154
1934
|
try {
|
|
3155
|
-
for (const e of
|
|
1935
|
+
for (const e of fs5.readdirSync(INTAKE_ROOT2, { withFileTypes: true })) {
|
|
3156
1936
|
if (e.isFile() && e.name.endsWith(".jsonl")) total += 1;
|
|
3157
1937
|
}
|
|
3158
1938
|
} catch {
|
|
@@ -3300,7 +2080,7 @@ function _retrieve_internal(types, keys, limit, today) {
|
|
|
3300
2080
|
}
|
|
3301
2081
|
const hits = (positives.length > 0 ? positives : repo_hits).slice(0, limit);
|
|
3302
2082
|
for (const h of hits) {
|
|
3303
|
-
if (
|
|
2083
|
+
if (_isPlainObject3(h.entry)) h.entry = sanitize_entry(h.entry);
|
|
3304
2084
|
}
|
|
3305
2085
|
return [hits, skipped];
|
|
3306
2086
|
}
|
|
@@ -3344,7 +2124,7 @@ function retrieve_v1(types, keys, limit = 20, options = {}) {
|
|
|
3344
2124
|
let truncation = null;
|
|
3345
2125
|
for (let hi = 0; hi < hits.length; hi++) {
|
|
3346
2126
|
const h = hits[hi];
|
|
3347
|
-
const safeEntry =
|
|
2127
|
+
const safeEntry = _isPlainObject3(h.entry) ? sanitize_entry(h.entry) : {};
|
|
3348
2128
|
const learning = _learningVerdictFor(h.type, safeEntry);
|
|
3349
2129
|
if (learning !== void 0) safeEntry["learning"] = learning;
|
|
3350
2130
|
if (budgeted) {
|
|
@@ -3364,7 +2144,7 @@ function retrieve_v1(types, keys, limit = 20, options = {}) {
|
|
|
3364
2144
|
id: h.id,
|
|
3365
2145
|
type: h.type,
|
|
3366
2146
|
source: "repo",
|
|
3367
|
-
confidence: new
|
|
2147
|
+
confidence: new PyFloat2(_round4(h.score)),
|
|
3368
2148
|
line,
|
|
3369
2149
|
...learning !== void 0 ? { learning } : {}
|
|
3370
2150
|
});
|
|
@@ -3378,7 +2158,7 @@ function retrieve_v1(types, keys, limit = 20, options = {}) {
|
|
|
3378
2158
|
type: h.type,
|
|
3379
2159
|
source: "repo",
|
|
3380
2160
|
// confidence = round(float(score), 4) — always a Python float.
|
|
3381
|
-
confidence: new
|
|
2161
|
+
confidence: new PyFloat2(_round4(h.score)),
|
|
3382
2162
|
body: safeEntry
|
|
3383
2163
|
};
|
|
3384
2164
|
if (h.type in slice_counts) {
|
|
@@ -3389,7 +2169,7 @@ function retrieve_v1(types, keys, limit = 20, options = {}) {
|
|
|
3389
2169
|
id: h.id,
|
|
3390
2170
|
type: h.type,
|
|
3391
2171
|
source: "repo",
|
|
3392
|
-
confidence: new
|
|
2172
|
+
confidence: new PyFloat2(_round4(h.score)),
|
|
3393
2173
|
title: _entry_title(safeEntry, h.id),
|
|
3394
2174
|
tokens_estimate: _entry_tokens_estimate(envelope_entry),
|
|
3395
2175
|
// Knowledge chunks carry their pinned flag in the index row
|
|
@@ -3438,7 +2218,7 @@ function memory_get_v1(ids) {
|
|
|
3438
2218
|
const found = /* @__PURE__ */ new Map();
|
|
3439
2219
|
const record = (id, mtype, entry) => {
|
|
3440
2220
|
if (wanted.has(id) && !found.has(id)) {
|
|
3441
|
-
const safeEntry =
|
|
2221
|
+
const safeEntry = _isPlainObject3(entry) ? sanitize_entry(entry) : {};
|
|
3442
2222
|
const learning = _learningVerdictFor(mtype, safeEntry);
|
|
3443
2223
|
if (learning !== void 0) safeEntry["learning"] = learning;
|
|
3444
2224
|
found.set(id, {
|
|
@@ -3563,7 +2343,7 @@ function _printUsage() {
|
|
|
3563
2343
|
"usage: memory_lookup [-h] [--types TYPES] [--key KEY] [--limit LIMIT] [--format {text,json}] [--envelope {legacy,v1}] [--detail {index,full}] [--token-budget N]\n"
|
|
3564
2344
|
);
|
|
3565
2345
|
}
|
|
3566
|
-
function
|
|
2346
|
+
function main4() {
|
|
3567
2347
|
const args = _parseArgs3(process5.argv.slice(2));
|
|
3568
2348
|
const types = args.types.split(",").map((t) => t.trim()).filter((t) => t);
|
|
3569
2349
|
if (types.length === 0) {
|
|
@@ -3710,12 +2490,12 @@ function _rglobYmlSorted(root) {
|
|
|
3710
2490
|
const walk = (dir) => {
|
|
3711
2491
|
let entries;
|
|
3712
2492
|
try {
|
|
3713
|
-
entries =
|
|
2493
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
3714
2494
|
} catch {
|
|
3715
2495
|
return;
|
|
3716
2496
|
}
|
|
3717
2497
|
for (const ent of entries) {
|
|
3718
|
-
const full =
|
|
2498
|
+
const full = path5.join(dir, ent.name);
|
|
3719
2499
|
if (ent.name.endsWith(".yml")) {
|
|
3720
2500
|
out.push(full);
|
|
3721
2501
|
}
|
|
@@ -3737,27 +2517,27 @@ function _globMdSorted(dir) {
|
|
|
3737
2517
|
function _globSorted(dir, suffix) {
|
|
3738
2518
|
let entries;
|
|
3739
2519
|
try {
|
|
3740
|
-
entries =
|
|
2520
|
+
entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
3741
2521
|
} catch {
|
|
3742
2522
|
return [];
|
|
3743
2523
|
}
|
|
3744
|
-
const out = entries.filter((e) => e.name.endsWith(suffix) && (e.isFile() || e.isSymbolicLink() && _isFile2(
|
|
2524
|
+
const out = entries.filter((e) => e.name.endsWith(suffix) && (e.isFile() || e.isSymbolicLink() && _isFile2(path5.join(dir, e.name)))).map((e) => path5.join(dir, e.name));
|
|
3745
2525
|
out.sort();
|
|
3746
2526
|
return out;
|
|
3747
2527
|
}
|
|
3748
2528
|
function _iterdirSorted(dir) {
|
|
3749
2529
|
let names;
|
|
3750
2530
|
try {
|
|
3751
|
-
names =
|
|
2531
|
+
names = fs5.readdirSync(dir);
|
|
3752
2532
|
} catch {
|
|
3753
2533
|
return [];
|
|
3754
2534
|
}
|
|
3755
|
-
const out = names.map((name) =>
|
|
2535
|
+
const out = names.map((name) => path5.join(dir, name));
|
|
3756
2536
|
out.sort();
|
|
3757
2537
|
return out;
|
|
3758
2538
|
}
|
|
3759
2539
|
function _stem(p) {
|
|
3760
|
-
const base =
|
|
2540
|
+
const base = path5.basename(p);
|
|
3761
2541
|
const dot = base.lastIndexOf(".");
|
|
3762
2542
|
return dot <= 0 ? base : base.slice(0, dot);
|
|
3763
2543
|
}
|
|
@@ -3782,7 +2562,7 @@ function _dumpsIndent2(value, indent, depth) {
|
|
|
3782
2562
|
if (value instanceof PyTimestamp2) {
|
|
3783
2563
|
return _jsonStrAscii2(value.pyStr);
|
|
3784
2564
|
}
|
|
3785
|
-
if (value instanceof
|
|
2565
|
+
if (value instanceof PyFloat2) {
|
|
3786
2566
|
return _jsonFloat2(value.value);
|
|
3787
2567
|
}
|
|
3788
2568
|
if (Array.isArray(value)) {
|
|
@@ -3794,7 +2574,7 @@ function _dumpsIndent2(value, indent, depth) {
|
|
|
3794
2574
|
${items.join(",\n")}
|
|
3795
2575
|
${closePad}]`;
|
|
3796
2576
|
}
|
|
3797
|
-
if (
|
|
2577
|
+
if (_isPlainObject3(value)) {
|
|
3798
2578
|
const keys = Object.keys(value);
|
|
3799
2579
|
if (keys.length === 0) {
|
|
3800
2580
|
return "{}";
|
|
@@ -3874,25 +2654,25 @@ function _escapeNonAscii3(s) {
|
|
|
3874
2654
|
}
|
|
3875
2655
|
return out;
|
|
3876
2656
|
}
|
|
3877
|
-
function
|
|
2657
|
+
function _isCliEntry3() {
|
|
3878
2658
|
if (process5.argv[1] === void 0) {
|
|
3879
2659
|
return false;
|
|
3880
2660
|
}
|
|
3881
|
-
const argvUrl =
|
|
2661
|
+
const argvUrl = pathToFileURL3(path5.resolve(process5.argv[1])).href;
|
|
3882
2662
|
if (import.meta.url === argvUrl) {
|
|
3883
2663
|
return true;
|
|
3884
2664
|
}
|
|
3885
2665
|
try {
|
|
3886
|
-
const here =
|
|
3887
|
-
const argv =
|
|
2666
|
+
const here = fs5.realpathSync(fileURLToPath4(import.meta.url));
|
|
2667
|
+
const argv = fs5.realpathSync(path5.resolve(process5.argv[1]));
|
|
3888
2668
|
return here === argv;
|
|
3889
2669
|
} catch {
|
|
3890
2670
|
return false;
|
|
3891
2671
|
}
|
|
3892
2672
|
}
|
|
3893
|
-
var _isMain3 =
|
|
2673
|
+
var _isMain3 = _isCliEntry3();
|
|
3894
2674
|
if (_isMain3) {
|
|
3895
|
-
process5.exit(
|
|
2675
|
+
process5.exit(main4());
|
|
3896
2676
|
}
|
|
3897
2677
|
|
|
3898
2678
|
export {
|