@event4u/agent-config 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/.claude-plugin/marketplace.json +5 -5
  2. package/CHANGELOG.md +167 -440
  3. package/README.md +3 -3
  4. package/dist/agent-src/commands/agent-handoff.md +5 -4
  5. package/dist/agent-src/commands/agent-status.md +1 -0
  6. package/dist/agent-src/commands/agents/audit.md +1 -0
  7. package/dist/agent-src/commands/agents/init.md +3 -0
  8. package/dist/agent-src/commands/agents/optimize.md +1 -0
  9. package/dist/agent-src/commands/agents/user/accept.md +1 -0
  10. package/dist/agent-src/commands/agents/user/init.md +1 -0
  11. package/dist/agent-src/commands/agents/user/review.md +1 -0
  12. package/dist/agent-src/commands/agents/user/show.md +1 -0
  13. package/dist/agent-src/commands/agents/user/update.md +1 -0
  14. package/dist/agent-src/commands/agents/user.md +1 -0
  15. package/dist/agent-src/commands/agents.md +1 -0
  16. package/dist/agent-src/commands/analytics/prune.md +3 -2
  17. package/dist/agent-src/commands/analytics/show.md +3 -2
  18. package/dist/agent-src/commands/analytics.md +3 -2
  19. package/dist/agent-src/commands/analyze-reference-repo.md +1 -0
  20. package/dist/agent-src/commands/bug-fix.md +1 -0
  21. package/dist/agent-src/commands/bug-investigate.md +1 -0
  22. package/dist/agent-src/commands/challenge-me/vision.md +3 -2
  23. package/dist/agent-src/commands/challenge-me/with-docs.md +3 -2
  24. package/dist/agent-src/commands/challenge-me.md +3 -2
  25. package/dist/agent-src/commands/chat-history/import.md +9 -9
  26. package/dist/agent-src/commands/chat-history.md +32 -30
  27. package/dist/agent-src/commands/check-current-md.md +1 -0
  28. package/dist/agent-src/commands/commit/in-chunks.md +1 -0
  29. package/dist/agent-src/commands/commit.md +1 -0
  30. package/dist/agent-src/commands/condense.md +1 -0
  31. package/dist/agent-src/commands/context/create.md +1 -0
  32. package/dist/agent-src/commands/context/refactor.md +1 -0
  33. package/dist/agent-src/commands/context.md +1 -0
  34. package/dist/agent-src/commands/cost-report.md +5 -4
  35. package/dist/agent-src/commands/council/analysis.md +3 -2
  36. package/dist/agent-src/commands/council/debate.md +5 -4
  37. package/dist/agent-src/commands/council/default.md +3 -2
  38. package/dist/agent-src/commands/council/design.md +3 -2
  39. package/dist/agent-src/commands/council/optimize.md +3 -2
  40. package/dist/agent-src/commands/council/pr.md +3 -2
  41. package/dist/agent-src/commands/council.md +4 -3
  42. package/dist/agent-src/commands/e2e-heal.md +1 -0
  43. package/dist/agent-src/commands/e2e-plan.md +1 -0
  44. package/dist/agent-src/commands/estimate-ticket.md +1 -0
  45. package/dist/agent-src/commands/feature/dev.md +1 -0
  46. package/dist/agent-src/commands/feature/explore.md +1 -0
  47. package/dist/agent-src/commands/feature/plan.md +6 -6
  48. package/dist/agent-src/commands/feature/refactor.md +1 -0
  49. package/dist/agent-src/commands/feature/roadmap.md +1 -0
  50. package/dist/agent-src/commands/feature.md +1 -0
  51. package/dist/agent-src/commands/fix/ci.md +1 -0
  52. package/dist/agent-src/commands/fix/portability.md +1 -0
  53. package/dist/agent-src/commands/fix/pr-comments.md +147 -15
  54. package/dist/agent-src/commands/fix/refs.md +1 -0
  55. package/dist/agent-src/commands/fix/seeder.md +1 -0
  56. package/dist/agent-src/commands/fix.md +8 -8
  57. package/dist/agent-src/commands/ghostwriter/delete.md +1 -0
  58. package/dist/agent-src/commands/ghostwriter/fetch.md +1 -0
  59. package/dist/agent-src/commands/ghostwriter/list.md +1 -0
  60. package/dist/agent-src/commands/ghostwriter/show.md +1 -0
  61. package/dist/agent-src/commands/ghostwriter/write.md +1 -0
  62. package/dist/agent-src/commands/ghostwriter.md +1 -0
  63. package/dist/agent-src/commands/grill-me.md +3 -2
  64. package/dist/agent-src/commands/image/analyse.md +1 -0
  65. package/dist/agent-src/commands/image/create.md +1 -0
  66. package/dist/agent-src/commands/image/verify.md +1 -0
  67. package/dist/agent-src/commands/image.md +1 -0
  68. package/dist/agent-src/commands/implement-ticket.md +1 -0
  69. package/dist/agent-src/commands/jira-ticket.md +1 -0
  70. package/dist/agent-src/commands/judge/on-diff.md +1 -0
  71. package/dist/agent-src/commands/judge/solo.md +1 -0
  72. package/dist/agent-src/commands/judge/steps.md +1 -0
  73. package/dist/agent-src/commands/judge.md +1 -0
  74. package/dist/agent-src/commands/knowledge/cross-repo.md +1 -0
  75. package/dist/agent-src/commands/knowledge/forget.md +1 -0
  76. package/dist/agent-src/commands/knowledge/ingest.md +1 -0
  77. package/dist/agent-src/commands/knowledge/list.md +1 -0
  78. package/dist/agent-src/commands/knowledge.md +1 -0
  79. package/dist/agent-src/commands/memory/add.md +8 -6
  80. package/dist/agent-src/commands/memory/learn-low-impact.md +3 -2
  81. package/dist/agent-src/commands/memory/load.md +7 -7
  82. package/dist/agent-src/commands/memory/mine-session.md +39 -12
  83. package/dist/agent-src/commands/memory/promote.md +3 -2
  84. package/dist/agent-src/commands/memory/propose.md +7 -6
  85. package/dist/agent-src/commands/memory.md +3 -2
  86. package/dist/agent-src/commands/mode.md +1 -0
  87. package/dist/agent-src/commands/module/create.md +1 -0
  88. package/dist/agent-src/commands/module/explore.md +1 -0
  89. package/dist/agent-src/commands/module.md +1 -0
  90. package/dist/agent-src/commands/optimize/agents-dir.md +1 -0
  91. package/dist/agent-src/commands/optimize/augmentignore.md +1 -0
  92. package/dist/agent-src/commands/optimize/rtk.md +1 -0
  93. package/dist/agent-src/commands/optimize/skills.md +1 -0
  94. package/dist/agent-src/commands/optimize-prompt.md +1 -0
  95. package/dist/agent-src/commands/optimize.md +1 -0
  96. package/dist/agent-src/commands/orchestrate.md +1 -0
  97. package/dist/agent-src/commands/override/create.md +1 -0
  98. package/dist/agent-src/commands/override/manage.md +1 -0
  99. package/dist/agent-src/commands/override.md +1 -0
  100. package/dist/agent-src/commands/package-reset.md +1 -0
  101. package/dist/agent-src/commands/package-test.md +1 -0
  102. package/dist/agent-src/commands/post-as/ghostwriter.md +1 -0
  103. package/dist/agent-src/commands/post-as/me.md +1 -0
  104. package/dist/agent-src/commands/post-as.md +1 -0
  105. package/dist/agent-src/commands/pr/create/description-only.md +1 -0
  106. package/dist/agent-src/commands/pr/create.md +25 -0
  107. package/dist/agent-src/commands/prediction-pool.md +1 -0
  108. package/dist/agent-src/commands/prepare-for-review.md +1 -0
  109. package/dist/agent-src/commands/profile/activate.md +1 -0
  110. package/dist/agent-src/commands/profile/deactivate.md +1 -0
  111. package/dist/agent-src/commands/profile/show.md +1 -0
  112. package/dist/agent-src/commands/profile.md +1 -0
  113. package/dist/agent-src/commands/project-analyze.md +1 -0
  114. package/dist/agent-src/commands/project-health.md +1 -0
  115. package/dist/agent-src/commands/quality-fix.md +1 -0
  116. package/dist/agent-src/commands/refine-ticket.md +1 -0
  117. package/dist/agent-src/commands/research/deep.md +1 -0
  118. package/dist/agent-src/commands/research/report.md +1 -0
  119. package/dist/agent-src/commands/research.md +1 -0
  120. package/dist/agent-src/commands/review-changes.md +1 -0
  121. package/dist/agent-src/commands/review-routing.md +1 -0
  122. package/dist/agent-src/commands/roadmap/ai-council.md +1 -0
  123. package/dist/agent-src/commands/roadmap/create.md +1 -0
  124. package/dist/agent-src/commands/roadmap/process-full.md +1 -0
  125. package/dist/agent-src/commands/roadmap/process-phase.md +1 -0
  126. package/dist/agent-src/commands/roadmap/process-step.md +1 -0
  127. package/dist/agent-src/commands/roadmap.md +1 -0
  128. package/dist/agent-src/commands/rule-compliance-audit.md +1 -0
  129. package/dist/agent-src/commands/security-audit-config.md +84 -0
  130. package/dist/agent-src/commands/set-cost-profile.md +1 -0
  131. package/dist/agent-src/commands/skill/preview.md +1 -0
  132. package/dist/agent-src/commands/skill.md +1 -0
  133. package/dist/agent-src/commands/skills/discover.md +1 -0
  134. package/dist/agent-src/commands/skills.md +1 -0
  135. package/dist/agent-src/commands/sync-agent-settings.md +1 -0
  136. package/dist/agent-src/commands/sync-gitignore/fix.md +1 -0
  137. package/dist/agent-src/commands/sync-gitignore.md +1 -0
  138. package/dist/agent-src/commands/tests/create.md +1 -0
  139. package/dist/agent-src/commands/tests/execute.md +1 -0
  140. package/dist/agent-src/commands/tests.md +1 -0
  141. package/dist/agent-src/commands/threat-model.md +1 -0
  142. package/dist/agent-src/commands/update-form-request-messages.md +1 -0
  143. package/dist/agent-src/commands/upstream-contribute.md +1 -0
  144. package/dist/agent-src/commands/video/from-script.md +1 -0
  145. package/dist/agent-src/commands/video/from-song.md +1 -0
  146. package/dist/agent-src/commands/video/scene.md +1 -0
  147. package/dist/agent-src/commands/video/stitch.md +1 -0
  148. package/dist/agent-src/commands/video/storyboard.md +1 -0
  149. package/dist/agent-src/commands/video.md +1 -0
  150. package/dist/agent-src/commands/work.md +1 -0
  151. package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
  152. package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
  153. package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +2 -2
  154. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -6
  155. package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +2 -2
  156. package/dist/agent-src/contexts/execution/rdp-gate.md +75 -0
  157. package/dist/agent-src/contexts/subagent-configuration.md +1 -0
  158. package/dist/agent-src/personas/advisors/contrarian.md +1 -1
  159. package/dist/agent-src/personas/advisors/executor.md +1 -1
  160. package/dist/agent-src/personas/advisors/expansionist.md +1 -1
  161. package/dist/agent-src/personas/advisors/first-principles.md +1 -1
  162. package/dist/agent-src/personas/advisors/outsider.md +1 -1
  163. package/dist/agent-src/rules/autonomous-execution.md +12 -0
  164. package/dist/agent-src/rules/external-reference-deep-dive.md +1 -1
  165. package/dist/agent-src/rules/git-history-discipline.md +47 -1
  166. package/dist/agent-src/rules/improve-before-implement.md +12 -0
  167. package/dist/agent-src/rules/lethal-trifecta-guard.md +80 -0
  168. package/dist/agent-src/rules/no-pr-progress-comments.md +3 -4
  169. package/dist/agent-src/rules/notes-first-reasoning.md +71 -0
  170. package/dist/agent-src/rules/roadmap-progress-sync.md +48 -31
  171. package/dist/agent-src/rules/security-sensitive-stop.md +14 -1
  172. package/dist/agent-src/rules/source-confidentiality.md +97 -0
  173. package/dist/agent-src/rules/think-before-action.md +9 -1
  174. package/dist/agent-src/rules/untrusted-input-defense.md +76 -0
  175. package/dist/agent-src/scripts/archive_completed_roadmaps.py +171 -0
  176. package/dist/agent-src/skills/adversarial-review/SKILL.md +14 -0
  177. package/dist/agent-src/skills/agent-security-review/SKILL.md +113 -0
  178. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +51 -0
  179. package/dist/agent-src/skills/ai-council/SKILL.md +3 -3
  180. package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
  181. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +12 -11
  182. package/dist/agent-src/skills/command-routing/SKILL.md +1 -1
  183. package/dist/agent-src/skills/complexity-first-planning/SKILL.md +96 -0
  184. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +16 -0
  185. package/dist/agent-src/skills/copilot-config/SKILL.md +3 -4
  186. package/dist/agent-src/skills/defense-in-depth/SKILL.md +1 -1
  187. package/dist/agent-src/skills/developer-like-execution/SKILL.md +5 -4
  188. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
  189. package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
  190. package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
  191. package/dist/agent-src/skills/memory-consolidation/SKILL.md +63 -17
  192. package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
  193. package/dist/agent-src/skills/readme-writing-package/SKILL.md +1 -1
  194. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +119 -0
  195. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +16 -0
  196. package/dist/agent-src/skills/receiving-code-review/SKILL.md +6 -6
  197. package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
  198. package/dist/agent-src/skills/refine-ticket/SKILL.md +1 -1
  199. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  200. package/dist/agent-src/skills/secrets-management/SKILL.md +1 -1
  201. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +10 -3
  202. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  203. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
  204. package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
  205. package/dist/agent-src/templates/agents/.gitattributes.fragment +0 -1
  206. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +4 -4
  207. package/dist/agent-src/templates/scripts/check_memory.py +1 -2
  208. package/dist/agent-src/templates/scripts/check_memory_proposal.py +1 -1
  209. package/dist/agent-src/templates/scripts/memory_lookup.py +148 -289
  210. package/dist/agent-src/templates/scripts/memory_report.py +132 -2
  211. package/dist/agent-src/templates/scripts/memory_signal.py +7 -9
  212. package/dist/agent-src/templates/scripts/memory_status.py +25 -206
  213. package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.py +6 -6
  214. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +3 -3
  215. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.py +0 -1
  216. package/dist/cli/agent-config.js +31 -300
  217. package/dist/cli/agent-config.js.map +1 -1
  218. package/dist/cli/commands/commands.js +10 -5
  219. package/dist/cli/commands/commands.js.map +1 -1
  220. package/dist/cli/discovery/loadManifest.js.map +1 -1
  221. package/dist/cli/main.js +309 -0
  222. package/dist/cli/main.js.map +1 -0
  223. package/dist/discovery/deprecation-report.md +1 -1
  224. package/dist/discovery/discovery-manifest.json +645 -342
  225. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  226. package/dist/discovery/discovery-manifest.summary.md +8 -5
  227. package/dist/discovery/orphan-report.md +1 -1
  228. package/dist/discovery/packs.json +149 -37
  229. package/dist/discovery/trust-report.md +3 -3
  230. package/dist/discovery/workspaces.json +61 -36
  231. package/dist/mcp/registry-manifest.json +4 -4
  232. package/dist/router.json +1 -1
  233. package/dist/server/routes/wizard.js +4 -3
  234. package/dist/server/routes/wizard.js.map +1 -1
  235. package/dist/server/schemas/settings.js +18 -0
  236. package/dist/server/schemas/settings.js.map +1 -1
  237. package/docs/MIGRATION.md +1 -1
  238. package/docs/adrs/cost/0001-hard-stop-hook.md +5 -5
  239. package/docs/adrs/memory/0001-consumer-side-snapshot.md +15 -7
  240. package/docs/adrs/memory/README.md +6 -5
  241. package/docs/adrs/router/0001-three-tier-routing.md +2 -2
  242. package/docs/adrs/schema/0001-json-schema-frontmatter.md +2 -2
  243. package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +5 -5
  244. package/docs/adrs/telegraph/0001-default-off-until-bench.md +3 -3
  245. package/docs/architecture.md +9 -9
  246. package/docs/archive/CHANGELOG-pre-2.2.0.md +30 -30
  247. package/docs/archive/CHANGELOG-pre-2.25.0.md +1 -1
  248. package/docs/archive/CHANGELOG-pre-4.5.0.md +1 -1
  249. package/docs/archive/CHANGELOG-pre-6.0.0.md +473 -0
  250. package/docs/benchmark.md +54 -53
  251. package/docs/benchmarks.md +2 -2
  252. package/docs/case-studies/{frontend-design-vs-ui-ux-pro-max.md → frontend-design-positioning.md} +4 -4
  253. package/docs/catalog.md +20 -13
  254. package/docs/command-flows.md +90 -92
  255. package/docs/contracts/adr-layout.md +2 -3
  256. package/docs/contracts/adr-level-6-productization.md +1 -1
  257. package/docs/contracts/ai-council-config.md +42 -7
  258. package/docs/contracts/command-clusters.md +1 -1
  259. package/docs/contracts/cost-enforcement.md +1 -1
  260. package/docs/contracts/cost-summary-schema.md +1 -1
  261. package/docs/contracts/daily-workspace.md +1 -0
  262. package/docs/contracts/discovery-manifest.schema.json +4 -2
  263. package/docs/contracts/explain-modes.md +1 -1
  264. package/docs/contracts/implement-ticket-flow.md +6 -7
  265. package/docs/contracts/mcp-tool-inventory.md +10 -10
  266. package/docs/contracts/measurement-baseline.md +1 -1
  267. package/docs/contracts/memory-visibility-v1.md +1 -5
  268. package/docs/contracts/namespace.md +1 -1
  269. package/docs/contracts/persona-schema.md +1 -1
  270. package/docs/contracts/rule-interactions.md +1 -1
  271. package/docs/contracts/smoke-contracts.md +1 -1
  272. package/docs/contracts/universal-skills.md +0 -1
  273. package/docs/contracts/workspace-boundary.md +84 -0
  274. package/docs/customization.md +3 -3
  275. package/docs/decisions/ADR-009-event4u-namespace.md +1 -1
  276. package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +1 -1
  277. package/docs/decisions/ADR-026-explain-mode-translation.md +1 -1
  278. package/docs/decisions/ADR-088-no-external-runtime-federation.md +26 -27
  279. package/docs/decisions/ADR-090-visibility-command-frontmatter-field.md +95 -0
  280. package/docs/decisions/ADR-091-split-meta-capability-packs.md +113 -0
  281. package/docs/decisions/ADR-092-defer-command-tier-alias-removal.md +93 -0
  282. package/docs/decisions/ADR-093-ai-council-config-user-global.md +111 -0
  283. package/docs/decisions/ADR-094-agent-memory-layer-removal.md +94 -0
  284. package/docs/decisions/ADR-095-workspace-boundary-contract.md +108 -0
  285. package/docs/decisions/INDEX.md +6 -0
  286. package/docs/development.md +5 -7
  287. package/docs/getting-started.md +4 -4
  288. package/docs/guidelines/agent-infra/5w2h-analysis.md +1 -1
  289. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  290. package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
  291. package/docs/guidelines/agent-infra/critical-thinking.md +1 -1
  292. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +1 -5
  293. package/docs/guidelines/agent-infra/first-principles.md +1 -1
  294. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +164 -0
  295. package/docs/guidelines/agent-infra/inversion-thinking.md +1 -1
  296. package/docs/guidelines/agent-infra/ios-simulator-guide.md +9 -14
  297. package/docs/guidelines/agent-infra/mcp-request-signing.md +19 -22
  298. package/docs/guidelines/agent-infra/memory-access.md +25 -31
  299. package/docs/guidelines/agent-infra/mental-models.md +1 -1
  300. package/docs/guidelines/agent-infra/model-recommendation.md +29 -0
  301. package/docs/guidelines/agent-infra/scqa-framework.md +3 -3
  302. package/docs/guidelines/agent-infra/security-lint-containment.md +81 -0
  303. package/docs/guidelines/agent-infra/six-hats.md +1 -1
  304. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  305. package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +72 -0
  306. package/docs/installation.md +1 -1
  307. package/docs/mcp.md +2 -2
  308. package/docs/parity/{bench-ruflo.json → bench-external.json} +10 -10
  309. package/docs/parity/{ruflo.md → external-runtime.md} +9 -9
  310. package/docs/quality.md +3 -3
  311. package/docs/safety.md +3 -3
  312. package/docs/skills-catalog.md +4 -1
  313. package/llms.txt +3 -0
  314. package/package.json +1 -1
  315. package/src/config/agent-settings.template.yml +65 -3
  316. package/src/config/discovery/packs.yml +29 -0
  317. package/src/config/discovery/workspaces.yml +3 -1
  318. package/src/config/gitignore-block.txt +6 -0
  319. package/src/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  320. package/src/scripts/_cli/cmd_doctor.py +99 -13
  321. package/src/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  322. package/src/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  323. package/src/scripts/_lib/bench_ab_scoring_v2.py +227 -0
  324. package/src/scripts/_lib/global_deploy_inventory.py +39 -9
  325. package/src/scripts/_lib/link_crypto.py +206 -0
  326. package/src/scripts/_lib/security_lint.py +228 -0
  327. package/src/scripts/ai_council/clients.py +2 -2
  328. package/src/scripts/ai_council/config.py +55 -0
  329. package/src/scripts/audit_adr_coverage.py +0 -2
  330. package/src/scripts/audit_command_surface.py +18 -5
  331. package/src/scripts/audit_mcp_tools.py +2 -2
  332. package/src/scripts/audit_skill_descriptions.py +2 -2
  333. package/src/scripts/bench_ab_clone.py +62 -12
  334. package/src/scripts/bench_ab_task_runner.py +475 -30
  335. package/src/scripts/bench_ab_v2_run.py +247 -0
  336. package/src/scripts/bench_ab_v2_stats.py +347 -0
  337. package/src/scripts/bench_run.py +1 -1
  338. package/src/scripts/build_discovery_manifest.py +10 -0
  339. package/src/scripts/check_bite_sized_granularity.py +1 -2
  340. package/src/scripts/check_memory.py +49 -63
  341. package/src/scripts/check_memory_proposal.py +1 -1
  342. package/src/scripts/check_no_external_sources.py +101 -0
  343. package/src/scripts/check_references.py +2 -0
  344. package/src/scripts/cost_by_conversation.py +1 -1
  345. package/src/scripts/council_cli.py +28 -14
  346. package/src/scripts/external_sources_denylist.json +91 -0
  347. package/src/scripts/hook_manifest.yaml +14 -6
  348. package/src/scripts/injection_scan_hook.py +145 -0
  349. package/src/scripts/install-hooks.sh +11 -0
  350. package/src/scripts/install.py +88 -13
  351. package/src/scripts/lint_agent_security.py +112 -0
  352. package/src/scripts/lint_bench_ab.py +5 -4
  353. package/src/scripts/lint_command_tiers.py +63 -22
  354. package/src/scripts/lint_discovery_vocabulary.py +2 -0
  355. package/src/scripts/lint_empty_roadmaps.py +80 -0
  356. package/src/scripts/lint_hidden_unicode.py +132 -0
  357. package/src/scripts/lint_instruction_smuggling.py +107 -0
  358. package/src/scripts/lint_marketplace.py +1 -1
  359. package/src/scripts/lint_mcp_config_security.py +124 -0
  360. package/src/scripts/lint_skill_frontmatter_safety.py +144 -0
  361. package/src/scripts/lint_workspace_boundary.py +122 -0
  362. package/src/scripts/mcp_server/consumer_tool_catalog.json +2 -3
  363. package/src/scripts/mcp_server/tools.py +8 -32
  364. package/src/scripts/memory_lookup.py +27 -296
  365. package/src/scripts/memory_report.py +1 -23
  366. package/src/scripts/memory_signal.py +6 -53
  367. package/src/scripts/memory_status.py +25 -206
  368. package/src/scripts/mine_session.py +118 -41
  369. package/src/scripts/pack_dependency_allowlist.json +2 -2
  370. package/src/scripts/render_benchmark_md.py +141 -52
  371. package/src/scripts/schemas/command.schema.json +6 -1
  372. package/src/scripts/security_audit_config.py +153 -0
  373. package/dist/agent-src/commands/chat-history/learn.md +0 -184
  374. package/dist/agent-src/commands/chat-history/show.md +0 -113
  375. package/dist/agent-src/commands/fix/pr-bot-comments.md +0 -157
  376. package/dist/agent-src/commands/fix/pr-developer-comments.md +0 -163
  377. package/dist/agent-src/templates/agents/memory/architecture-decisions.example.yml +0 -95
  378. package/docs/contracts/agent-memory-contract.md +0 -159
