skilldrop-cli 0.16.44 → 0.16.46

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 (255) hide show
  1. package/catalogue.json +1 -0
  2. package/model-routing.json +1 -0
  3. package/package.json +1 -1
  4. package/packs/converters/skills/md-to-html/manifest.json +1 -1
  5. package/packs/converters/skills/md-to-html/scripts/md_to_html.py +3 -0
  6. package/packs/design/skills/brand-kit/manifest.json +1 -1
  7. package/packs/design/skills/brand-kit/scripts/check_brand.py +11 -1
  8. package/packs/dev-team/skills/behaviour-equivalence/manifest.json +1 -1
  9. package/packs/dev-team/skills/behaviour-equivalence/scripts/golden_diff.py +11 -1
  10. package/packs/frontend/skills/bundle-size-review/manifest.json +1 -1
  11. package/packs/frontend/skills/bundle-size-review/scripts/bundle_stats.py +13 -1
  12. package/packs/frontend/skills/web-performance-review/manifest.json +1 -1
  13. package/packs/frontend/skills/web-performance-review/scripts/lh_summary.py +12 -2
  14. package/packs/grc/skills/risk-register/manifest.json +1 -1
  15. package/packs/grc/skills/risk-register/scripts/check_register.py +9 -1
  16. package/packs/infra-as-code/skills/terraform-plan-review/manifest.json +1 -1
  17. package/packs/infra-as-code/skills/terraform-plan-review/scripts/plan_summary.py +12 -2
  18. package/packs/product-manager/skills/feedback-synthesis/manifest.json +1 -1
  19. package/packs/product-manager/skills/feedback-synthesis/scripts/theme_counts.py +6 -1
  20. package/packs/research/skills/hypothesis-comparison/manifest.json +1 -1
  21. package/packs/research/skills/hypothesis-comparison/scripts/ach_matrix.py +10 -2
  22. package/packs/solution-architect/skills/context-graph/SKILL.md +119 -0
  23. package/packs/solution-architect/skills/context-graph/evals/eval_queries.json +11 -0
  24. package/packs/solution-architect/skills/context-graph/evals/evals.json +225 -0
  25. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0001-record-architecture-decisions.md +19 -0
  26. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0002-postgres-as-primary-database.md +16 -0
  27. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0003-use-redis-for-session-storage.md +24 -0
  28. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0004-structured-json-logging.md +15 -0
  29. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0005-session-lifetime-eight-hours.md +22 -0
  30. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0006-move-sessions-to-postgres.md +16 -0
  31. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0007-stateless-signed-session-cookies.md +35 -0
  32. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/__init__.py +0 -0
  33. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/db.py +0 -0
  34. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/logging_setup.py +0 -0
  35. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/__init__.py +0 -0
  36. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/cookie_sessions.py +7 -0
  37. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/redis_sessions.py +7 -0
  38. package/packs/solution-architect/skills/context-graph/evals/files/10/README.md +8 -0
  39. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0001-record-architecture-decisions.md +10 -0
  40. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0004-service-auth-hmac-shared-keys.md +21 -0
  41. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0007-secrets-from-vault-agent.md +19 -0
  42. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0011-service-auth-mtls.md +23 -0
  43. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/app.py +16 -0
  44. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/__init__.py +4 -0
  45. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/hmac_verify.py +31 -0
  46. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/config/settings.py +14 -0
  47. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/__init__.py +4 -0
  48. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/mtls.py +18 -0
  49. package/packs/solution-architect/skills/context-graph/evals/files/11/README.md +4 -0
  50. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/base.py +3 -0
  51. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/line_item.py +14 -0
  52. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/order.py +24 -0
  53. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-003-money-as-minor-units.md +10 -0
  54. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-005-orders-typed-columns-only.md +10 -0
  55. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-009-line-items-immutable.md +11 -0
  56. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-014-optional-order-attributes-json.md +16 -0
  57. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-016-order-attributes-table.md +11 -0
  58. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0007_create_orders.sql +11 -0
  59. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0012_add_order_attributes.sql +2 -0
  60. package/packs/solution-architect/skills/context-graph/evals/files/12/README.md +8 -0
  61. package/packs/solution-architect/skills/context-graph/evals/files/12/config/delivery.yaml +4 -0
  62. package/packs/solution-architect/skills/context-graph/evals/files/12/config/export.yaml +2 -0
  63. package/packs/solution-architect/skills/context-graph/evals/files/12/config/partners.yaml +10 -0
  64. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0001-record-architecture-decisions.md +10 -0
  65. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0002-postgres-delivery-log.md +15 -0
  66. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0003-redis-idempotency-keys.md +15 -0
  67. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0004-retry-policy.md +16 -0
  68. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0005-hmac-signed-payloads.md +10 -0
  69. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0006-postgres-idempotency.md +15 -0
  70. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0007-sftp-batch-export.md +12 -0
  71. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0008-partner-config-in-yaml.md +12 -0
  72. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0009-partner-config-admin-api.md +13 -0
  73. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/003_idempotency_keys.sql +6 -0
  74. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/004_partners.sql +7 -0
  75. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/dispatcher.py +29 -0
  76. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/retry.py +15 -0
  77. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/signing.py +13 -0
  78. package/packs/solution-architect/skills/context-graph/evals/files/12/src/export/s3_export.py +24 -0
  79. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/pg_store.py +11 -0
  80. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/redis_store.py +8 -0
  81. package/packs/solution-architect/skills/context-graph/evals/files/12/src/partners/loader.py +15 -0
  82. package/packs/solution-architect/skills/context-graph/evals/files/12/src/store/delivery_log.py +18 -0
  83. package/packs/solution-architect/skills/context-graph/evals/files/13/README.md +3 -0
  84. package/packs/solution-architect/skills/context-graph/evals/files/13/config/cache.yaml +2 -0
  85. package/packs/solution-architect/skills/context-graph/evals/files/13/config/settings.yaml +2 -0
  86. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-008-pricing-from-erp.md +10 -0
  87. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-012-pricing-cache.md +23 -0
  88. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-015-checkout-price-lock.md +15 -0
  89. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-019-pricing-service.md +17 -0
  90. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/catalog/views.py +8 -0
  91. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/checkout/lock.py +14 -0
  92. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/cache.py +22 -0
  93. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/client.py +10 -0
  94. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0001-idempotency-keys.md +33 -0
  95. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0002-processor-retry-policy.md +26 -0
  96. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0003-money-in-minor-units.md +31 -0
  97. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0004-webhook-signing.md +27 -0
  98. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0005-retry-with-jitter.md +30 -0
  99. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0006-idempotency-at-gateway.md +28 -0
  100. package/packs/solution-architect/skills/context-graph/evals/files/14/pr-summary.md +27 -0
  101. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/amount.ts +10 -0
  102. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/charge.ts +28 -0
  103. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/idempotency.ts +4 -0
  104. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/retry.ts +21 -0
  105. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/send.ts +9 -0
  106. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/sign.ts +6 -0
  107. package/packs/solution-architect/skills/context-graph/evals/files/15/deploy/services.yaml +14 -0
  108. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0001-record-architecture-decisions.md +20 -0
  109. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0002-use-postgresql-for-shipment-data.md +23 -0
  110. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0003-store-vehicle-telemetry-in-cassandra.md +22 -0
  111. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0004-use-redis-for-session-storage.md +22 -0
  112. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0005-use-react-for-dispatcher-dashboard.md +19 -0
  113. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0006-archive-delivered-shipments-to-object-storage.md +23 -0
  114. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0007-move-shipment-records-to-mongodb.md +23 -0
  115. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0008-store-vehicle-telemetry-in-timescaledb.md +28 -0
  116. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0009-stateless-sessions-with-signed-cookies.md +24 -0
  117. package/packs/solution-architect/skills/context-graph/evals/files/15/services/api/session.py +17 -0
  118. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/db.py +30 -0
  119. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/migrations.sql +3 -0
  120. package/packs/solution-architect/skills/context-graph/evals/files/15/services/telemetry/store.py +23 -0
  121. package/packs/solution-architect/skills/context-graph/evals/files/15/web/dashboard/App.jsx +3 -0
  122. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0001-record-architecture-decisions.md +11 -0
  123. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0002-rabbitmq-for-background-jobs.md +15 -0
  124. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0003-thumbnail-service.md +20 -0
  125. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0004-money-as-integer-minor-units.md +17 -0
  126. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0005-worker-retries.md +12 -0
  127. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0006-fx-amounts-with-four-decimals.md +18 -0
  128. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0007-feature-flags.md +16 -0
  129. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0008-retire-legacy-search.md +14 -0
  130. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/__init__.py +0 -0
  131. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/amount.py +9 -0
  132. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/flags.py +1 -0
  133. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/publish.py +0 -0
  134. package/packs/solution-architect/skills/context-graph/evals/files/2/services/media/resize.py +5 -0
  135. package/packs/solution-architect/skills/context-graph/evals/files/2/services/worker/consumer.py +0 -0
  136. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0001-how-we-write-rfcs.md +9 -0
  137. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0002-payments-service-boundary.md +16 -0
  138. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0003-webhook-retries-fixed-interval.md +19 -0
  139. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0004-webhook-idempotency-keys.md +16 -0
  140. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0005-notification-retries.md +16 -0
  141. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0006-webhook-retry-backoff.md +26 -0
  142. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0007-webhooks-on-the-job-queue.md +12 -0
  143. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/__init__.py +0 -0
  144. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/retry.py +4 -0
  145. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/__init__.py +0 -0
  146. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/__init__.py +0 -0
  147. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/retry.py +15 -0
  148. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/send.py +0 -0
  149. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0001-record-architecture-decisions.md +19 -0
  150. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0002-postgres-as-system-of-record.md +18 -0
  151. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0004-redis-locks-for-scheduler.md +19 -0
  152. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0007-remove-redis.md +27 -0
  153. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0009-money-as-integer-minor-units.md +19 -0
  154. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/onboarding.md +12 -0
  155. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/__init__.py +0 -0
  156. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/db/__init__.py +22 -0
  157. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/invoicing.py +9 -0
  158. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/money.py +10 -0
  159. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/__init__.py +0 -0
  160. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/lock.py +23 -0
  161. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/runner.py +17 -0
  162. package/packs/solution-architect/skills/context-graph/evals/files/5/lib/types/index.ts +13 -0
  163. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0001-service-layout.md +20 -0
  164. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0003-ingest-retry-policy.md +26 -0
  165. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0006-shared-retry-library.md +24 -0
  166. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0008-outbound-http-client.md +22 -0
  167. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/client.ts +15 -0
  168. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/retry.ts +12 -0
  169. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/client.ts +14 -0
  170. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/retry.ts +20 -0
  171. package/packs/solution-architect/skills/context-graph/evals/files/6/README.md +4 -0
  172. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0001-monorepo-layout.md +10 -0
  173. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0002-billing-on-postgres.md +13 -0
  174. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0004-ledger-sync-nightly-batch.md +9 -0
  175. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0003-invoice-ids.md +9 -0
  176. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0007-invoice-ids-ulid.md +11 -0
  177. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0009-billing-event-store.md +15 -0
  178. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0010-revenue-service.md +13 -0
  179. package/packs/solution-architect/skills/context-graph/evals/files/6/libs/money/ulid.py +8 -0
  180. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/events.py +10 -0
  181. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/store.py +10 -0
  182. package/packs/solution-architect/skills/context-graph/evals/files/6/services/invoicing/ids/generator.py +7 -0
  183. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/README.md +4 -0
  184. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/sync.py +3 -0
  185. package/packs/solution-architect/skills/context-graph/evals/files/7/README.md +4 -0
  186. package/packs/solution-architect/skills/context-graph/evals/files/7/db/queries/orders.sql +2 -0
  187. package/packs/solution-architect/skills/context-graph/evals/files/7/db/sharding/router.py +9 -0
  188. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-001-postgres-primary.md +8 -0
  189. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-002-kafka-event-bus.md +20 -0
  190. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-003-no-orm.md +9 -0
  191. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-006-tenant-sharding.md +9 -0
  192. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-011-orm-for-admin-console.md +11 -0
  193. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/fanout/router.py +4 -0
  194. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/consumer.py +5 -0
  195. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/topics.yaml +8 -0
  196. package/packs/solution-architect/skills/context-graph/evals/files/7/rfcs/0004-region-sharding.md +15 -0
  197. package/packs/solution-architect/skills/context-graph/evals/files/7/services/admin-console/models.py +11 -0
  198. package/packs/solution-architect/skills/context-graph/evals/files/7/services/orders/repo.py +9 -0
  199. package/packs/solution-architect/skills/context-graph/evals/files/8/README.md +11 -0
  200. package/packs/solution-architect/skills/context-graph/evals/files/8/api/ledger.proto +30 -0
  201. package/packs/solution-architect/skills/context-graph/evals/files/8/config/http.yaml +10 -0
  202. package/packs/solution-architect/skills/context-graph/evals/files/8/config/messaging.yaml +8 -0
  203. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0001-record-architecture-decisions.md +20 -0
  204. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0002-postgresql-for-ledger.md +22 -0
  205. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0003-rabbitmq-domain-events.md +22 -0
  206. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0004-integer-minor-units.md +32 -0
  207. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0005-provider-http-retries.md +26 -0
  208. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0006-openapi-generated-clients.md +20 -0
  209. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0007-kafka-domain-events.md +25 -0
  210. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0008-structured-logging.md +18 -0
  211. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/rfcs/RFC-012-idempotency-keys.md +19 -0
  212. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/idempotency.py +19 -0
  213. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/server.py +35 -0
  214. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/clients/provider.py +33 -0
  215. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0001_init.sql +14 -0
  216. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0008_idempotency_keys.sql +5 -0
  217. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0009_fx_entries.sql +4 -0
  218. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/events/publisher.py +28 -0
  219. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/logging.py +25 -0
  220. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/models/entry.py +16 -0
  221. package/packs/solution-architect/skills/context-graph/evals/files/9/.env.example +3 -0
  222. package/packs/solution-architect/skills/context-graph/evals/files/9/README.md +5 -0
  223. package/packs/solution-architect/skills/context-graph/evals/files/9/docker-compose.yml +18 -0
  224. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/001-session-storage.md +21 -0
  225. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/002-api-rate-limiting.md +32 -0
  226. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/003-jwt-sessions.md +29 -0
  227. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/004-catalog-cache.md +19 -0
  228. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/cache.ts +13 -0
  229. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/repository.ts +13 -0
  230. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/email.ts +3 -0
  231. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/export.ts +3 -0
  232. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/queue.ts +10 -0
  233. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/worker.ts +8 -0
  234. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/db.ts +10 -0
  235. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/redis.ts +8 -0
  236. package/packs/solution-architect/skills/context-graph/evals/files/9/src/middleware/rateLimit.ts +26 -0
  237. package/packs/solution-architect/skills/context-graph/evals/files/9/src/server.ts +17 -0
  238. package/packs/solution-architect/skills/context-graph/evals/files/9/src/session/store.ts +10 -0
  239. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0004-kafka-for-order-events.md +19 -0
  240. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0006-email-receipts.md +7 -0
  241. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0009-sqs-for-order-events.md +19 -0
  242. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/notifications/receipts.py +0 -0
  243. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/orders/publisher.py +0 -0
  244. package/packs/solution-architect/skills/context-graph/examples/order-events.md +63 -0
  245. package/packs/solution-architect/skills/context-graph/manifest.json +33 -0
  246. package/packs/solution-architect/skills/context-graph/reference.md +104 -0
  247. package/packs/solution-architect/skills/context-graph/scripts/context_graph.py +634 -0
  248. package/packs/solution-architect/skills/event-contract-draft/manifest.json +1 -1
  249. package/packs/solution-architect/skills/event-contract-draft/scripts/check_asyncapi.py +14 -2
  250. package/packs/sre-oncall/skills/cloud-cost-review/manifest.json +1 -1
  251. package/packs/sre-oncall/skills/cloud-cost-review/scripts/cost_summary.py +2 -0
  252. package/packs/trackers/skills/backlog-triage/manifest.json +1 -1
  253. package/packs/trackers/skills/backlog-triage/scripts/triage_backlog.py +4 -1
  254. package/packs/trackers/skills/team-status-report/manifest.json +1 -1
  255. package/packs/trackers/skills/team-status-report/scripts/status_counts.py +4 -1
