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
@@ -0,0 +1,35 @@
1
+ from concurrent import futures
2
+
3
+ import grpc
4
+
5
+ from services.ledger.api import idempotency
6
+ from services.ledger.api.gen import ledger_pb2, ledger_pb2_grpc
7
+ from services.ledger.logging import get_logger
8
+
9
+ log = get_logger(__name__)
10
+
11
+
12
+ class LedgerServicer(ledger_pb2_grpc.LedgerServicer):
13
+ def __init__(self, db):
14
+ self.db = db
15
+
16
+ def PostEntry(self, request, context):
17
+ with self.db.transaction() as conn:
18
+ cached = idempotency.lookup(conn, request.idempotency_key)
19
+ if cached:
20
+ return ledger_pb2.PostEntryResponse(**cached)
21
+ entry_id = self.db.post_entry(conn, request)
22
+ idempotency.store(conn, request.idempotency_key, {"entry_id": entry_id})
23
+ return ledger_pb2.PostEntryResponse(entry_id=entry_id)
24
+
25
+ def GetBalance(self, request, context):
26
+ return self.db.balance(request.account_id)
27
+
28
+
29
+ def serve(db, port: int = 50051) -> None:
30
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=16))
31
+ ledger_pb2_grpc.add_LedgerServicer_to_server(LedgerServicer(db), server)
32
+ server.add_insecure_port(f"[::]:{port}")
33
+ server.start()
34
+ log.info("ledger gRPC server started")
35
+ server.wait_for_termination()
@@ -0,0 +1,33 @@
1
+ import random
2
+ import time
3
+
4
+ import httpx
5
+ import yaml
6
+
7
+ with open("config/http.yaml") as fh:
8
+ _cfg = yaml.safe_load(fh)["provider"]
9
+
10
+
11
+ def _sleep(attempt: int) -> None:
12
+ base = _cfg["backoff"]["base_ms"] / 1000
13
+ time.sleep(random.uniform(0, base * (2 ** attempt)))
14
+
15
+
16
+ def call(method: str, path: str, **kwargs) -> httpx.Response:
17
+ retries = _cfg["max_retries"] if method in _cfg["retry_methods"] else 0
18
+ for attempt in range(retries + 1):
19
+ try:
20
+ resp = httpx.request(
21
+ method,
22
+ _cfg["base_url"] + path,
23
+ timeout=_cfg["timeout_seconds"],
24
+ headers={"Authorization": f"Bearer {_cfg['api_key']}"},
25
+ **kwargs,
26
+ )
27
+ if resp.status_code not in (502, 503):
28
+ return resp
29
+ except httpx.TransportError:
30
+ if attempt == retries:
31
+ raise
32
+ _sleep(attempt)
33
+ return resp
@@ -0,0 +1,14 @@
1
+ CREATE TABLE accounts (
2
+ id UUID PRIMARY KEY,
3
+ currency CHAR(3) NOT NULL,
4
+ balance_minor BIGINT NOT NULL DEFAULT 0,
5
+ frozen BOOLEAN NOT NULL DEFAULT FALSE
6
+ );
7
+
8
+ CREATE TABLE entries (
9
+ id UUID PRIMARY KEY,
10
+ account_id UUID NOT NULL REFERENCES accounts(id),
11
+ amount_minor BIGINT NOT NULL,
12
+ currency CHAR(3) NOT NULL,
13
+ posted_at TIMESTAMPTZ NOT NULL DEFAULT now()
14
+ );
@@ -0,0 +1,5 @@
1
+ CREATE TABLE idempotency_keys (
2
+ key TEXT PRIMARY KEY,
3
+ response JSONB NOT NULL,
4
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
5
+ );
@@ -0,0 +1,4 @@
1
+ -- FX conversions: store the converted amount and the rate used.
2
+ ALTER TABLE entries ADD COLUMN fx_amount NUMERIC(18,4);
3
+ ALTER TABLE entries ADD COLUMN fx_currency CHAR(3);
4
+ ALTER TABLE entries ADD COLUMN fx_rate NUMERIC(18,8);
@@ -0,0 +1,28 @@
1
+ import json
2
+
3
+ import yaml
4
+ from confluent_kafka import Producer
5
+
6
+ from services.ledger.logging import get_logger
7
+
8
+ log = get_logger(__name__)
9
+
10
+ with open("config/messaging.yaml") as fh:
11
+ _cfg = yaml.safe_load(fh)
12
+
13
+ _producer = Producer({
14
+ "bootstrap.servers": ",".join(_cfg["bootstrap_servers"]),
15
+ "acks": _cfg["acks"],
16
+ })
17
+
18
+
19
+ def publish_entry_posted(entry) -> None:
20
+ payload = {
21
+ "type": "EntryPosted",
22
+ "entry_id": entry.id,
23
+ "account_id": entry.account_id,
24
+ "amount_minor": entry.amount_minor,
25
+ "currency": entry.currency,
26
+ }
27
+ _producer.produce(_cfg["topic"], key=entry.account_id, value=json.dumps(payload))
28
+ log.info("event published", extra={"account_id": entry.account_id})
@@ -0,0 +1,25 @@
1
+ import json
2
+ import logging
3
+ import sys
4
+ from datetime import datetime, timezone
5
+
6
+
7
+ class _JsonFormatter(logging.Formatter):
8
+ def format(self, record: logging.LogRecord) -> str:
9
+ return json.dumps({
10
+ "ts": datetime.now(timezone.utc).isoformat(),
11
+ "level": record.levelname,
12
+ "msg": record.getMessage(),
13
+ "trace_id": getattr(record, "trace_id", None),
14
+ "account_id": getattr(record, "account_id", None),
15
+ })
16
+
17
+
18
+ def get_logger(name: str) -> logging.Logger:
19
+ logger = logging.getLogger(name)
20
+ if not logger.handlers:
21
+ handler = logging.StreamHandler(sys.stdout)
22
+ handler.setFormatter(_JsonFormatter())
23
+ logger.addHandler(handler)
24
+ logger.setLevel(logging.INFO)
25
+ return logger
@@ -0,0 +1,16 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from decimal import Decimal
4
+ from typing import Optional
5
+
6
+
7
+ @dataclass(frozen=True)
8
+ class Entry:
9
+ id: str
10
+ account_id: str
11
+ amount_minor: int
12
+ currency: str
13
+ posted_at: datetime
14
+ fx_amount: Optional[Decimal] = None
15
+ fx_currency: Optional[str] = None
16
+ fx_rate: Optional[Decimal] = None
@@ -0,0 +1,3 @@
1
+ DATABASE_URL=postgres://tidepool:example-only@postgres:5432/tidepool
2
+ REDIS_URL=redis://redis:6379/0
3
+ SESSION_SECRET=replace-me
@@ -0,0 +1,5 @@
1
+ # tidepool-shop
2
+
3
+ Storefront API for Tidepool Outfitters. TypeScript, Express, PostgreSQL, Redis.
4
+
5
+ Run locally with `docker compose up`. Decision records live in `docs/decisions/`.
@@ -0,0 +1,18 @@
1
+ services:
2
+ app:
3
+ build: .
4
+ ports: ["3000:3000"]
5
+ env_file: .env
6
+ depends_on: [postgres, redis]
7
+ worker:
8
+ build: .
9
+ command: ["node", "dist/jobs/worker.js"]
10
+ env_file: .env
11
+ depends_on: [redis]
12
+ postgres:
13
+ image: postgres:16
14
+ environment:
15
+ POSTGRES_PASSWORD: example-only
16
+ redis:
17
+ image: redis:7
18
+ ports: ["6379:6379"]
@@ -0,0 +1,21 @@
1
+ # 001. Store user sessions in Redis
2
+
3
+ Date: 2023-05-09
4
+
5
+ ## Status
6
+
7
+ Superseded by [003](003-jwt-sessions.md)
8
+
9
+ ## Context
10
+
11
+ We run three app containers behind the load balancer. In-memory sessions log users out
12
+ whenever a request lands on a different container.
13
+
14
+ ## Decision
15
+
16
+ Sessions are stored in Redis via `connect-redis`, configured in `src/session/store.ts`,
17
+ with a 7-day TTL.
18
+
19
+ ## Consequences
20
+
21
+ Redis becomes a hard dependency of login.
@@ -0,0 +1,32 @@
1
+ ---
2
+ status: accepted
3
+ date: 2023-11-20
4
+ deciders: platform team
5
+ ---
6
+
7
+ # Rate-limit the public API with a shared token bucket
8
+
9
+ ## Context and Problem Statement
10
+
11
+ A partner's misconfigured sync job hit `/v1/products` 40 times a second for an hour. We need
12
+ per-API-key limits that hold across all app containers.
13
+
14
+ ## Considered Options
15
+
16
+ * Per-container in-memory limiter
17
+ * Token bucket in Redis, shared by all containers
18
+ * Limit at the CDN edge
19
+
20
+ ## Decision Outcome
21
+
22
+ Chosen option: "Token bucket in Redis", because limits must be global and the CDN plan we
23
+ are on cannot key on API key.
24
+
25
+ Implemented in `src/middleware/rateLimit.ts`: 600 requests per minute per API key, using a
26
+ Lua script so refill-and-take is atomic. Redis availability and failover are covered in
27
+ DR-007.
28
+
29
+ ### Consequences
30
+
31
+ * Good, because limits are exact across containers.
32
+ * Bad, because if Redis is down the limiter fails open.
@@ -0,0 +1,29 @@
1
+ # RFC 003 — Stateless JWT sessions
2
+
3
+ | Field | Value |
4
+ |---------|------------|
5
+ | State | Proposed |
6
+ | Author | r.achebe |
7
+ | Created | 2026-09-02 |
8
+ | Replaces | 001 |
9
+
10
+ ## Motivation
11
+
12
+ Mobile clients want a bearer token rather than a cookie, and we would like login to keep
13
+ working during a Redis restart.
14
+
15
+ ## Proposal
16
+
17
+ Issue a signed access token (15 minutes) and a refresh token (7 days). The app verifies the
18
+ signature locally; no session lookup per request.
19
+
20
+ ## Open questions
21
+
22
+ 1. **Revocation.** Logout and "sign out everywhere" need to invalidate tokens before they
23
+ expire. Current thinking: keep a denylist of revoked token ids in Redis with a TTL equal to
24
+ the token's remaining lifetime.
25
+ 2. Key rotation schedule — needs a decision before this is accepted.
26
+
27
+ ## Status of discussion
28
+
29
+ Not yet reviewed by the platform team.
@@ -0,0 +1,19 @@
1
+ # 004. Cache the product catalogue in process
2
+
3
+ - Status: Accepted
4
+ - Date: 2024-02-27
5
+
6
+ ## Context
7
+
8
+ Catalogue reads are about 70% of API traffic, and the catalogue changes a few times a day.
9
+
10
+ ## Decision
11
+
12
+ Each app container holds the catalogue in an in-process LRU cache (`lru-cache`, 5,000 items,
13
+ 10-minute TTL) in `src/catalog/cache.ts`. We deliberately do **not** put the catalogue in
14
+ Redis: it adds a network hop to the hottest path for data that is fine to be a few minutes
15
+ stale per container.
16
+
17
+ ## Consequences
18
+
19
+ Containers may briefly disagree after a catalogue update. That is acceptable.
@@ -0,0 +1,13 @@
1
+ import { redis } from "../lib/redis";
2
+ import { loadProduct, type Product } from "./repository";
3
+
4
+ const TTL_SECONDS = 600;
5
+
6
+ // Moved to Redis so all containers see catalogue updates at once (see #482).
7
+ export async function getProduct(id: string): Promise<Product | null> {
8
+ const hit = await redis.get(`catalog:${id}`);
9
+ if (hit) return JSON.parse(hit) as Product;
10
+ const product = await loadProduct(id);
11
+ if (product) await redis.set(`catalog:${id}`, JSON.stringify(product), { EX: TTL_SECONDS });
12
+ return product;
13
+ }
@@ -0,0 +1,13 @@
1
+ import { db } from "../lib/db";
2
+
3
+ export interface Product {
4
+ id: string;
5
+ name: string;
6
+ priceCents: number;
7
+ }
8
+
9
+ export async function loadProduct(id: string): Promise<Product | null> {
10
+ const rows = await db.query("SELECT id, name, price_cents FROM products WHERE id = $1", [id]);
11
+ if (rows.length === 0) return null;
12
+ return { id: rows[0].id, name: rows[0].name, priceCents: rows[0].price_cents };
13
+ }
@@ -0,0 +1,3 @@
1
+ export async function sendEmail(data: { orderId: string; to: string }): Promise<void> {
2
+ console.log(`would send order confirmation for ${data.orderId} to ${data.to}`);
3
+ }
@@ -0,0 +1,3 @@
1
+ export async function exportOrder(data: { orderId: string }): Promise<void> {
2
+ console.log(`would export order ${data.orderId} to the warehouse feed`);
3
+ }
@@ -0,0 +1,10 @@
1
+ import { Queue } from "bullmq";
2
+
3
+ const connection = { url: process.env.REDIS_URL };
4
+
5
+ export const emailQueue = new Queue("email", { connection });
6
+ export const orderExportQueue = new Queue("order-export", { connection });
7
+
8
+ export async function enqueueOrderConfirmation(orderId: string, to: string) {
9
+ await emailQueue.add("order-confirmation", { orderId, to }, { attempts: 5 });
10
+ }
@@ -0,0 +1,8 @@
1
+ import { Worker } from "bullmq";
2
+ import { sendEmail } from "./email";
3
+ import { exportOrder } from "./export";
4
+
5
+ const connection = { url: process.env.REDIS_URL };
6
+
7
+ new Worker("email", async (job) => sendEmail(job.data), { connection });
8
+ new Worker("order-export", async (job) => exportOrder(job.data), { connection });
@@ -0,0 +1,10 @@
1
+ import { Pool } from "pg";
2
+
3
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
4
+
5
+ export const db = {
6
+ async query(text: string, params: unknown[] = []) {
7
+ const result = await pool.query(text, params);
8
+ return result.rows;
9
+ },
10
+ };
@@ -0,0 +1,8 @@
1
+ import { createClient } from "redis";
2
+
3
+ export const redis = createClient({ url: process.env.REDIS_URL });
4
+ redis.on("error", (err) => console.error("redis error", err));
5
+
6
+ export async function connectRedis(): Promise<void> {
7
+ if (!redis.isOpen) await redis.connect();
8
+ }
@@ -0,0 +1,26 @@
1
+ import type { Request, Response, NextFunction } from "express";
2
+ import { redis } from "../lib/redis";
3
+
4
+ const LIMIT_PER_MINUTE = 600;
5
+
6
+ const TAKE_TOKEN = `
7
+ local tokens = tonumber(redis.call('GET', KEYS[1]) or ARGV[1])
8
+ if tokens <= 0 then return 0 end
9
+ redis.call('SET', KEYS[1], tokens - 1, 'EX', 60, 'KEEPTTL')
10
+ return 1
11
+ `;
12
+
13
+ export async function rateLimit(req: Request, res: Response, next: NextFunction) {
14
+ const apiKey = req.header("x-api-key");
15
+ if (!apiKey) return next();
16
+ try {
17
+ const ok = await redis.eval(TAKE_TOKEN, {
18
+ keys: [`rl:${apiKey}`],
19
+ arguments: [String(LIMIT_PER_MINUTE)],
20
+ });
21
+ if (ok === 0) return res.status(429).json({ error: "rate_limited" });
22
+ } catch {
23
+ // fail open, per decision 002
24
+ }
25
+ next();
26
+ }
@@ -0,0 +1,17 @@
1
+ import express from "express";
2
+ import { connectRedis } from "./lib/redis";
3
+ import { sessionMiddleware } from "./session/store";
4
+ import { rateLimit } from "./middleware/rateLimit";
5
+ import { getProduct } from "./catalog/cache";
6
+
7
+ const app = express();
8
+ app.use(sessionMiddleware);
9
+ app.use("/v1", rateLimit);
10
+
11
+ app.get("/v1/products/:id", async (req, res) => {
12
+ const product = await getProduct(req.params.id);
13
+ if (!product) return res.status(404).end();
14
+ res.json(product);
15
+ });
16
+
17
+ connectRedis().then(() => app.listen(3000));
@@ -0,0 +1,10 @@
1
+ import session from "express-session";
2
+ import RedisStore from "connect-redis";
3
+ import { redis } from "../lib/redis";
4
+
5
+ export const sessionMiddleware = session({
6
+ store: new RedisStore({ client: redis, prefix: "sess:", ttl: 60 * 60 * 24 * 7 }),
7
+ secret: process.env.SESSION_SECRET ?? "",
8
+ resave: false,
9
+ saveUninitialized: false,
10
+ });
@@ -0,0 +1,19 @@
1
+ # ADR-0004: Kafka for order events
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ Date: 2025-03-02
8
+
9
+ ## Context
10
+
11
+ Order events feed billing, notifications and the warehouse. We need replay for new consumers.
12
+
13
+ ## Decision
14
+
15
+ Order events are published to Kafka from `services/orders/`, one topic per event type.
16
+
17
+ ## Consequences
18
+
19
+ Replay works for a new consumer. We run a Kafka cluster.
@@ -0,0 +1,7 @@
1
+ ---
2
+ status: accepted
3
+ date: 2025-06-11
4
+ ---
5
+ # Email receipts from the notifications service
6
+
7
+ Receipts are sent by `services/notifications/` when it reads an OrderPlaced event (see ADR-0004).
@@ -0,0 +1,19 @@
1
+ ---
2
+ status: accepted
3
+ date: 2026-02-10
4
+ ---
5
+ # Order events on SQS
6
+
7
+ ## Context
8
+
9
+ Only two consumers ever replayed, and the Kafka cluster is the team's largest on-call load.
10
+
11
+ ## Decision
12
+
13
+ Supersedes ADR-0004. Order events move to SQS queues, one per consumer, published from
14
+ `services/orders/`. The bridge in `services/kafka-bridge/` is removed once billing has moved.
15
+
16
+ ## Consequences
17
+
18
+ One fewer system to run, and the volume fits SQS. Replay for a new consumer now means a
19
+ backfill from the orders table.
@@ -0,0 +1,63 @@
1
+ # Worked example: why do order events go through Kafka?
2
+
3
+ A made-up repository, in [`inputs/order-events/`](inputs/order-events/), with three ADRs:
4
+ - **ADR-0004** chose Kafka for order events in 2025.
5
+ - **ADR-0006** has receipts sent when the notifications service reads an OrderPlaced event, and
6
+ cites ADR-0004.
7
+ - **ADR-0009** moved order events to SQS in 2026, and says it supersedes ADR-0004. Nobody updated
8
+ ADR-0004's Status line, and ADR-0009 names a bridge folder that has since been deleted.
9
+
10
+ ## The request
11
+
12
+ > I'm changing `services/orders/publisher.py`. Why do we publish order events to Kafka, and is
13
+ > that still the plan?
14
+
15
+ ## Script runs
16
+
17
+ ```bash
18
+ python3 scripts/context_graph.py --root examples/inputs/order-events --why services/orders/publisher.py
19
+ python3 scripts/context_graph.py --root examples/inputs/order-events
20
+ ```
21
+
22
+ The `--why` output:
23
+
24
+ ```text
25
+ # Decisions governing services/orders/publisher.py
26
+
27
+ - **ADR-0009 Order events on SQS** (accepted, current, 2026-02-10), via `services/orders/`: docs/adr/0009-sqs-for-order-events.md
28
+ - **ADR-0004 Kafka for order events** (marked accepted, but superseded by ADR-0009, 2025-03-02), via `services/orders/`: docs/adr/0004-kafka-for-order-events.md
29
+ ```
30
+
31
+ The full check, which exits 1 because it found problems:
32
+
33
+ ```text
34
+ ## Problems (2)
35
+
36
+ - ADR-0004 is still marked Accepted, but ADR-0009 supersedes it: mark it 'Superseded by ADR-0009'
37
+ - ADR-0009 is accepted but points at code that is gone: services/kafka-bridge
38
+
39
+ ## Warnings (1)
40
+
41
+ - ADR-0006 is current but cites ADR-0004, which ADR-0009 supersedes: check it still holds
42
+ ```
43
+
44
+ ## The reply
45
+
46
+ It isn't the plan any more. ADR-0009 (accepted 2026-02-10) moved order events from Kafka to SQS
47
+ queues, one per consumer, published from `services/orders/`. Its reasons: "only two consumers
48
+ ever replayed, and the Kafka cluster is the team's largest on-call load". It replaces ADR-0004,
49
+ which chose Kafka in 2025. ADR-0004's own Status line still says Accepted, so anyone reading it on
50
+ its own gets the wrong answer.
51
+
52
+ Before you change the publisher:
53
+
54
+ 1. **ADR-0004 needs its status fixed.** Change `## Status` to `Superseded by ADR-0009`, linked
55
+ to `0009-sqs-for-order-events.md`.
56
+ 2. **ADR-0009 names `services/kafka-bridge/`, which no longer exists.** If billing has moved, add a
57
+ line saying the bridge was removed. If it hasn't, find where the bridge went.
58
+ 3. **ADR-0006 (receipts) still cites ADR-0004.** It has the notifications service read OrderPlaced
59
+ events, which now come from an SQS queue. Check that the receipts consumer has its queue before
60
+ you change what the publisher sends.
61
+
62
+ What the records don't say: when billing moved off Kafka, and whether replay for a new consumer
63
+ (now a backfill from the orders table, per ADR-0009) has been tested.
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "context-graph",
3
+ "version": "0.1.0",
4
+ "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.",
5
+ "entrypoint": "SKILL.md",
6
+ "deps": { "npm": [], "pip": [] },
7
+ "env": { "required": [], "optional": [] },
8
+ "related": [
9
+ "adr-generator",
10
+ "codebase-tour",
11
+ "reverse-architecture",
12
+ "decision-log"
13
+ ],
14
+ "handoff": [
15
+ {
16
+ "to": "adr-generator",
17
+ "when": "a decision is live but unrecorded, or a record needs superseding, deprecating or correcting",
18
+ "purpose": "Write the new or corrected record, with the supersession link the graph found missing.",
19
+ "fallback": "If adr-generator is absent, give the record's title, status line, the context in two sentences, the decision and its consequences, and the exact Superseded by line for the old record."
20
+ }
21
+ ],
22
+ "tags": ["architecture", "adr", "decision-records", "onboarding", "documentation"],
23
+ "permissions": {
24
+ "network": [],
25
+ "commands": ["git"],
26
+ "files": "named-paths",
27
+ "notes": "context_graph.py reads the decision-record folders under --root and checks whether the paths they name exist. With --git it runs `git log` read-only. It writes only to the -o and --mermaid paths."
28
+ },
29
+ "model": {
30
+ "tier": "standard",
31
+ "rationale": "The graph and its checks are computed by the script; the model reads records, quotes the rationale and writes the fixes."
32
+ }
33
+ }