@@ -1,28 +1,23 @@
1
1
  #!/usr/bin/env python3
2
- """Hybrid retrieval — file-first with optional package augmentation.
2
+ """File-first memory retrieval.
3
3
 
4
4
  Implements the shared `retrieve(types, keys, limit)` abstraction used
5
5
  by skills. Reads YAML under `agents/memory/<type>/` (curated, hand-
6
6
  reviewed) and JSONL under `agents/memory/intake/*.jsonl` (agent-written,
7
- append-only, supersede-chain aware).
7
+ append-only, supersede-chain aware), plus user-ingested `knowledge`
8
+ chunks and opted-in `cross-repo` matches.
8
9
 
9
- When the `@event4u/agent-memory` package is present (see
10
- `scripts/memory_status.py`), callers can pass the result of
11
- :func:`package_operational_provider` to route additional retrieval
12
- through the package's semantic CLI. Repo entries always win on
13
- conflict — see `_apply_conflict_rule`.
10
+ Retrieval is entirely repo-side and file-backed — there is no external
11
+ backend. (The former optional `@event4u/agent-memory` package routing
12
+ was removed; see `docs/decisions/` for the agent-memory removal ADR.)
14
13
 
15
14
  Usage:
16
15
  python3 scripts/memory_lookup.py --types domain-invariants,ownership \\