package/catalogue.json CHANGED
@@ -42,6 +42,7 @@
42
42
  "agent-budget",
43
43
  "terraform-module",
44
44
  "mcp-pairing",
45
+ "context-graph",
45
46
  "event-contract-draft"
46
47
  ]
47
48
  },
@@ -270,6 +270,7 @@
270
270
  "tier": "standard",
271
271
  "rationale": "Reads a SKILL.md and synthesizes eval cases — requires understanding of skill intent but not heavy reasoning."
272
272
  },
273
+ "context-graph": {"tier": "standard", "rationale": "The decision graph and its consistency checks are computed by its script; the model quotes the governing record and writes the fixes."},
273
274
  "event-contract-draft": {
274
275
  "tier": "standard",
275
276
  "rationale": "Contract drafting against the AsyncAPI shape with fixed rules on ordering, delivery and versioning; mid tier is enough."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skilldrop-cli",
3
- "version": "0.16.44",
3
+ "version": "0.16.46",
4
4
  "description": "Portable AI-agent skills, measured against the agent without them. ADRs, PRDs, runbooks, decks and reviews, installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
5
5
  "author": {
6
6
  "name": "Sanjay Ananthanarayan",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md-to-html",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Turn a Markdown draft into one self-contained, print-friendly HTML file that survives being emailed or attached, with headings that have anchor links, tables, code, quotes, an optional table of contents, local images embedded, brand colours and fonts from a brand.json, Mermaid diagrams kept as text or drawn from a pinned CDN, and raw HTML escaped so nothing in the source runs. Use when the user wants Markdown \"as a web page\", \"as an HTML file I can send\", \"something people can open in a browser and print\", or says \"convert this to HTML\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -552,6 +552,9 @@ def build_toc(headings):
552
552
 
553
553
 
554
554
  def convert(src_text, base_dir, brand_path=None, toc=False, mermaid="none", allow_html=False):
555
+ # \x00 and \x01 mark the converter's own placeholders (code spans, line breaks); a source
556
+ # that contains them would collide with those markers, and neither belongs in a document.
557
+ src_text = src_text.replace("\x00", "").replace("\x01", "")
555
558
  ctx = Ctx(base_dir, allow_html, mermaid)
556
559
  brand = load_brand(brand_path, ctx)
557
560
  lines = src_text.replace("\r\n", "\n").replace("\r", "\n").split("\n")
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brand-kit",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Capture a brand once as a reusable brand.json — logo files (and an on-dark version), colour roles as hex codes, heading and body fonts, voice, imagery rules, a PowerPoint template, contact details and the legal footer — plus a one-page BRAND.md, with text contrast checked and every value traced to where it came from. Use when the user wants decks, flyers or documents in their branding, says \"use our brand\", \"here's our logo and colours\", \"set up our brand kit\", or hands over brand guidelines.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -35,7 +35,7 @@ def contrast(a, b):
35
35
  return (la + 0.05) / (lb + 0.05)
36
36
 
37
37
 
38
- def main(argv):
38
+ def _main(argv):
39
39
  if len(argv) != 1:
40
40
  print(__doc__)
41
41
  return 2
@@ -116,5 +116,15 @@ def main(argv):
116
116
  return 1 if fails else 0
117
117
 
118
118
 
119
+
120
+ def main(argv):
121
+ """Run, and turn an input that parses but has the wrong shape into one clear error."""
122
+ try:
123
+ return _main(argv)
124
+ except (KeyError, TypeError, AttributeError, IndexError, ValueError) as e:
125
+ print("error: couldn't read the input as a brand file (%s: %s). If it is one, this is a bug: "
126
+ "please report it with the file." % (type(e).__name__, e), file=sys.stderr)
127
+ return 2
128
+
119
129
  if __name__ == "__main__":
120
130
  sys.exit(main(sys.argv[1:]))
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "behaviour-equivalence",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Prove that a rewritten, migrated or refactored component behaves the same as the old one with a golden-master comparison — record inputs and outputs at a boundary (HTTP, function calls, batch files, DB writes, events) from production-shaped traffic and edge cases, run the old system twice to find its nondeterminism, normalise narrowly field by field, replay against the new one, triage every difference as defect, intended change (with a named approver) or missing normalisation, and give a verdict of EQUIVALENT, EQUIVALENT EXCEPT LISTED CHANGES, NOT EQUIVALENT or NOT PROVEN. Use when the user asks \"does the new one behave the same as the old one\", \"can we sign off the rewrite\", \"are these diffs just noise\", wants a golden-master, approval or shadow-traffic comparison, a parity check between old and new outputs, or says \"prove behaviour equivalence\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
@@ -495,7 +495,7 @@ def render(rep, max_diffs):
495
495
  return "\n".join(out) + "\n"
496
496
 
497
497
 
498
- def main(argv=None):
498
+ def _main(argv=None):
499
499
  ap = argparse.ArgumentParser(description="Golden-master diff of old vs new recorded outputs.")
500
500
  ap.add_argument("old", help="directory or JSONL file of the old system's outputs")
501
501
  ap.add_argument("new", help="directory or JSONL file of the new system's outputs")
@@ -522,5 +522,15 @@ def main(argv=None):
522
522
  return 0 if rep["verdict"] != "NOT EQUIVALENT" else 1
523
523
 
524
524
 
525
+
526
+ def main(argv=None):
527
+ """Run, and turn an input that parses but has the wrong shape into one clear error."""
528
+ try:
529
+ return _main(argv)
530
+ except (KeyError, TypeError, AttributeError, IndexError, ValueError) as e:
531
+ print("error: couldn't read the input as recordings and rules (%s: %s). If it is one, this is a bug: "
532
+ "please report it with the file." % (type(e).__name__, e), file=sys.stderr)
533
+ return 2
534
+
525
535
  if __name__ == "__main__":
526
536
  sys.exit(main())
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bundle-size-review",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Find what makes a JavaScript bundle heavy and what can safely come out, from the bundler's stats file (webpack stats.json, an esbuild metafile, or the rollup-plugin-visualizer raw-data JSON that Vite builds use) read together with the repo around it (package.json, .browserslistrc, the lockfile, the bundler config and the source files that import the heavy modules). Gives each entry's first-load JavaScript in the exact bytes the stats record, kept apart from lazy chunks; finds whole-library imports, CommonJS packages that can't be tree-shaken, packages bundled twice and polyfills the browser targets don't need; names the import chain that pulls each module in before suggesting a removal; and, given before and after stats, says what grew, why, whether it lands in the first load and which per-entry budget would have caught it. Use when the user says \"why is our bundle so big\", \"what can we cut from the bundle\", \"review this stats.json\", \"why is lodash or moment in our bundle\", \"the bundle grew in this PR\", or \"set a bundle size budget\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -500,6 +500,8 @@ def load(path):
500
500
  text = fh.read()
501
501
  except OSError as e:
502
502
  raise InputError("cannot read %s: %s" % (path, e))
503
+ except UnicodeDecodeError:
504
+ raise InputError("%s is not UTF-8 text; save it as UTF-8" % path)
503
505
  if not text.strip():
504
506
  raise InputError("%s is empty" % path)
505
507
  try:
@@ -1574,7 +1576,7 @@ def to_jsonable(o):
1574
1576
  raise TypeError(type(o))
1575
1577
 
1576
1578
 
1577
- def main(argv=None):
1579
+ def _main(argv=None):
1578
1580
  ap = argparse.ArgumentParser(description="Size a JS bundle from webpack stats, an esbuild metafile or rollup-plugin-visualizer raw data, and read the project files around it.")
1579
1581
  ap.add_argument("stats", nargs="?", help="stats file, or - for stdin")
1580
1582
  ap.add_argument("--compare", nargs=2, metavar=("BEFORE", "AFTER"), help="diff two stats files")
@@ -1629,5 +1631,15 @@ def main(argv=None):
1629
1631
  return 1 if over else 0
1630
1632
 
1631
1633
 
1634
+
1635
+ def main(argv=None):
1636
+ """Run, and turn an input that parses but has the wrong shape into one clear error."""
1637
+ try:
1638
+ return _main(argv)
1639
+ except (KeyError, TypeError, AttributeError, IndexError, ValueError) as e:
1640
+ print("error: couldn't read the input as webpack, esbuild or Vite stats (%s: %s). If it is one, this is a bug: "
1641
+ "please report it with the file." % (type(e).__name__, e), file=sys.stderr)
1642
+ return 2
1643
+
1632
1644
  if __name__ == "__main__":
1633
1645
  sys.exit(main())
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-performance-review",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Read a Lighthouse report or PageSpeed Insights result, with field data when there is any (CrUX, PSI loadingExperience or RUM p75), and say what makes the page slow for real users and what to fix first, ranked by how much each fix moves LCP, INP and CLS at the 75th percentile. Names the LCP element and which LCP phase dominates, the elements that shift and why, the long tasks and third parties by main-thread time, and treats estimated savings as lab estimates that overlap. Use when the user shares a Lighthouse JSON or PSI result and asks \"why is this page slow\", \"what should we fix first\", \"we score 92 but Search Console says LCP is poor\", \"did our change fix INP\", \"review this Lighthouse report\", or \"how do we pass Core Web Vitals\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -702,7 +702,7 @@ def cmp_md(c):
702
702
  return "\n".join(L)
703
703
 
704
704
 
705
- def main():
705
+ def _main():
706
706
  ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
707
707
  ap.add_argument("reports", nargs="+", help="Lighthouse JSON, PSI JSON or CrUX JSON path, or - for stdin (max 2)")
708
708
  ap.add_argument("--field", help="extra field data: a PSI response or CrUX API record JSON")
@@ -744,5 +744,15 @@ def main():
744
744
  print(text)
745
745
 
746
746
 
747
+
748
+ def main():
749
+ """Run, and turn an input that parses but has the wrong shape into one clear error."""
750
+ try:
751
+ return _main()
752
+ except (KeyError, TypeError, AttributeError, IndexError, ValueError) as e:
753
+ print("error: couldn't read the input as a Lighthouse, PageSpeed Insights or CrUX report (%s: %s). If it is one, this is a bug: "
754
+ "please report it with the file." % (type(e).__name__, e), file=sys.stderr)
755
+ return 2
756
+
747
757
  if __name__ == "__main__":
748
- main()
758
+ sys.exit(main())
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "risk-register",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Build or update an enterprise or project risk register — each risk written as cause, event and consequence, scored for likelihood and impact on a defined scale, inherent and residual ratings, a named owner, a treatment (avoid, reduce, transfer, accept), controls, a due date and a review trigger — with a heat map, the top risks that need a decision, and a stdlib script that validates the register CSV and flags overdue reviews. Use when the user wants a risk register, a risk log, a RAID log's risk section, a heat map, or says \"what are our top risks\", \"update the risk register\", \"score these risks\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -152,8 +152,16 @@ def main(argv=None):
152
152
  except (IOError, OSError) as exc:
153
153
  print("error: cannot read %s: %s" % (args.csv, exc), file=sys.stderr)
154
154
  return 2
155
+ except UnicodeDecodeError:
156
+ print("error: %s is not UTF-8 text; save it as UTF-8 (in Excel: CSV UTF-8)" % args.csv, file=sys.stderr)
157
+ return 2
155
158
 
156
- reader = csv.DictReader(io.StringIO(text))
159
+ try: # parse once up front, so a malformed file is one clear error, not a traceback mid-loop
160
+ list(csv.reader(io.StringIO(text, newline="")))
161
+ except csv.Error as exc:
162
+ print("error: %s is not a readable CSV: %s" % (args.csv, exc), file=sys.stderr)
163
+ return 2
164
+ reader = csv.DictReader(io.StringIO(text, newline=""))
157
165
  if not reader.fieldnames:
158
166
  print("error: %s has no header row" % args.csv, file=sys.stderr)
159
167
  return 2
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terraform-plan-review",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Review a terraform plan before apply, from the plan text or terraform show -json output. Flags every destroy and replace with the attribute forcing it, changes to stateful resources such as databases, buckets and volumes, IAM and security-group widening, drift nobody made in code, and changes outside the intended scope, then gives a SAFE TO APPLY, APPLY WITH CARE or DO NOT APPLY verdict with reasons. Use when the user pastes a plan, says \"review this terraform plan\", \"is this plan safe to apply\", \"why is terraform replacing my database\", or \"check the plan before I apply\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -338,7 +338,7 @@ def to_markdown(r):
338
338
  return "\n".join(lines) + "\n"
339
339
 
340
340
 
341
- def main():
341
+ def _main():
342
342
  ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
343
343
  ap.add_argument("plan", help="path to `terraform show -json` output, or - for stdin")
344
344
  ap.add_argument("--scope", action="append", default=[],
@@ -359,5 +359,15 @@ def main():
359
359
  sys.stdout.write(text)
360
360
 
361
361
 
362
+
363
+ def main():
364
+ """Run, and turn an input that parses but has the wrong shape into one clear error."""
365
+ try:
366
+ return _main()
367
+ except (KeyError, TypeError, AttributeError, IndexError, ValueError) as e:
368
+ print("error: couldn't read the input as a Terraform JSON plan (%s: %s). If it is one, this is a bug: "
369
+ "please report it with the file." % (type(e).__name__, e), file=sys.stderr)
370
+ return 2
371
+
362
372
  if __name__ == "__main__":
363
- main()
373
+ sys.exit(main())
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feedback-synthesis",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Turn raw customer feedback — interview notes, support tickets, NPS or CSAT verbatims, app-store reviews, sales-call notes — into ranked themes a product decision can rest on, each a problem statement rather than a feature request, counted by distinct people or accounts not mentions, with segments, severity kept separate from frequency, verbatim quotes with source IDs, what people value, where sources disagree, what the sample cannot tell, and the questions for the next interviews. A stdlib script computes the counts. Use when the user says \"what are customers telling us\", \"synthesise this feedback\", \"find the themes in these tickets / reviews / NPS comments\", \"affinity map these interview notes\", or \"what should we fix first based on feedback\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -75,6 +75,8 @@ def load(path: Path, person_col: str, ignore: set, segments_wanted: list):
75
75
  text = path.read_text(encoding="utf-8-sig")
76
76
  except OSError as e:
77
77
  die(f"cannot read {path}: {e}")
78
+ except UnicodeDecodeError:
79
+ die(f"{path} is not UTF-8 text; save it as UTF-8 (in Excel: CSV UTF-8)")
78
80
  reader = csv.DictReader(text.splitlines())
79
81
  if not reader.fieldnames:
80
82
  die(f"{path} has no header row")
@@ -334,7 +336,10 @@ def main(argv=None) -> int:
334
336
  a = ap.parse_args(argv)
335
337
 
336
338
  ignore = DEFAULT_IGNORE | {c.lower() for c in a.ignore}
337
- rows, segs, warnings = load(a.csv, a.person_col, ignore, a.segment)
339
+ try:
340
+ rows, segs, warnings = load(a.csv, a.person_col, ignore, a.segment)
341
+ except csv.Error as e: # e.g. a NUL byte, which Python before 3.11 rejects
342
+ die(f"{a.csv} is not a readable CSV: {e}")
338
343
  if not rows:
339
344
  die(f"{a.csv} has no feedback rows")
340
345
  label = a.person_label or ("person" if a.person_col == "person_id" else a.person_col.replace("_id", "").replace("_", " "))
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypothesis-comparison",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Compare rival explanations for an observation with analysis of competing hypotheses (ACH) — list the hypotheses and the evidence, build a consistency matrix (consistent / inconsistent / neutral), rank hypotheses by how little evidence contradicts them rather than how much supports them, name the diagnostic evidence and the linchpins, and say which next observation would tell the leaders apart. Use when the user asks \"why did X happen\", \"which explanation fits the evidence\", \"what's really causing this\", wants to stop arguing over a favourite theory, or says \"compare these hypotheses\", \"competing explanations\", \"ACH\".",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": {
@@ -33,6 +33,7 @@ Exit codes: 0 report written, 2 bad input.
33
33
 
34
34
  import argparse
35
35
  import csv
36
+ import io
36
37
  import sys
37
38
  from pathlib import Path
38
39
 
@@ -53,7 +54,11 @@ def load(path):
53
54
  p = Path(path)
54
55
  if not p.is_file():
55
56
  fail("file not found: " + str(path))
56
- with p.open(newline="", encoding="utf-8-sig") as f:
57
+ try:
58
+ text = p.read_text(encoding="utf-8-sig")
59
+ except UnicodeDecodeError:
60
+ fail("{} is not UTF-8 text; save it as UTF-8 (in Excel: CSV UTF-8)".format(path))
61
+ with io.StringIO(text, newline="") as f:
57
62
  reader = csv.DictReader(f)
58
63
  if not reader.fieldnames:
59
64
  fail("the CSV is empty")
@@ -123,7 +128,10 @@ def main():
123
128
  ap.add_argument("-o", "--output", help="write the report here instead of stdout")
124
129
  args = ap.parse_args()
125
130
 
126
- hyps, rows = load(args.matrix)
131
+ try:
132
+ hyps, rows = load(args.matrix)
133
+ except csv.Error as e: # e.g. a NUL byte, which Python before 3.11 rejects
134
+ fail("{} is not a readable CSV: {}".format(args.matrix, e))
127
135
  s = scores(hyps, rows)
128
136
  order = ranking(hyps, s)
129
137
  top = leaders(hyps, s)
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: context-graph
3
+ description: Map the decisions behind a codebase from its ADRs, RFCs and design records — each record's status and date, what supersedes or amends what, which records cite which, the files and folders each decision governs, and with git the commits that implemented it — then answer "why is it like this?" from the record and check the record is still true. Finds supersessions only one side records, current decisions pointing at code that is gone, two current decisions governing the same path, and references to records that don't exist. Use when the user asks "why do we use X", "which decisions govern this file or service", "is this ADR still current", "are our ADRs out of date", "what was decided before I change this", wants a map of the architecture decisions, or is onboarding onto a codebase's history.
4
+ ---
5
+
6
+ # context-graph
7
+
8
+ Answers "why is it like this?" from what the team actually decided and wrote down, and says
9
+ plainly when nothing was written down. It reads every decision record (ADRs, RFCs, design
10
+ decisions), builds the graph between them and the code they govern, and checks that graph against
11
+ the repository as it is today. Writing a new or corrected record is `adr-generator`. Explaining how
12
+ the code works now, with no decision history, is `codebase-tour`. Recovering the architecture from
13
+ the code itself is `reverse-architecture`.
14
+
15
+ ## How to respond
16
+
17
+ **Four rules come before the steps and outrank them:**
18
+
19
+ - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
20
+ - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
21
+ - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
22
+ - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
23
+ - **For this skill:** A rationale comes only from a record, quoted or cited by its id, and a record is only as true as the code: check the one that answers the question against the files it governs. When no record covers it, say "no recorded decision" and, at most, what the code shows, labelled as inferred. Never mention the script, the graph or any tool in the reply; say what the records and the code show.
24
+
25
+ 1. **Find the records and build the graph with the script.** Read numbers, statuses and links from its output, not by eye. It finds records in the usual folders (`docs/adr`, `docs/decisions`, `docs/rfcs`, `architecture/decisions`, …) or the ones you name, and exits 2 when there are none.
26
+ ```bash
27
+ # Claude Code
28
+ python3 "${CLAUDE_SKILL_DIR}/scripts/context_graph.py" --root .
29
+ python3 "${CLAUDE_SKILL_DIR}/scripts/context_graph.py" --root . --why services/orders/consumer.py
30
+ python3 "${CLAUDE_SKILL_DIR}/scripts/context_graph.py" --root . --record ADR-0004 --git
31
+ # Other IDEs (from the skill folder)
32
+ python3 scripts/context_graph.py --root <repo> --docs architecture/decisions --json -o graph.json --mermaid graph.mmd
33
+ ```
34
+ `--git` adds the commits whose messages mention each record. A path counts as governed when a record names it in backticks or links to it, and it exists. Without the script, do the same by hand and say the links were found by reading, not computed.
35
+
36
+ **The script's findings are leads, not answers.** Confirm each one by reading the records and the code before you report it, and drop the ones that don't hold. Two records "governing the same path" often don't clash at all: say so only when their decisions actually conflict, and quote both.
37
+
38
+ 2. **Answer "why" from the current record, and show the chain.** Say which decision governs the thing now, with its id, title, status and date, and the reason as the record states it. Then name what it replaced, if anything.
39
+ - ✅ *"Order events moved from Kafka to SQS in ADR-0009 (accepted 2026-02-10): 'one fewer system to run, and the volume fits SQS'. ADR-0004 chose Kafka in 2025 and is still marked Accepted, so anyone reading it alone gets the wrong answer."*
40
+ - ❌ *"You use Kafka for order events (ADR-0004), which gives you durability and ordering."* That reads the superseded record and adds a rationale that isn't in it.
41
+
42
+ 3. **Trust the newest record only when the chain agrees.** A record superseded by another is history, even when its own Status line still says Accepted. The script lists each such one-sided supersession as a problem. Say which record a reader should rely on and why.
43
+
44
+ 4. **Check the deciding record against the code.** Open the files it governs and check each thing the record requires (every "must", every named field, check, limit or setting), not only its headline. Confirm or contradict each with the code, quoting the line: ✅ *"`scheduler/jobs.py` line 18 still opens a database transaction per job, as ADR-0012 says."* Report drift as a finding with both sides: ✅ *"ADR-0015 promises 30 days of audit-log retention; `ops/logging.yaml` sets `retention_days: 14`."* When the record describes a phased change (a migration, a dual-write, a rollout), say which phase the code is in. While it's mid-rollout, the old decision still holds for the parts not yet moved: that is a missing cross-reference, not a contradiction.
45
+
46
+ 5. **For "can I remove or change X?", search the code for every use of X,** not only the records: imports, client constructors, config keys, environment variables and container definitions. A use that no record covers is still a dependency: list it as "in use, no recorded decision", with its file. The records tell you why; only the code tells you everything that would break.
47
+
48
+ 6. **Find the decisions that bear on it, not only the ones that name its path.** Read any record that amends, extends or narrows the governing one, and any that sets a rule for the same concern across the codebase (error handling, data access, logging, authentication), even when it names a different folder. A shared-library rule governs a change that creates a shared library. Before you call a related record unrelated, read it.
49
+
50
+ 7. **Report what is no longer true, worst first.** Problems before warnings:
51
+ - **Supersession recorded on one side only:** "ADR-0004 still says Accepted". Fix it by marking it "Superseded by ADR-0009".
52
+ - **A current decision pointing at code that is gone:** the record names a folder or file that no longer exists. When the script suggests where it moved (a renamed sibling), or a README says so, report it as moved, not gone, and give the path to update. Only a path with no successor is gone; then the decision is dead, so deprecate it.
53
+ - **A guide that still teaches a superseded decision:** an onboarding doc or a README that cites the old record, or describes its choice. Name the file and the line to change.
54
+ - **Two current decisions governing the same path, neither superseding nor amending the other:** a possible conflict. Read both, quote the clash if there is one, and recommend which one supersedes or amends the other.
55
+ - **A reference to a record that doesn't exist, a status that's missing or unrecognised, or a duplicate id.**
56
+
57
+ 8. **Give each fix as the exact edit.** The line to change in which record, such as changing `## Status` to `Superseded by ADR-0009`, linked to that record's file, or the new record that's needed and what it must decide. Don't rewrite records nobody asked about.
58
+
59
+ 9. **Say what the record can't tell.** Decisions made in chat or tickets and never written down, code that no record governs, and, without `--git`, whether anything was actually implemented. When a question has no record, say so, and suggest writing one only if the decision is still live.
60
+
61
+ 10. **Write the reply in this order, at the size asked for:**
62
+ - the answer, in two or three sentences, with the governing record's id;
63
+ - the chain or the problems, as a short list, each with its record id and the fix;
64
+ - what the records don't cover;
65
+ - "To confirm", only for inputs that are missing.
66
+
67
+ Answer each question someone asked, in their order. A length they set is a limit: "two lines" is two lines, with the decision and the one thing they must not miss. When they say "keep it short" or "don't need an essay", give a few lines per question, and at most one line on record hygiene that doesn't change the answer. Give a table when they ask for a map, a list or something to paste; otherwise none. No closing offer or summary line.
68
+
69
+ **Non-interactive runs** (subagent, CI, headless): with no records found, emit `BLOCKED: no decision records found; name the folder that holds the ADRs or RFCs`. Exit 1 from the full check means problems were found. Report them; never edit the records yourself.
70
+
71
+ ## Useful references in this skill
72
+
73
+ - [`reference.md`](reference.md): the record formats read (MADR, Nygard, RFC frontmatter), how status, supersession, amendment and governed paths are detected, every check and its fix, and the JSON shape
74
+ - [`scripts/context_graph.py`](scripts/context_graph.py): stdlib; builds the graph, checks it, answers `--why PATH` and `--record ID`; `--json`, `--mermaid`, `--git`; exits 1 on problems and 2 on bad input
75
+ - [`examples/order-events.md`](examples/order-events.md): worked example, a repo whose Kafka ADR was superseded on one side only and whose newer ADR names a folder that was deleted
76
+
77
+ ## Quality bar
78
+
79
+ - **The answer names the governing record by id, status and date**, and the rationale is quoted or closely paraphrased from that record. No reason is supplied that the record doesn't give.
80
+ - **A superseded record is never presented as current**, including one whose own Status line wasn't updated.
81
+ - **"No recorded decision" is said when it's true**, and any reading of the code is labelled as inferred.
82
+ - **Every problem names its record id and the exact fix.** Problems come before warnings.
83
+ - **Two current records on the same path are raised as a possible conflict**, not silently resolved by date.
84
+ - **The deciding record is checked against the code it governs, claim by claim,** with the line quoted, and drift is reported with both sides. A line number is given only when read from the file.
85
+ - **Every script finding in the reply has been confirmed by reading;** one that doesn't hold is dropped.
86
+ - **A removal or change question lists every use of the thing in the code,** recorded or not.
87
+ - **Related records are read before they're called unrelated:** amendments, and rules for the same concern elsewhere in the codebase.
88
+ - **A moved path is reported as moved, with its new location; only a path with no successor is "gone".**
89
+ - **A mid-rollout pair of records is a missing cross-reference, not a contradiction.**
90
+ - **The reply fits the size asked for (a stated limit is obeyed exactly), and never mentions a script, a graph or a tool.**
91
+ - **Statuses, links and governed paths come from the script's output**, or are marked as read by hand when it couldn't run.
92
+ - **No invented records, ids, dates, paths or commits.**
93
+
94
+ ## When to use this skill
95
+
96
+ - ✅ "Why do we use X?" or "Why is this service built this way?" in a repo with ADRs or RFCs
97
+ - ✅ "Which decisions govern this file, folder or service before I change it?"
98
+ - ✅ "Are our ADRs still current?" or "Find the stale or contradictory decisions"
99
+ - ✅ A map of a codebase's architecture decisions for onboarding or a review
100
+
101
+ ## When NOT to use this skill
102
+
103
+ - ❌ Writing a new ADR or fixing one: use `adr-generator`
104
+ - ❌ How the code works now, with no decision history: use `codebase-tour`
105
+ - ❌ Recovering the architecture from code with no records: use `reverse-architecture`
106
+ - ❌ A record of business or product decisions for stakeholders: use `decision-log`
107
+
108
+ ## Anti-patterns to avoid
109
+
110
+ - ❌ **Reading one ADR and stopping.** The record that answers the question may have been superseded by a later one that never touched the first file.
111
+ - ❌ **Trusting a Status line over the chain.** "Accepted" on a record another record supersedes means someone forgot to update it, not that it is still in force.
112
+ - ❌ **Supplying the reason.** "Kafka gives you ordering" is general knowledge, not the team's decision. If the record doesn't say why, say it doesn't.
113
+ - ❌ **Resolving a conflict by date alone.** Two current records on the same path need a person to decide which wins; the newer one isn't automatically right.
114
+ - ❌ **Listing every record.** Answer the question; the full table is for a map that was asked for.
115
+ - ❌ **Passing on a script warning unread.** "Both govern the same path" is a prompt to read both, not a conflict.
116
+ - ❌ **Answering "can I remove it?" from the records alone.** The uses nobody recorded are the ones that break.
117
+ - ❌ **Taking the record's word for it.** A decision the code no longer follows is the most useful thing to find; read the files.
118
+ - ❌ **"Gone" for a folder that was renamed.** Look for where it went before telling someone the decision is dead.
119
+ - ❌ **Telling the reader how you found it.** "The script shows" or "the graph says" means nothing to them; say what the records and the code say.
@@ -0,0 +1,11 @@
1
+ [
2
+ {"query": "Why do we use Kafka for order events? Is the ADR that chose it still the current decision?", "should_trigger": true},
3
+ {"query": "I'm about to refactor services/billing/invoice.py. Which architecture decisions govern it that I should read first?", "should_trigger": true},
4
+ {"query": "Our docs/adr folder has 40 records going back five years. Find the ones that are stale, superseded without being marked, or contradict each other", "should_trigger": true},
5
+ {"query": "Give me a map of our RFCs and ADRs: what supersedes what, and which folders each one covers, for onboarding the new hires", "should_trigger": true},
6
+ {"query": "Is ADR-0012 still true? I think the code it talks about was deleted last year", "should_trigger": true},
7
+ {"query": "We just decided to move our search from Postgres full-text to a hosted search engine. Write the ADR for it in MADR format", "should_trigger": false},
8
+ {"query": "I start on the checkout repo on Monday. How do I run it locally, run the tests, and where's the code for applying discount codes?", "should_trigger": false},
9
+ {"query": "There are no design docs for this monolith. Work out its architecture from the code and the docker-compose file and draw me a C4 diagram", "should_trigger": false},
10
+ {"query": "Here are the notes from this morning's pricing steering meeting. Pull out what was decided, who owns each action and when it's due", "should_trigger": false}
11
+ ]