17
16
  --key "app/Http/Controllers/Foo" --limit 5
18
17
  python3 scripts/memory_lookup.py --types incident-learnings --format json
19
- python3 scripts/memory_lookup.py --types ownership --key billing --auto
20
18
 
21
- from scripts.memory_lookup import retrieve, package_operational_provider
22
- hits = retrieve(
23
- types=["ownership"], keys=["app/Http"], limit=3,
24
- operational_provider=package_operational_provider(),
25
- )
19
+ from scripts.memory_lookup import retrieve
20
+ hits = retrieve(types=["ownership"], keys=["app/Http"], limit=3)
26
21
  """
27
22
 
28
23
  from __future__ import annotations
@@ -30,31 +25,43 @@ from __future__ import annotations
30
25
  import argparse
31
26
  import fnmatch
32
27
  import json
33
- import os
34
- import subprocess
35
28
  import sys
36
29
  from dataclasses import dataclass, asdict, field
37
30
  from pathlib import Path
38
- from typing import Any, Callable, Iterable, Optional, Union
31
+ from typing import Iterable, Union
39
32
 
40
33
  MEMORY_ROOT = Path("agents/memory")
41
34
  INTAKE_ROOT = MEMORY_ROOT / "intake"
35
+ KNOWLEDGE_ROOT = MEMORY_ROOT / "knowledge"
42
36
 
43
37
  CURATED_TYPES = {
44
38
  "ownership",
45
39
  "historical-patterns",
46
40
  "domain-invariants",
47
- "architecture-decisions",
48
41
  "incident-learnings",
49
42
  "product-rules",
50
43
  }
51
44
 
45
+ # `knowledge` is its own type: user-ingested local documents that live
46
+ # under `agents/memory/knowledge/<ingest-id>/chunks/*.md`. They are
47
+ # repo-side (file-backed) but not "curated" and not intake.
48
+ KNOWLEDGE_TYPE = "knowledge"
49
+
50
+ # Cross-repo retrieval (road-to-leaner-core-and-discovery Phase 4). When this
51
+ # type is requested AND opted-in linked-project siblings exist, matches from
52
+ # scripts/cross_repo_retrieve.py are projected as `source="cross-repo"` Hits,
53
+ # scored below curated/knowledge so cross-repo context never outranks the
54
+ # project's own truth (mirrors the 0.85× knowledge discount, then floored
55
+ # further). Opt-in by caller (type must be requested) + lazy import → existing
56
+ # call sites and consumers without the script are unaffected.
57
+ CROSS_REPO_TYPE = "cross-repo"
58
+
52
59
 
53
60
  @dataclass
54
61
  class Hit:
55
62
  id: str
56
63
  type: str
57
- source: str # "curated" | "intake" | "operational"
64
+ source: str # "curated" | "intake" | "knowledge" | "cross-repo"
58
65
  path: str # file (or logical locator) that produced the hit
59
66
  score: float # naive, content-match based [0..1]
60
67
  entry: dict = field(default_factory=dict)
@@ -63,36 +70,13 @@ class Hit:
63
70
  return asdict(self)
64
71
 
65
72
 
66
- @dataclass
67
- class Shadow:
68
- """An operational entry suppressed by the conflict rule."""
69
- id: str
70
- type: str
71
- reason: str # "same-id" | "repo-deprecated"
72
- operational_path: str # where the suppressed entry came from
73
- repo_path: str # repo entry that shadowed it
74
-
75
- def as_dict(self) -> dict:
76
- return asdict(self)
77
-
78
-
79
73
  @dataclass
80
74
  class RetrievalResult:
81
- """Full retrieval payload with conflict-rule observability."""
75
+ """Full retrieval payload."""
82
76
  hits: list
83
- shadows: list = field(default_factory=list)
84
77
 
85
78
  def as_dict(self) -> dict:
86
- return {
87
- "hits": [h.as_dict() for h in self.hits],
88
- "shadows": [s.as_dict() for s in self.shadows],
89
- }
90
-
91
-
92
- # An operational provider returns repo-shaped Hit objects with
93
- # source="operational". Backend adapters (e.g. @event4u/agent-memory)
94
- # are expected to translate their native payload into this shape.
95
- OperationalProvider = Callable[[list[str], list[str]], Iterable[Hit]]
79
+ return {"hits": [h.as_dict() for h in self.hits]}
96
80
 
97
81
 
98
82
  def _load_yaml(path: Path):
@@ -167,11 +151,62 @@ def _iter_intake_entries(mtype: str) -> Iterable[tuple[Path, dict]]:
167
151
  yield jsonl, obj
168
152
 
169
153
 
154
+ def _iter_knowledge_entries() -> Iterable[tuple[Path, dict]]:
155
+ """Yield (chunk-file, entry) pairs from `agents/memory/knowledge/`.
156
+
157
+ Layout (frozen in `docs/contracts/local-knowledge-ingestion.md`):
158
+
159
+ agents/memory/knowledge/<ingest-id>/
160
+ manifest.json
161
+ chunks/<n>.md
162
+
163
+ Each chunk becomes one retrieval entry. The chunk body, the
164
+ manifest source path, and pinned flag are surfaced into the entry
165
+ so `_score()` can match on either the source path or the chunk
166
+ text. The entry id is ``<ingest-id>:<chunk-stem>`` so callers can
167
+ locate the exact file on disk.
168
+ """
169
+ if not KNOWLEDGE_ROOT.is_dir():
170
+ return
171
+ for ingest_dir in sorted(KNOWLEDGE_ROOT.iterdir()):
172
+ if not ingest_dir.is_dir():
173
+ continue
174
+ manifest_path = ingest_dir / "manifest.json"
175
+ manifest: dict = {}
176
+ if manifest_path.is_file():
177
+ try:
178
+ manifest = json.loads(
179
+ manifest_path.read_text(encoding="utf-8")
180
+ )
181
+ except (ValueError, OSError):
182
+ manifest = {}
183
+ ingest_id = str(manifest.get("ingest_id") or ingest_dir.name)
184
+ source = str(manifest.get("source") or "")
185
+ pinned = bool(manifest.get("pinned", False))
186
+ chunks_dir = ingest_dir / "chunks"
187
+ if not chunks_dir.is_dir():
188
+ continue
189
+ for chunk in sorted(chunks_dir.glob("*.md")):
190
+ try:
191
+ body = chunk.read_text(encoding="utf-8")
192
+ except OSError:
193
+ continue
194
+ entry = {
195
+ "id": f"{ingest_id}:{chunk.stem}",
196
+ "ingest_id": ingest_id,
197
+ "source": source,
198
+ "path": source,
199
+ "body": body,
200
+ "pinned": pinned,
201
+ "source_kind": "knowledge",
202
+ }
203
+ yield chunk, entry
204
+
205
+
170
206
  def _score(entry: dict, keys: list[str]) -> float:
171
207
  """Naive relevance score: max over keys of (glob-match | substring).
172
208
 
173
- Good enough for the `absent` path where retrieval is best-effort.
174
- The `present` path returns a real score from agent-memory.
209
+ Good enough for best-effort file retrieval.
175
210
  """
176
211
  if not keys:
177
212
  return 0.1 # any hit beats no hit when there is no key
@@ -193,191 +228,80 @@ def _score(entry: dict, keys: list[str]) -> float:
193
228
  return best
194
229
 
195
230
 
196
- def _apply_conflict_rule(
197
- repo_hits: list[Hit],
198
- operational_hits: list[Hit],
199
- ) -> tuple[list[Hit], list[Shadow]]:
200
- """Enforce REPO WINS / OPERATIONAL AUGMENTS / NEVER CONTRADICTS SILENTLY.
231
+ def _cross_repo_hits(keys: list[str], limit: int) -> list[Hit]:
232
+ """Project cross-repo matches into discounted, tagged Hits.
201
233
 
202
- Reference: `agents/roadmaps/road-to-memory-self-consumption.md` §
203
- "Conflict rule: repo vs. operational". The four cases mapped below
204
- are covered by `tests/test_conflict_rule.py`.
234
+ Lazy + guarded: imports `cross_repo_retrieve` on demand and swallows any
235
+ failure (script absent in a consumer install, no opted-in siblings) so the
236
+ cross-repo type degrades to zero hits rather than breaking retrieval. Scores
237
+ sit below curated/knowledge (0.85× floor, then a small per-rank decrement)
238
+ so cross-repo context never outranks the project's own truth.
205
239
  """
206
- # Repo entries index curated AND intake both count as "repo" for
207
- # the conflict rule. The operational store is the only non-repo side.
208
- repo_by_id: dict[str, Hit] = {h.id: h for h in repo_hits if h.id}
209
-
210
- merged: list[Hit] = list(repo_hits)
211
- shadows: list[Shadow] = []
212
-
213
- for op in operational_hits:
214
- if op.id and op.id in repo_by_id:
215
- # Case 1+2: same id → repo wins (including when repo is
216
- # status:deprecated — operational cannot revive a retired
217
- # entry). Suppress the operational entry and record shadow.
218
- repo = repo_by_id[op.id]
219
- reason = (
220
- "repo-deprecated"
221
- if repo.entry.get("status") == "deprecated"
222
- else "same-id"
223
- )
224
- shadows.append(Shadow(
225
- id=op.id,
226
- type=op.type,
227
- reason=reason,
228
- operational_path=op.path,
229
- repo_path=repo.path,
230
- ))
231
- continue
232
- # Case 3 (different ids on same logical key) and Case 4 (repo
233
- # has no entry) — both simply include the operational hit.
234
- # Repo entries naturally rank higher because their score is not
235
- # discounted (see _score / operational scoring in retrieve()).
236
- merged.append(op)
237
-
238
- return merged, shadows
239
-
240
-
241
- # ---------------------------------------------------------------------------
242
- # Package-backed operational provider (the `present` path)
243
- # ---------------------------------------------------------------------------
244
- #
245
- # When `memory_status.status() == "present"` the consumer-facing contract
246
- # says retrieval should route through `@event4u/agent-memory`. The package
247
- # CLI is purely **semantic** (`memory retrieve <query> --type T …`); the
248
- # shared `retrieve(types, keys, …)` API is **key-based**. The hybrid
249
- # resolution agreed in `docs/contracts/agent-memory-contract.md` synthesises
250
- # `keys` into a single natural-language query for the package call, while
251
- # the file fallback continues to do glob/substring matching on the same
252
- # keys. Both legs land in the same `Hit` shape so the conflict rule can
253
- # merge them transparently.
254
-
255
- _CLI_TIMEOUT_SECONDS = 5.0
256
- _CLI_RETRIEVE_LIMIT_DEFAULT = 20
257
-
258
-
259
- def _synthesize_query(keys: list[str]) -> str:
260
- """Turn a list of retrieval keys into one natural-language query.
261
-
262
- Keys are typically file paths (`app/Http/Controllers/Foo`), feature
263
- names (`billing`), or short identifiers — joining them with spaces
264
- gives the package's semantic search enough surface to score against
265
- without inventing structure. Empty or whitespace-only keys are
266
- dropped; if nothing remains the caller falls back to the file path.
267
- """
268
- cleaned = [k.strip() for k in keys if isinstance(k, str) and k.strip()]
269
- return " ".join(cleaned)
270
-
271
-
272
- def _cli_operational_provider(
273
- types: list[str],
274
- keys: list[str],
275
- *,
276
- cli_path: str = "memory",
277
- timeout: float = _CLI_TIMEOUT_SECONDS,
278
- limit: int = _CLI_RETRIEVE_LIMIT_DEFAULT,
279
- ) -> Iterable[Hit]:
280
- """Run `memory retrieve` and yield operational `Hit` objects.
281
-
282
- Pino structured logs from the package go to stderr; stdout is a
283
- clean v1 retrieval envelope. Any non-zero exit, timeout, or parse
284
- failure degrades to "no operational hits" — `retrieve()` already
285
- treats provider exceptions as a soft warning, so the caller still
286
- gets the file-fallback result.
287
- """
288
- query = _synthesize_query(keys)
240
+ query = " ".join(k for k in keys if k).strip()
289
241
  if not query:
290
- return
291
- cmd: list[str] = [cli_path, "retrieve", query, "--limit", str(limit)]
292
- for t in types:
293
- cmd.extend(["--type", t])
294
- try:
295
- out = subprocess.run(
296
- cmd,
297
- capture_output=True, text=True, timeout=timeout,
298
- )
299
- except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
300
- return
301
- if out.returncode != 0:
302
- return
242
+ return []
303
243
  try:
304
- envelope = json.loads(out.stdout)
305
- except (ValueError, TypeError):
306
- return
307
- entries = envelope.get("entries") if isinstance(envelope, dict) else None
308
- if not isinstance(entries, list):
309
- return
310
- for e in entries:
311
- if not isinstance(e, dict):
312
- continue
313
- eid = e.get("id")
314
- etype = e.get("type")
315
- if not isinstance(eid, str) or not isinstance(etype, str):
316
- continue
317
- # The package returns `confidence` (0..1) per the v1 envelope;
318
- # map it onto our internal `score` field so the conflict rule
319
- # and ranking work uniformly across providers.
320
- try:
321
- score = float(e.get("confidence", 0.0))
322
- except (TypeError, ValueError):
323
- score = 0.0
324
- body = e.get("body") if isinstance(e.get("body"), dict) else {}
325
- yield Hit(
326
- id=eid,
327
- type=etype,
328
- source="operational",
329
- path=f"agent-memory:{eid}",
330
- score=score,
331
- entry=body,
332
- )
333
-
334
-
335
- def package_operational_provider() -> Optional[OperationalProvider]:
336
- """Return a CLI-backed provider when the package is `present`, else None.
337
-
338
- Callers who want automatic backend routing pass the result directly
339
- to :func:`retrieve` — `None` is a safe value that yields file-only
340
- retrieval, so this is the recommended one-liner for skills:
341
-
342
- retrieve(types, keys, operational_provider=package_operational_provider())
343
-
344
- The status probe is bounded (≤ 2s, cached per process) — see
345
- `scripts/memory_status.py`. We import lazily so pure file-fallback
346
- callers never pay for the probe.
347
- """
348
- # Late import: keeps `memory_lookup` importable even when
349
- # `memory_status` is missing in stripped consumer installs.
350
- try:
351
- sys.path.insert(0, str(Path(__file__).resolve().parent))
352
- import memory_status # type: ignore[import-not-found]
353
- except ImportError:
354
- return None
355
- if memory_status.status().status != "present":
356
- return None
357
- return _cli_operational_provider
244
+ import os
245
+ import sys as _sys
246
+ from pathlib import Path as _Path
247
+
248
+ here = _Path(__file__).resolve().parent
249
+ if str(here) not in _sys.path:
250
+ _sys.path.insert(0, str(here))
251
+ import cross_repo_retrieve # type: ignore
252
+
253
+ result = cross_repo_retrieve.retrieve(_Path(os.getcwd()), query, None, limit)
254
+ except Exception: # noqa: BLE001 — optional surface; never break retrieval
255
+ return []
256
+
257
+ hits: list[Hit] = []
258
+ for i, m in enumerate(result.get("matches", [])):
259
+ hits.append(Hit(
260
+ id=f"cross-repo:{m.get('source_repo', '')}:{m.get('path', '')}",
261
+ type=CROSS_REPO_TYPE,
262
+ source="cross-repo",
263
+ path=f"{m.get('source_repo', '')}/{m.get('path', '')}",
264
+ score=round(0.7 * 0.85 - i * 0.01, 4),
265
+ entry=m,
266
+ ))
267
+ return hits
358
268
 
359
269
 
360
270
  def retrieve(
361
271
  types: list[str],
362
272
  keys: list[str],
363
273
  limit: int = 5,
364
- operational_provider: Optional[OperationalProvider] = None,
365
- with_shadows: bool = False,
366
- ) -> Union[list[Hit], RetrievalResult]:
274
+ ) -> list[Hit]:
367
275
  """Return up to `limit` hits across the requested types, highest score first.
368
276
 
369
277
  Repo entries (curated + intake) are preferred on ties — they are
370
- hand-reviewed or session-captured against the repo itself. When an
371
- `operational_provider` is supplied (the `present` path of the
372
- backend-detection contract), its results are merged under the
373
- REPO WINS conflict rule; suppressed operational entries surface as
374
- `shadows` when `with_shadows=True`.
375
-
376
- The return type stays `list[Hit]` by default for backward
377
- compatibility with existing skill call sites.
278
+ hand-reviewed or session-captured against the repo itself. Knowledge
279
+ and cross-repo hits are discounted so the project's own truth wins on
280
+ equal relevance.
378
281
  """
379
282
  repo_hits: list[Hit] = []
380
283
  for mtype in types:
284
+ if mtype == KNOWLEDGE_TYPE:
285
+ for path, entry in _iter_knowledge_entries():
286
+ base = _score(entry, keys)
287
+ # Pinned entries get a slight ranking boost so the
288
+ # `/knowledge:list --pin` flag has retrieval effect.
289
+ if entry.get("pinned"):
290
+ base = min(1.0, base + 0.05)
291
+ repo_hits.append(Hit(
292
+ id=str(entry.get("id", "")),
293
+ type=KNOWLEDGE_TYPE,
294
+ source="knowledge",
295
+ path=str(path),
296
+ # Discount vs curated/intake so hand-reviewed repo
297
+ # entries still win on equal relevance.
298
+ score=base * 0.85,
299
+ entry=entry,
300
+ ))
301
+ continue
302
+ if mtype == CROSS_REPO_TYPE:
303
+ repo_hits.extend(_cross_repo_hits(keys, limit))
304
+ continue
381
305
  if mtype not in CURATED_TYPES:
382
306
  continue
383
307
  for path, entry in _iter_curated_entries(mtype):
@@ -399,41 +323,22 @@ def retrieve(
399
323
  entry=entry,
400
324
  ))
401
325
 
402
- operational_hits: list[Hit] = []
403
- if operational_provider is not None:
404
- try:
405
- for oh in operational_provider(list(types), list(keys)) or []:
406
- # Discount operational vs curated/intake so repo ranks
407
- # higher on equal relevance. Providers may already return
408
- # trust-adjusted scores; we only apply a floor discount.
409
- oh.score = min(oh.score, 0.85)
410
- operational_hits.append(oh)
411
- except Exception as exc: # noqa: BLE001 — providers are external
412
- print(f"warning: operational_provider raised "
413
- f"{exc.__class__.__name__}: {exc}", file=sys.stderr)
414
-
415
- merged, shadows = _apply_conflict_rule(repo_hits, operational_hits)
416
- merged.sort(key=lambda h: (h.score, h.source == "curated"), reverse=True)
417
- positives = [h for h in merged if h.score > 0]
418
- final_hits = (positives or merged)[:limit]
419
-
420
- if with_shadows:
421
- return RetrievalResult(hits=final_hits, shadows=shadows)
422
- return final_hits
326
+ repo_hits.sort(key=lambda h: (h.score, h.source == "curated"), reverse=True)
327
+ positives = [h for h in repo_hits if h.score > 0]
328
+ return (positives or repo_hits)[:limit]
423
329
 
424
330
 
425
331
  CONTRACT_VERSION = 1
426
332
 
427
333
  # Memory types this file-backed backend can answer. Types outside this
428
334
  # set map to `unknown_type` per the retrieval contract.
429
- _KNOWN_TYPES = CURATED_TYPES
335
+ _KNOWN_TYPES = CURATED_TYPES | {KNOWLEDGE_TYPE, CROSS_REPO_TYPE}
430
336
 
431
337
 
432
338
  def retrieve_v1(
433
339
  types: list[str],
434
340
  keys: list[str],
435
341
  limit: int = 20,
436
- operational_provider: Optional[OperationalProvider] = None,
437
342
  ) -> dict:
438
343
  """Return a v1 retrieval-contract envelope.
439
344
 
@@ -441,49 +346,27 @@ def retrieve_v1(
441
346
  the shape defined by
442
347
  ``internal/schemas/retrieval-v1.schema.json``. Unknown types are reported as
443
348
  ``status: unknown_type`` for that slice only, rather than failing
444
- the whole call.
349
+ the whole call. All entries are file-backed (``source: "repo"``).
445
350
  """
446
351
  known = [t for t in types if t in _KNOWN_TYPES]
447
352
  unknown = [t for t in types if t not in _KNOWN_TYPES]
448
353
 
449
- result = retrieve(known, keys, limit=limit,
450
- operational_provider=operational_provider,
451
- with_shadows=True)
452
- assert isinstance(result, RetrievalResult)
453
- hits, shadows = result.hits, result.shadows
454
- shadow_by_id = {s.id: s for s in shadows if s.id}
354
+ hits = retrieve(known, keys, limit=limit)
455
355
 
456
356
  slice_counts: dict[str, int] = {t: 0 for t in known}
457
357
  entries: list[dict] = []
458
358
  for h in hits:
459
- source = "operational" if h.source == "operational" else "repo"
460
359
  envelope_entry: dict = {
461
360
  "id": h.id,
462
361
  "type": h.type,
463
- "source": source,
362
+ "source": "repo",
464
363
  "confidence": round(float(h.score), 4),
465
364
  "body": dict(h.entry) if isinstance(h.entry, dict) else {},
466
- "shadowed_by": None,
467
365
  }
468
366
  if h.type in slice_counts:
469
367
  slice_counts[h.type] += 1
470
368
  entries.append(envelope_entry)
471
369
 
472
- # Surface shadowed operational entries as additional entries carrying
473
- # `shadowed_by`. The conformance harness checks that only
474
- # source="operational" entries ever set this field.
475
- for sid, s in shadow_by_id.items():
476
- entries.append({
477
- "id": sid,
478
- "type": s.type,
479
- "source": "operational",
480
- "confidence": 0.0,
481
- "body": {},
482
- "shadowed_by": f"repo:{sid}",
483
- })
484
- if s.type in slice_counts:
485
- slice_counts[s.type] += 1
486
-
487
370
  slices: dict[str, dict] = {
488
371
  t: {"status": "ok", "count": slice_counts.get(t, 0)}
489
372
  for t in known
@@ -527,35 +410,18 @@ def main() -> int:
527
410
  ap.add_argument("--envelope", choices=["legacy", "v1"], default="legacy",
528
411
  help="Output shape: `legacy` (Hit list) or `v1` "
529
412
  "(retrieval contract v1 envelope). `v1` implies JSON output.")
530
- ap.add_argument("--with-shadows", action="store_true",
531
- help="Include shadowed-operational entries in the output "
532
- "(no-op until an operational backend is wired)")
533
- ap.add_argument("--auto", action="store_true",
534
- help="Auto-route to the @event4u/agent-memory package "
535
- "when memory_status.status() == 'present'; "
536
- "falls through to file-only retrieval otherwise")
537
413
  args = ap.parse_args()
538
414
  types = [t.strip() for t in args.types.split(",") if t.strip()]
539
415
  if not types:
540
416
  print("error: --types is required", file=sys.stderr)
541
417
  return 2
542
- op_provider = package_operational_provider() if args.auto else None
543
418
  if args.envelope == "v1":
544
- envelope = retrieve_v1(types, args.key, args.limit,
545
- operational_provider=op_provider)
419
+ envelope = retrieve_v1(types, args.key, args.limit)
546
420
  print(json.dumps(envelope, indent=2, default=str))
547
421
  return 0
548
- result = retrieve(types, args.key, args.limit,
549
- operational_provider=op_provider,
550
- with_shadows=args.with_shadows)
551
- if args.with_shadows:
552
- assert isinstance(result, RetrievalResult)
553
- hits, shadows = result.hits, result.shadows
554
- else:
555
- hits, shadows = result, [] # type: ignore[assignment]
422
+ hits = retrieve(types, args.key, args.limit)
556
423
  if args.format == "json":
557
- payload = {"hits": [h.as_dict() for h in hits],
558
- "shadows": [s.as_dict() for s in shadows]}
424
+ payload = {"hits": [h.as_dict() for h in hits]}
559
425
  print(json.dumps(payload, indent=2, default=str))
560
426
  else:
561
427
  if not hits:
@@ -563,13 +429,6 @@ def main() -> int:
563
429
  for h in hits:
564
430
  print(f" [{h.source}] {h.type} score={h.score:.2f} "
565
431
  f"id={h.id or '-'} path={h.path}")
566
- if shadows:
567
- print(f"\n shadows: {len(shadows)} operational entr"
568
- f"{'y' if len(shadows) == 1 else 'ies'} suppressed by "
569
- f"the conflict rule")
570
- for s in shadows:
571
- print(f" [{s.reason}] {s.type} id={s.id} "
572
- f"op={s.operational_path} repo={s.repo_path}")
573
432
  return 0
574
433
 
575
434