declapract-typescript-ehmpathy 0.49.14 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/dist/.test/assets/cicd-common/declarations/declapract.declare.yml +8 -0
  2. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.declapract.integration.test.ts +597 -0
  3. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.test/assets/repo-with-unpinned-workflow/.github/workflows/.test.yml +19 -0
  4. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.test/assets/repo-with-unpinned-workflow/.github/workflows/consumer-owned.yml +21 -0
  5. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.test/assets/repo-with-unpinned-workflow/.github/workflows/review.yml +26 -0
  6. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.test/assets/repo-with-unpinned-workflow/declapract.use.yml +6 -0
  7. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/.test/assets/repo-with-unpinned-workflow/package.json +4 -0
  8. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/__snapshots__/.declapract.integration.test.ts.snap +604 -0
  9. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/__snapshots__/declastruct-insync-grep.declapract.integration.test.ts.snap +3 -0
  10. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/__snapshots__/report-slow-tests.play.declapract.integration.test.ts.snap +28 -0
  11. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/has-changelog-file/changelog.md.declapract.ts +11 -0
  12. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-names/.github/workflows/ci-on-commit.yml.declapract.ts +3 -0
  13. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-names/.github/workflows/ci_on_commit.yml.declapract.ts +3 -0
  14. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-names/.github/workflows/pr-release-on-main.yml.declapract.ts +3 -0
  15. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-names/.github/workflows/test-on-commit.yml.declapract.ts +3 -0
  16. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-names/.github/workflows/test_on_commit.yml.declapract.ts +3 -0
  17. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-use-apikeys/.agent/repo=.this/role=any/skills/use.apikeys.json.declapract.ts +7 -0
  18. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/bad-practices/old-use-apikeys/.agent/repo=.this/role=any/skills/use.apikeys.sh.declapract.ts +7 -0
  19. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.declapract.readme.md +8 -0
  20. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/actions/please-release/action.yml +469 -0
  21. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/actions/test-shards-setup/action.yml +68 -0
  22. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/.declastruct.yml +218 -0
  23. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/.install.yml +56 -0
  24. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/.test.yml +434 -0
  25. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/.test.yml.declapract.ts +26 -0
  26. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/release.yml +32 -0
  27. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/report-slow-tests.sh +65 -0
  28. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/review.yml +26 -0
  29. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/test.yml +25 -0
  30. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/best-practice/.github/workflows/test.yml.declapract.ts +15 -0
  31. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/declastruct-insync-grep.declapract.integration.test.ts +49 -0
  32. package/dist/.test/assets/cicd-common/declarations/practices/cicd-common/report-slow-tests.play.declapract.integration.test.ts +161 -0
  33. package/dist/.test/assets/cicd-common/declarations/useCases.yml +11 -0
  34. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/declapract.use.yml +4 -0
  35. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/package.json +17 -0
  36. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/left-pad@1.3.0.patch +6 -0
  37. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/pg-pool@3.14.0.patch +12 -0
  38. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/__snapshots__/pg-pool-patch.declapract.integration.test.ts.snap +147 -0
  39. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/best-practice/.declapract.readme.md +29 -0
  40. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/best-practice/.gitattributes.declapract.ts +64 -0
  41. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/best-practice/package.json +5 -0
  42. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/best-practice/patches/pg-pool.patch +21 -0
  43. package/dist/.test/assets/cicd-service/declarations/practices/persist-with-rds/pg-pool-patch.declapract.integration.test.ts +884 -0
  44. package/dist/.test/assets/expo-fullusecase/declarations/practices/cicd-common/.declapract.integration.test.ts +15 -21
  45. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/.declapract.integration.test.ts +2 -2
  46. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/.gitattributes.declapract.integration.test.ts +34 -19
  47. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/.test/assets/repo-with-legacy-gitattributes/declapract.use.yml +3 -3
  48. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/__snapshots__/.gitattributes.declapract.integration.test.ts.snap +4 -4
  49. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/best-practice/.declapract.readme.md +37 -0
  50. package/dist/.test/assets/expo-fullusecase/declarations/practices/git/best-practice/.gitattributes.declapract.ts +42 -63
  51. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/declapract.use.yml +4 -0
  52. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/package.json +15 -0
  53. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy.patch +6 -0
  54. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy@1.39.1.patch +6 -0
  55. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/type-fns@1.21.3.patch +6 -0
  56. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/pnpm-lock.yaml +19 -0
  57. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/__snapshots__/stale-patched-dependency.declapract.integration.test.ts.snap +39 -0
  58. package/dist/.test/assets/expo-fullusecase/declarations/practices/pnpm/stale-patched-dependency.declapract.integration.test.ts +53 -0
  59. package/dist/.test/assets/expo-fullusecase/declarations/practices/rhachet/best-practice/.declapract.readme.md +8 -0
  60. package/dist/.test/assets/expo-fullusecase/declarations/practices/rhachet/best-practice/.gitattributes.declapract.ts +65 -0
  61. package/dist/.test/assets/expo-fullusecase/declarations/practices/tests-any/best-practice/.declapract.readme.md +7 -0
  62. package/dist/.test/assets/expo-fullusecase/declarations/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  63. package/dist/.test/assets/expo-migration/declarations/practices/git/.declapract.integration.test.ts +2 -2
  64. package/dist/.test/assets/expo-migration/declarations/practices/git/.gitattributes.declapract.integration.test.ts +34 -19
  65. package/dist/.test/assets/expo-migration/declarations/practices/git/.test/assets/repo-with-legacy-gitattributes/declapract.use.yml +3 -3
  66. package/dist/.test/assets/expo-migration/declarations/practices/git/__snapshots__/.gitattributes.declapract.integration.test.ts.snap +4 -4
  67. package/dist/.test/assets/expo-migration/declarations/practices/git/best-practice/.declapract.readme.md +37 -0
  68. package/dist/.test/assets/expo-migration/declarations/practices/git/best-practice/.gitattributes.declapract.ts +42 -63
  69. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/declapract.use.yml +4 -0
  70. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/package.json +15 -0
  71. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy.patch +6 -0
  72. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy@1.39.1.patch +6 -0
  73. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/type-fns@1.21.3.patch +6 -0
  74. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/pnpm-lock.yaml +19 -0
  75. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/__snapshots__/stale-patched-dependency.declapract.integration.test.ts.snap +39 -0
  76. package/dist/.test/assets/expo-migration/declarations/practices/pnpm/stale-patched-dependency.declapract.integration.test.ts +53 -0
  77. package/dist/.test/assets/expo-migration/declarations/practices/rhachet/best-practice/.declapract.readme.md +8 -0
  78. package/dist/.test/assets/expo-migration/declarations/practices/rhachet/best-practice/.gitattributes.declapract.ts +65 -0
  79. package/dist/.test/assets/expo-migration/declarations/practices/tests-any/best-practice/.declapract.readme.md +7 -0
  80. package/dist/.test/assets/expo-migration/declarations/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  81. package/dist/.test/assets/expo-toolchain/declarations/practices/tests-any/best-practice/.declapract.readme.md +7 -0
  82. package/dist/.test/assets/expo-toolchain/declarations/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  83. package/dist/.test/assets/git/declarations/declapract.declare.yml +8 -0
  84. package/dist/.test/assets/git/declarations/practices/git/.declapract.integration.test.ts +1001 -0
  85. package/dist/.test/assets/git/declarations/practices/git/.gitattributes.declapract.integration.test.ts +120 -0
  86. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-with-legacy-gitattributes/.gitattributes +6 -0
  87. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-with-legacy-gitattributes/declapract.use.yml +7 -0
  88. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-with-legacy-gitattributes/package.json +4 -0
  89. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-with-rhachet-only/declapract.use.yml +6 -0
  90. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-with-rhachet-only/package.json +4 -0
  91. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-without-cache-ignores/declapract.use.yml +9 -0
  92. package/dist/.test/assets/git/declarations/practices/git/.test/assets/repo-without-cache-ignores/package.json +4 -0
  93. package/dist/.test/assets/git/declarations/practices/git/__snapshots__/.declapract.integration.test.ts.snap +55 -0
  94. package/dist/.test/assets/git/declarations/practices/git/__snapshots__/.gitattributes.declapract.integration.test.ts.snap +24 -0
  95. package/dist/.test/assets/git/declarations/practices/git/best-practice/.declapract.readme.md +60 -0
  96. package/dist/.test/assets/git/declarations/practices/git/best-practice/.gitattributes.declapract.ts +77 -0
  97. package/dist/.test/assets/git/declarations/practices/git/best-practice/.gitignore.declapract.ts +100 -0
  98. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/.declapract.integration.test.ts +181 -0
  99. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/.test/assets/demo-repo-with-dynamodb/declapract.declare.yml +4 -0
  100. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/.test/assets/demo-repo-with-dynamodb/declapract.use.yml +11 -0
  101. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/.test/assets/demo-repo-with-dynamodb/package.json +1 -0
  102. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/.test/assets/demo-repo-with-dynamodb/useCases.yml +8 -0
  103. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/__snapshots__/.declapract.integration.test.ts.snap +234 -0
  104. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/best-practice/.gitattributes.declapract.ts +56 -0
  105. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/best-practice/codegen.dynamodb.dao.ts +16 -0
  106. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/best-practice/package.json +16 -0
  107. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/best-practice/package.json.declapract.ts +3 -0
  108. package/dist/.test/assets/git/declarations/practices/persist-with-dynamodb/best-practice/provision/docker/integration-test-db/docker-compose.yml +9 -0
  109. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.declapract.integration.test.ts +237 -0
  110. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.extensions.sql.declapract.integration.test.ts +159 -0
  111. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-config-schema/declapract.use.yml +20 -0
  112. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-config-schema/declarations/declapract.declare.yml +6 -0
  113. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-config-schema/package.json +4 -0
  114. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-on-a-prior-major/codegen.sql.dao.yml +20 -0
  115. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-on-a-prior-major/declapract.declare.yml +4 -0
  116. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-on-a-prior-major/declapract.use.yml +19 -0
  117. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-on-a-prior-major/package.json +4 -0
  118. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-on-a-prior-major/provision/docker/testdb/build-image.dockerfile +6 -0
  119. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-custom-extensions/declapract.declare.yml +4 -0
  120. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-custom-extensions/declapract.use.yml +21 -0
  121. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-custom-extensions/package.json +4 -0
  122. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-custom-extensions/provision/schema/sql/init/.extensions.sql +9 -0
  123. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-dev-config/config/dev.json +18 -0
  124. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-dev-config/declapract.declare.yml +4 -0
  125. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-dev-config/declapract.use.yml +18 -0
  126. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/demo-repo-with-dev-config/package.json +4 -0
  127. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/declapract.use.yml +4 -0
  128. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/package.json +17 -0
  129. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/left-pad@1.3.0.patch +6 -0
  130. package/dist/.test/assets/git/declarations/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/pg-pool@3.14.0.patch +12 -0
  131. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/.declapract.integration.test.ts.snap +45 -0
  132. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/.extensions.sql.declapract.integration.test.ts.snap +77 -0
  133. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/config-validates-schema.declapract.integration.test.ts.snap +500 -0
  134. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/database-wrappers-typecheck.declapract.integration.test.ts.snap +10 -0
  135. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/deploy-database-gerunds.declapract.integration.test.ts.snap +102 -0
  136. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/engine-upgrade.declapract.integration.test.ts.snap +151 -0
  137. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/pg-pool-patch.declapract.integration.test.ts.snap +147 -0
  138. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/provision-testdb-access.declapract.integration.test.ts.snap +3 -0
  139. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/ssm-param-names.declapract.integration.test.ts.snap +9 -0
  140. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/testdb-preflight-failloud.declapract.integration.test.ts.snap +30 -0
  141. package/dist/.test/assets/git/declarations/practices/persist-with-rds/__snapshots__/with-connection-in-input.declapract.integration.test.ts.snap +57 -0
  142. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.declapract.integration.test.ts +71 -0
  143. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.declapract.readme.md +6 -0
  144. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.test/assets/demo-repo-with-legacy-change-id/declapract.declare.yml +4 -0
  145. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.test/assets/demo-repo-with-legacy-change-id/declapract.use.yml +19 -0
  146. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.test/assets/demo-repo-with-legacy-change-id/package.json +4 -0
  147. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/.test/assets/demo-repo-with-legacy-change-id/provision/schema/sql/init.yml +15 -0
  148. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/__snapshots__/.declapract.integration.test.ts.snap +39 -0
  149. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/legacy-change-id/provision/schema/<star><star>/<star>.yml.declapract.ts +68 -0
  150. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/.declapract.readme.md +5 -0
  151. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/database.sql.declapract.ts +3 -0
  152. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/extensions.sql.declapract.ts +13 -0
  153. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/schema.sql.declapract.ts +3 -0
  154. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/user.cicd.sql.declapract.ts +3 -0
  155. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/non-prefixed-manual-init-sqls/provision/schema/sql/init/user.datalakedb.sql.declapract.ts +3 -0
  156. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-config-file-names/codegen.sql.yml.declapract.ts +3 -0
  157. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-dev-config-location/config/dev.json.declapract.ts +23 -0
  158. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.declapract.integration.test.ts +221 -0
  159. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.declapract.readme.md +11 -0
  160. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/declapract.declare.yml +4 -0
  161. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/declapract.use.yml +19 -0
  162. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/package.json +4 -0
  163. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/src/access/daos/daoSurfer.ts +15 -0
  164. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/src/domain.operations/getSurfLesson.ts +14 -0
  165. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/src/utils/database/getDatabaseConnection.integration.test.ts +10 -0
  166. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/demo-repo-with-old-get-database-connection/src/utils/database/getDatabaseConnection.ts +68 -0
  167. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.3a193e5.ts +65 -0
  168. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.66284e3.ts +30 -0
  169. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.68cf8ba.ts +90 -0
  170. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.9e1bdc4.ts +65 -0
  171. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.c6cef7e.ts +68 -0
  172. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.c8eb35b.ts +90 -0
  173. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.d1e8cd7.ts +31 -0
  174. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.e0c53d8.ts +90 -0
  175. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.eab15c0.ts +89 -0
  176. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.ef25ae0.ts +32 -0
  177. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/.test/assets/old-templates/getDatabaseConnection.integration.test.66284e3.ts +10 -0
  178. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/__snapshots__/.declapract.integration.test.ts.snap +75 -0
  179. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/src/<star><star>/<star>.ts.declapract.ts +33 -0
  180. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/src/utils/database/getDatabaseConnection.integration.test.ts.declapract.ts +43 -0
  181. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-get-database-connection/src/utils/database/getDatabaseConnection.ts.declapract.ts +51 -0
  182. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-dir/.declapract.readme.md +1 -0
  183. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-dir/provision/docker/integration_test_db/<star><star>/<star>.declapract.ts +15 -0
  184. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-hyphen-dir/.declapract.readme.md +1 -0
  185. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-hyphen-dir/provision/docker/integration-test-db/<star><star>/<star>.declapract.ts +15 -0
  186. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/.declapract.readme.md +1 -0
  187. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/package.json +8 -0
  188. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-integration-test-db-paths/package.json.declapract.ts +10 -0
  189. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-packagejson-script-names/package.json +9 -0
  190. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-packagejson-script-names/package.json.declapract.ts +22 -0
  191. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/old-param-placeholder/config/<star>.json.declapract.ts +14 -0
  192. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.declapract.integration.test.ts +86 -0
  193. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.declapract.readme.md +9 -0
  194. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.test/assets/demo-repo-with-plaintext-pg-client/declapract.declare.yml +4 -0
  195. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.test/assets/demo-repo-with-plaintext-pg-client/declapract.use.yml +19 -0
  196. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.test/assets/demo-repo-with-plaintext-pg-client/package.json +4 -0
  197. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.test/assets/demo-repo-with-plaintext-pg-client/src/access/sdks/sdkWaveArchive.ts +7 -0
  198. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/.test/assets/demo-repo-with-plaintext-pg-client/src/utils/database/getSurfReportConnection.ts +19 -0
  199. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/__snapshots__/.declapract.integration.test.ts.snap +72 -0
  200. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/pg-client-without-ssl/src/<star><star>/<star>.ts.declapract.ts +32 -0
  201. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/schema-entities-dir/.declapract.readme.md +1 -0
  202. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/schema-entities-dir/provision/schema/entities/<star>.ts.declapract.ts +12 -0
  203. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/schema-entities-dir/provision/schema/sql/entities.yml.declapract.ts +13 -0
  204. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/.declapract.integration.test.ts +95 -0
  205. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/.test/assets/demo-repo-with-terraform-ssm/declapract.declare.yml +4 -0
  206. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/.test/assets/demo-repo-with-terraform-ssm/declapract.use.yml +18 -0
  207. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/.test/assets/demo-repo-with-terraform-ssm/package.json +4 -0
  208. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/.test/assets/demo-repo-with-terraform-ssm/provision/aws/product/parameter-store.tf +32 -0
  209. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/__snapshots__/.declapract.integration.test.ts.snap +60 -0
  210. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/terraform-parameters/provision/aws/product/parameter-store.tf.declapract.ts +94 -0
  211. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/.declapract.readme.md +10 -0
  212. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/.test/assets/demo-repo-with-connection-in-input/declapract.use.yml +2 -0
  213. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/.test/assets/demo-repo-with-connection-in-input/package.json +4 -0
  214. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/.test/assets/demo-repo-with-connection-in-input/src/domain.operations/findSurferById.ts +9 -0
  215. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/.test/assets/demo-repo-with-connection-in-input/src/utils/database/withDatabaseConnection.ts +10 -0
  216. package/dist/.test/assets/git/declarations/practices/persist-with-rds/bad-practices/with-connection-in-input/src/<star><star>/<star>.ts.declapract.ts +55 -0
  217. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/.declapract.readme.md +114 -0
  218. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/.gitattributes.declapract.ts +64 -0
  219. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/codegen.sql.dao.yml +18 -0
  220. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/codegen.sql.dao.yml.declapract.ts +35 -0
  221. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/codegen.sql.schema.yml +6 -0
  222. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/codegen.sql.types.yml +16 -0
  223. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/prep.json +40 -0
  224. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/prep.json.declapract.ts +11 -0
  225. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/prod.json +40 -0
  226. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/prod.json.declapract.ts +11 -0
  227. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/test.json +37 -0
  228. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/config/test.json.declapract.ts +11 -0
  229. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/package.json +36 -0
  230. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/package.json.declapract.ts +3 -0
  231. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/patches/pg-pool.patch +21 -0
  232. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/aws/readme.md +113 -0
  233. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/aws/resources.parameters.ts +60 -0
  234. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/aws/resources.ts +30 -0
  235. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/build-image.dockerfile +7 -0
  236. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/build-image.dockerfile.declapract.ts +37 -0
  237. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/check-engine-skew.integration.test.ts +115 -0
  238. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/check-engine-skew.sh +165 -0
  239. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/compose.sh +43 -0
  240. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/docker-compose.yml +19 -0
  241. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/init/.gitignore +3 -0
  242. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/init/readme.md +3 -0
  243. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/docker/testdb/wait-for-postgres.sh +25 -0
  244. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/connection.config.js +36 -0
  245. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/control.yml +7 -0
  246. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/deploy.database.sh +97 -0
  247. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.database.sql +10 -0
  248. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.extensions.sql +16 -0
  249. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.extensions.sql.declapract.ts +46 -0
  250. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.schema.sql +11 -0
  251. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.cicd.sql +14 -0
  252. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/.user.datalakedb.sql +12 -0
  253. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/default_transaction_isolation.sql +6 -0
  254. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init/user.service.sql +16 -0
  255. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init.yml +9 -0
  256. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/provision/schema/sql/init.yml.declapract.ts +3 -0
  257. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/.test/assets/database/getTestdbIdentity.ts +52 -0
  258. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/.test/assets/database/getTestdbPort.ts +17 -0
  259. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/config/config.schema.ts +77 -0
  260. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/asDatabaseClientSsl.test.ts +82 -0
  261. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/asDatabaseClientSsl.ts +52 -0
  262. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/databaseClientTimeouts.ts +14 -0
  263. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/getOneDatabaseConnection.integration.test.ts +10 -0
  264. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/getOneDatabaseConnection.ts +119 -0
  265. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/getOneDatabasePort.ts +30 -0
  266. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/rdsCaBundleUsEast1.test.ts +51 -0
  267. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/rdsCaBundleUsEast1.ts +86 -0
  268. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseContext.ts +54 -0
  269. package/dist/.test/assets/git/declarations/practices/persist-with-rds/best-practice/src/utils/database/withDatabaseTransaction.ts +35 -0
  270. package/dist/.test/assets/git/declarations/practices/persist-with-rds/config-validates-schema.declapract.integration.test.ts +332 -0
  271. package/dist/.test/assets/git/declarations/practices/persist-with-rds/database-client.declapract.integration.test.ts +291 -0
  272. package/dist/.test/assets/git/declarations/practices/persist-with-rds/database-wrappers-typecheck.declapract.integration.test.ts +225 -0
  273. package/dist/.test/assets/git/declarations/practices/persist-with-rds/deploy-database-gerunds.declapract.integration.test.ts +57 -0
  274. package/dist/.test/assets/git/declarations/practices/persist-with-rds/empty-template-declares-zero-clusters.declapract.integration.test.ts +71 -0
  275. package/dist/.test/assets/git/declarations/practices/persist-with-rds/engine-upgrade.declapract.integration.test.ts +243 -0
  276. package/dist/.test/assets/git/declarations/practices/persist-with-rds/pg-pool-patch.declapract.integration.test.ts +884 -0
  277. package/dist/.test/assets/git/declarations/practices/persist-with-rds/provision-testdb-access.declapract.integration.test.ts +50 -0
  278. package/dist/.test/assets/git/declarations/practices/persist-with-rds/ssm-param-names.declapract.integration.test.ts +154 -0
  279. package/dist/.test/assets/git/declarations/practices/persist-with-rds/testdb-per-worktree.declapract.integration.test.ts +332 -0
  280. package/dist/.test/assets/git/declarations/practices/persist-with-rds/testdb-preflight-failloud.declapract.integration.test.ts +83 -0
  281. package/dist/.test/assets/git/declarations/practices/persist-with-rds/with-connection-in-input.declapract.integration.test.ts +97 -0
  282. package/dist/.test/assets/git/declarations/practices/rhachet/.declapract.integration.test.ts +98 -0
  283. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/demo-repo-with-consumer-boot/.agent/repo=.this/role=any/boot.yml +9 -0
  284. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/demo-repo-with-consumer-boot/declapract.declare.yml +4 -0
  285. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/demo-repo-with-consumer-boot/declapract.use.yml +2 -0
  286. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/demo-repo-with-consumer-boot/package.json +4 -0
  287. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-keyrack-extant/.agent/keyrack.yml +9 -0
  288. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-keyrack-extant/declapract.use.node.yml +4 -0
  289. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-keyrack-extant/declapract.use.yml +4 -0
  290. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-keyrack-extant/package.json +4 -0
  291. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-self-linked/declapract.use.yml +4 -0
  292. package/dist/.test/assets/git/declarations/practices/rhachet/.test/assets/repo-self-linked/package.json +22 -0
  293. package/dist/.test/assets/git/declarations/practices/rhachet/__snapshots__/.declapract.integration.test.ts.snap +46 -0
  294. package/dist/.test/assets/git/declarations/practices/rhachet/__snapshots__/boot-refs-glossary.declapract.integration.test.ts.snap +6 -0
  295. package/dist/.test/assets/git/declarations/practices/rhachet/__snapshots__/boot-yml-findsert.declapract.integration.test.ts.snap +33 -0
  296. package/dist/.test/assets/git/declarations/practices/rhachet/__snapshots__/keyrack-yml-findsert.declapract.integration.test.ts.snap +28 -0
  297. package/dist/.test/assets/git/declarations/practices/rhachet/__snapshots__/self-link-build-order.declapract.integration.test.ts.snap +81 -0
  298. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/deprecated-use-file/.declapract.readme.md +11 -0
  299. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/deprecated-use-file/rhachet.use.ts.declapract.ts +12 -0
  300. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/.declapract.readme.md +59 -0
  301. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/.test/assets/demo-repo-with-rhachet-prod-deps/declapract.declare.yml +4 -0
  302. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/.test/assets/demo-repo-with-rhachet-prod-deps/declapract.use.yml +2 -0
  303. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/.test/assets/demo-repo-with-rhachet-prod-deps/package.json +12 -0
  304. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/package.json +5 -0
  305. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/prod-deps/package.json.declapract.ts +88 -0
  306. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/review-peer-artifacts/.behavior/<star><star>/.reviews/<star><star>/<star>peer-review<star>.md.declapract.ts +16 -0
  307. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/review-peer-artifacts/.behavior/<star><star>/.reviews/peer/<star><star>/<star>.md.declapract.ts +16 -0
  308. package/dist/.test/assets/git/declarations/practices/rhachet/bad-practices/review-peer-artifacts/.declapract.readme.md +12 -0
  309. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.agent/keyrack.yml.declapract.ts +143 -0
  310. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.agent/repo=.this/role=any/boot.yml +22 -0
  311. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.agent/repo=.this/role=any/boot.yml.declapract.ts +189 -0
  312. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.declapract.readme.md +40 -0
  313. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.gitattributes.declapract.ts +65 -0
  314. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/.gitignore.declapract.ts +94 -0
  315. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/package.json +19 -0
  316. package/dist/.test/assets/git/declarations/practices/rhachet/best-practice/package.json.declapract.ts +51 -0
  317. package/dist/.test/assets/git/declarations/practices/rhachet/boot-refs-glossary.declapract.integration.test.ts +91 -0
  318. package/dist/.test/assets/git/declarations/practices/rhachet/boot-yml-findsert.declapract.integration.test.ts +149 -0
  319. package/dist/.test/assets/git/declarations/practices/rhachet/keyrack-yml-findsert.declapract.integration.test.ts +105 -0
  320. package/dist/.test/assets/git/declarations/practices/rhachet/self-link-build-order.declapract.integration.test.ts +88 -0
  321. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils/blackbox/lambdas/consumeSESEmailEventFromSNS.acceptance.test.ts +23 -0
  322. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils/declapract.use.yml +9 -0
  323. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils/package.json +4 -0
  324. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-2/blackbox/lambdas/addDecoratedImage.acceptance.test.ts +19 -0
  325. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-2/declapract.use.yml +9 -0
  326. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-2/package.json +4 -0
  327. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-3/blackbox/lambdas/addDecoratedImage.acceptance.test.ts +19 -0
  328. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-3/declapract.use.yml +9 -0
  329. package/dist/.test/assets/git/declarations/practices/tests-any/.test/assets/repo-old-acceptance-utils-3/package.json +4 -0
  330. package/dist/.test/assets/git/declarations/practices/tests-any/__snapshots__/changedsince-origin-main.declapract.integration.test.ts.snap +8 -0
  331. package/dist/.test/assets/git/declarations/practices/tests-any/__snapshots__/livedb-wake-branches.declapract.integration.test.ts.snap +6 -0
  332. package/dist/.test/assets/git/declarations/practices/tests-any/__snapshots__/old-acceptance-test-utils.declapract.integration.test.ts.snap +162 -0
  333. package/dist/.test/assets/git/declarations/practices/tests-any/__snapshots__/test-kind-seam.declapract.integration.test.ts.snap +9 -0
  334. package/dist/.test/assets/git/declarations/practices/tests-any/autoprune-hooks.declapract.integration.test.ts +111 -0
  335. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/.declapract.integration.test.ts +69 -0
  336. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/.declapract.readme.md +19 -0
  337. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/.test/assets/demo-repo-with-stale-test-fns-dep/declapract.use.yml +3 -0
  338. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/.test/assets/demo-repo-with-stale-test-fns-dep/package.json +11 -0
  339. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/__snapshots__/.declapract.integration.test.ts.snap +43 -0
  340. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/dev-tool-in-dependencies/package.json.declapract.ts +81 -0
  341. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/javascript-config-files/.declapract.readme.md +1 -0
  342. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/javascript-config-files/jest.<star>.js.declapract.ts +17 -0
  343. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/mocks/.declapract.readme.md +8 -0
  344. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/mocks/<star><star>/__mock__/<star>.js +3 -0
  345. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/mocks/<star><star>/__mock__/<star>.ts +3 -0
  346. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.declapract.integration.test.ts +83 -0
  347. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.declapract.readme.md +22 -0
  348. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.test/assets/demo-repo-with-accept-blackbox-dir/accept.blackbox/.test/assets/.agent/config.yml +1 -0
  349. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.test/assets/demo-repo-with-accept-blackbox-dir/accept.blackbox/.test/assets/.rhachet/manifest.json +1 -0
  350. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.test/assets/demo-repo-with-accept-blackbox-dir/accept.blackbox/somefile.ts +1 -0
  351. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.test/assets/demo-repo-with-accept-blackbox-dir/declapract.use.yml +6 -0
  352. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/.test/assets/demo-repo-with-accept-blackbox-dir/package.json +4 -0
  353. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/accept.blackbox/<star><star>/<star>.declapract.ts +19 -0
  354. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-dir-location/acceptance/<star><star>/<star>.declapract.ts +19 -0
  355. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-import-paths/.declapract.readme.md +31 -0
  356. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-import-paths/<star><star>/<star>.ts.declapract.ts +25 -0
  357. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils/blackbox/_utils/getDataFromLastOpenBracketAtStartOfLine.ts.declapract.ts +3 -0
  358. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils/blackbox/_utils/invokeLambda.ts.declapract.ts +3 -0
  359. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils/blackbox/lambdas/<star>.ts.declapract.ts +49 -0
  360. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils-2/blackbox/lambdas/<star>.ts.declapract.ts +27 -0
  361. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils-3/blackbox/_utils/environment.ts.declapract.ts +3 -0
  362. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-acceptance-test-utils-3/blackbox/lambdas/<star>.ts.declapract.ts +23 -0
  363. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-extension-pattern/.declapract.readme.md +3 -0
  364. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-extension-pattern/<star><star>/<star>.test.acceptance.ts.declapract.ts +11 -0
  365. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-extension-pattern/<star><star>/<star>.test.integration.ts.declapract.ts +11 -0
  366. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-test-utils-and-assets-location/.declapract.readme.md +8 -0
  367. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-test-utils-and-assets-location/<star><star>/<star>.ts.declapract.ts +27 -0
  368. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-test-utils-and-assets-location/<star><star>/__test_assets__/<star><star>/<star>.declapract.ts +17 -0
  369. package/dist/.test/assets/git/declarations/practices/tests-any/bad-practices/old-test-utils-and-assets-location/<star><star>/__test_utils__/<star><star>/<star>.declapract.ts +17 -0
  370. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/.declapract.readme.md +52 -0
  371. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/.declapract.todo.md +3 -0
  372. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  373. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/package.json +18 -0
  374. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/package.json.declapract.ts +3 -0
  375. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/src/.test/useWakeOfLivedb.ts +209 -0
  376. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/src/<star><star>/<star>.integration.test.ts.declapract.ts +8 -0
  377. package/dist/.test/assets/git/declarations/practices/tests-any/best-practice/src/<star><star>/<star>.test.ts.declapract.ts +7 -0
  378. package/dist/.test/assets/git/declarations/practices/tests-any/build-ifstale.declapract.integration.test.ts +124 -0
  379. package/dist/.test/assets/git/declarations/practices/tests-any/changedsince-origin-main.declapract.integration.test.ts +58 -0
  380. package/dist/.test/assets/git/declarations/practices/tests-any/livedb-wake-branches.declapract.integration.test.ts +315 -0
  381. package/dist/.test/assets/git/declarations/practices/tests-any/old-acceptance-test-utils.declapract.integration.test.ts +122 -0
  382. package/dist/.test/assets/git/declarations/practices/tests-any/package.json.shell-flags.declapract.integration.test.ts +139 -0
  383. package/dist/.test/assets/git/declarations/practices/tests-any/test-kind-seam.declapract.integration.test.ts +87 -0
  384. package/dist/.test/assets/git/declarations/useCases.yml +29 -0
  385. package/dist/.test/assets/{expo-fullusecase/declarations/practices/git/best-practice → git/repo-with-all-gitattributes-declarers}/.gitattributes +3 -0
  386. package/dist/.test/assets/git/repo-with-all-gitattributes-declarers/declapract.use.yml +26 -0
  387. package/dist/.test/assets/git/repo-with-all-gitattributes-declarers/package.json +4 -0
  388. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/declapract.use.yml +4 -0
  389. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/package.json +15 -0
  390. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy.patch +6 -0
  391. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy@1.39.1.patch +6 -0
  392. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/type-fns@1.21.3.patch +6 -0
  393. package/dist/.test/assets/pnpm/declarations/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/pnpm-lock.yaml +19 -0
  394. package/dist/.test/assets/pnpm/declarations/practices/pnpm/__snapshots__/stale-patched-dependency.declapract.integration.test.ts.snap +39 -0
  395. package/dist/.test/assets/pnpm/declarations/practices/pnpm/stale-patched-dependency.declapract.integration.test.ts +53 -0
  396. package/dist/.test/assets/rhachet/declarations/practices/rhachet/best-practice/.declapract.readme.md +8 -0
  397. package/dist/.test/assets/rhachet/declarations/practices/rhachet/best-practice/.gitattributes.declapract.ts +65 -0
  398. package/dist/.test/assets/tests-any-only/declarations/practices/tests-any/best-practice/.declapract.readme.md +7 -0
  399. package/dist/.test/assets/tests-any-only/declarations/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  400. package/dist/__snapshots__/gitattributesDeclarers.declapract.integration.test.ts.snap +79 -0
  401. package/dist/__snapshots__/repoSkills.declapract.acceptance.test.ts.snap +512 -0
  402. package/dist/__snapshots__/typecheckBestPracticeTemplates.declapract.integration.test.ts.snap +80 -0
  403. package/dist/gitattributesDeclarers.declapract.integration.test.ts +438 -0
  404. package/dist/practiceOwnerPerFile.declapract.integration.test.ts +53 -0
  405. package/dist/practices/cicd-common/.declapract.integration.test.ts +15 -21
  406. package/dist/practices/git/.declapract.integration.test.ts +2 -2
  407. package/dist/practices/git/.gitattributes.declapract.integration.test.ts +34 -19
  408. package/dist/practices/git/.test/assets/repo-with-legacy-gitattributes/declapract.use.yml +3 -3
  409. package/dist/practices/git/__snapshots__/.gitattributes.declapract.integration.test.ts.snap +4 -4
  410. package/dist/practices/git/best-practice/.declapract.readme.md +37 -0
  411. package/dist/practices/git/best-practice/.gitattributes.declapract.ts +42 -63
  412. package/dist/practices/persist-with-dynamodb/best-practice/.gitattributes.declapract.ts +56 -0
  413. package/dist/practices/persist-with-rds/.test/assets/repo-with-hand-patch/declapract.use.yml +4 -0
  414. package/dist/practices/persist-with-rds/.test/assets/repo-with-hand-patch/package.json +17 -0
  415. package/dist/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/left-pad@1.3.0.patch +6 -0
  416. package/dist/practices/persist-with-rds/.test/assets/repo-with-hand-patch/patches/pg-pool@3.14.0.patch +12 -0
  417. package/dist/practices/persist-with-rds/__snapshots__/pg-pool-patch.declapract.integration.test.ts.snap +147 -0
  418. package/dist/practices/persist-with-rds/best-practice/.declapract.readme.md +29 -0
  419. package/dist/practices/persist-with-rds/best-practice/.gitattributes.declapract.ts +64 -0
  420. package/dist/practices/persist-with-rds/best-practice/package.json +5 -0
  421. package/dist/practices/persist-with-rds/best-practice/patches/pg-pool.patch +21 -0
  422. package/dist/practices/persist-with-rds/pg-pool-patch.declapract.integration.test.ts +884 -0
  423. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/declapract.use.yml +4 -0
  424. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/package.json +15 -0
  425. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy.patch +6 -0
  426. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/rhachet-roles-ehmpathy@1.39.1.patch +6 -0
  427. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/patches/type-fns@1.21.3.patch +6 -0
  428. package/dist/practices/pnpm/.test/assets/repo-stale-patch-beside-bare/pnpm-lock.yaml +19 -0
  429. package/dist/practices/pnpm/__snapshots__/stale-patched-dependency.declapract.integration.test.ts.snap +39 -0
  430. package/dist/practices/pnpm/stale-patched-dependency.declapract.integration.test.ts +53 -0
  431. package/dist/practices/rhachet/best-practice/.declapract.readme.md +8 -0
  432. package/dist/practices/rhachet/best-practice/.gitattributes.declapract.ts +65 -0
  433. package/dist/practices/tests-any/best-practice/.declapract.readme.md +7 -0
  434. package/dist/practices/tests-any/best-practice/.gitattributes.declapract.ts +60 -0
  435. package/dist/repoSkills.declapract.acceptance.test.ts +1150 -0
  436. package/dist/typecheckBestPracticeTemplates.declapract.integration.test.ts +181 -19
  437. package/dist/utils/defineExpectedGitattributesContents.ts +247 -0
  438. package/package.json +6 -6
  439. package/dist/.test/assets/expo-migration/declarations/practices/git/best-practice/.gitattributes +0 -7
  440. package/dist/practices/git/best-practice/.gitattributes +0 -7
@@ -0,0 +1,1150 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { realpathSync } from 'node:fs';
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { stripVTControlCharacters } from 'node:util';
6
+
7
+ import { ConstraintError, MalfunctionError } from 'helpful-errors';
8
+ import { genTempDir, given, then, useBeforeAll, when } from 'test-fns';
9
+
10
+ /**
11
+ * .what = the path to one of this repo's own skills
12
+ */
13
+ const asSkillPath = (input: { skill: string }): string =>
14
+ path.join(
15
+ __dirname,
16
+ '..',
17
+ '.agent',
18
+ 'repo=.this',
19
+ 'role=any',
20
+ 'skills',
21
+ `${input.skill}.sh`,
22
+ );
23
+
24
+ /**
25
+ * .what = the hermetic env a skill runs in: no global or system git config, plus any extras
26
+ */
27
+ const asSkillEnv = (input: { env: Record<string, string> }): NodeJS.ProcessEnv => ({
28
+ ...process.env,
29
+ GIT_CONFIG_GLOBAL: '/dev/null',
30
+ GIT_CONFIG_SYSTEM: '/dev/null',
31
+ ...input.env,
32
+ });
33
+
34
+ /**
35
+ * .what = runs one of this repo's own skills as a human would, and captures what they see
36
+ * .why = a skill is a contract of stdout, stderr, and exit code; only a real run proves each.
37
+ * `env` lets a case bound the git search (`GIT_CEILING_DIRECTORIES`), so a dir under
38
+ * this repo can stand for "no repo", or point git at an absent attr source
39
+ */
40
+ const runSkill = (input: {
41
+ skill: string;
42
+ args: string[];
43
+ cwd: string;
44
+ stdin: string | null;
45
+ env: Record<string, string>;
46
+ }): { stdout: string; stderr: string; status: number | null } => {
47
+ const result = spawnSync(
48
+ 'bash',
49
+ [asSkillPath({ skill: input.skill }), ...input.args],
50
+ {
51
+ cwd: input.cwd,
52
+ input: input.stdin ?? '',
53
+ encoding: 'utf8',
54
+ env: asSkillEnv({ env: input.env }),
55
+ },
56
+ );
57
+ return {
58
+ stdout: result.stdout,
59
+ stderr: result.stderr,
60
+ status: result.status,
61
+ };
62
+ };
63
+
64
+ /**
65
+ * .what = runs a skill under a pseudo-terminal, as a human at a shell would, with no pipe
66
+ * .why = a guard on `-t 0` only fires when stdin is a terminal; util-linux `script` gives the
67
+ * skill one. a pty merges stdout and stderr into one stream, with crlf line ends
68
+ */
69
+ const runSkillOnTerminal = (input: {
70
+ skill: string;
71
+ args: string[];
72
+ cwd: string;
73
+ }): { output: string; status: number | null } => {
74
+ // fail fast, and legibly, where the host lacks util-linux `script` (bsd `script` has no -c)
75
+ const probe = spawnSync('script', ['--version'], { encoding: 'utf8' });
76
+ if (probe.error || !`${probe.stdout}`.includes('util-linux'))
77
+ throw new ConstraintError(
78
+ 'the pty case needs util-linux `script`, which gives the skill a terminal',
79
+ {
80
+ found: probe.error ? `${probe.error.message}` : `${probe.stdout}`.trim(),
81
+ hint: 'install util-linux (debian: apt install bsdutils; macos: brew install util-linux)',
82
+ },
83
+ );
84
+
85
+ const command = ['bash', asSkillPath({ skill: input.skill }), ...input.args]
86
+ .map((part) => `'${part.split("'").join("'\\''")}'`)
87
+ .join(' ');
88
+ const result = spawnSync('script', ['-qec', command, '/dev/null'], {
89
+ cwd: input.cwd,
90
+ encoding: 'utf8',
91
+ env: asSkillEnv({ env: {} }),
92
+ });
93
+ if (result.error)
94
+ throw new MalfunctionError('the pty run of the skill failed to start', {
95
+ error: result.error.message,
96
+ });
97
+ return {
98
+ output: result.stdout.split('\r\n').join('\n'),
99
+ status: result.status,
100
+ };
101
+ };
102
+
103
+ /**
104
+ * .what = writes a `git` shim that fails one subcommand and passes every other to real git
105
+ * .why = some skill branches only run when git breaks for a reason no real input can cause
106
+ * portably; the shim reaches them. each use carries a `.mock` / `.why` / `.real` note
107
+ */
108
+ const genGitShim = async (input: {
109
+ dir: string;
110
+ subcommand: string;
111
+ }): Promise<{ dir: string }> => {
112
+ const gitReal = spawnSync('bash', ['-c', 'command -v git'], {
113
+ encoding: 'utf8',
114
+ }).stdout.trim();
115
+ await fs.mkdir(input.dir, { recursive: true });
116
+ await fs.writeFile(
117
+ path.join(input.dir, 'git'),
118
+ [
119
+ '#!/usr/bin/env bash',
120
+ '# the subcommand is the first arg that is not an option (`git --no-pager diff` → diff)',
121
+ 'SUB=""',
122
+ 'for ARG in "$@"; do case "$ARG" in -*) ;; *) SUB="$ARG"; break ;; esac; done',
123
+ `if [[ "$SUB" == "${input.subcommand}" ]]; then echo "fatal: simulated failure" >&2; exit 128; fi`,
124
+ `exec "${gitReal}" "$@"`,
125
+ '',
126
+ ].join('\n'),
127
+ { mode: 0o755 },
128
+ );
129
+ return { dir: input.dir };
130
+ };
131
+
132
+ /**
133
+ * .what = masks a temp dir path, as given and as resolved, so a snapshot holds the same text on every host
134
+ * .why = git prints the resolved path of a linked temp dir, which also names the clock of its birth
135
+ */
136
+ const asMasked = (input: { text: string; tempDir: string }): string =>
137
+ input.text
138
+ .split(realpathSync(input.tempDir))
139
+ .join('[tempdir]')
140
+ .split(input.tempDir)
141
+ .join('[tempdir]');
142
+
143
+ /**
144
+ * .what = the stdout of a skill run as a human reads it, with the bytes that vary per run cut
145
+ * .why = declapract colors its lines only where the env asks, and prints `> took N seconds`
146
+ * under a step that runs slow; neither is part of the skill's contract
147
+ */
148
+ const asStdoutStable = (input: { stdout: string }): string =>
149
+ stripVTControlCharacters(input.stdout).replace(/^\s*> took [\d.]+ seconds\n/gm, '');
150
+
151
+ /**
152
+ * .what = proves the contracts of this repo's own skills, `git.attr.get` and
153
+ * `declapract.self.apply`, through real runs
154
+ * .why = a skill a human or a robot reaches for must name the fix on every bad input, keep
155
+ * its exit codes semantic, and (for a reader skill) keep stdout clean to pipe. the
156
+ * skills sit under `.agent/`, which jest ignores, so the suite sits at the `src/` root
157
+ */
158
+ describe('repo skills', () => {
159
+ given('[case1] git.attr.get, in a repo with a collapse line and an override', () => {
160
+ const tempDir = genTempDir({ slug: 'skill-git-attr-get', git: true });
161
+ useBeforeAll(async () => {
162
+ await fs.writeFile(
163
+ path.join(tempDir, '.gitattributes'),
164
+ '*.test.ts linguist-generated\nkeep.test.ts -linguist-generated\n*.lock merge=theirs\n',
165
+ );
166
+ return {};
167
+ });
168
+ const run = (input: {
169
+ args: string[];
170
+ stdin: string | null;
171
+ env?: Record<string, string>;
172
+ }) =>
173
+ runSkill({
174
+ skill: 'git.attr.get',
175
+ args: input.args,
176
+ cwd: tempDir,
177
+ stdin: input.stdin,
178
+ env: input.env ?? {},
179
+ });
180
+
181
+ when('[t0] --help is asked', () => {
182
+ then('it prints usage, options, and guarantee to stdout, exit 0', () => {
183
+ const result = run({ args: ['--help'], stdin: null });
184
+ expect(result.status).toEqual(0);
185
+ expect(result.stdout).toContain('usage:');
186
+ expect(result.stdout).toContain('--paths');
187
+ expect(result.stdout).not.toContain('set -euo pipefail');
188
+ expect(result.stdout).not.toMatch(/^#/m); // plain help, no comment markers
189
+ expect(result.stdout).toMatchSnapshot('git.attr.get --help');
190
+ });
191
+
192
+ then('the --skill, --repo, and --role args rhx passes are skipped, so help still prints', () => {
193
+ const result = run({
194
+ args: ['--skill', 'git.attr.get', '--repo', '.this', '--role', 'any', '--help'],
195
+ stdin: null,
196
+ });
197
+ expect(result.status).toEqual(0);
198
+ expect(result.stdout).toEqual(run({ args: ['--help'], stdin: null }).stdout);
199
+ });
200
+ });
201
+
202
+ when('[t1] paths are passed by flag', () => {
203
+ then('stdout holds only git lines, and the banner rides stderr, exit 0', () => {
204
+ const result = run({
205
+ args: [
206
+ '--attr',
207
+ 'linguist-generated',
208
+ '--paths',
209
+ 'a.test.ts keep.test.ts a.ts',
210
+ ],
211
+ stdin: null,
212
+ });
213
+ expect(result.status).toEqual(0);
214
+ expect(result.stdout).toEqual(
215
+ [
216
+ 'a.test.ts: linguist-generated: set',
217
+ 'keep.test.ts: linguist-generated: unset',
218
+ 'a.ts: linguist-generated: unspecified',
219
+ '',
220
+ ].join('\n'),
221
+ );
222
+ expect(result.stderr).toContain('🐚 git.attr.get');
223
+ // the split is never silent: the banner names the count and the @stdin route
224
+ expect(result.stderr).toContain(
225
+ 'paths: 3, split on spaces; a path with a space goes via @stdin',
226
+ );
227
+ expect(result.stderr).toMatchSnapshot('git.attr.get banner');
228
+ expect(result.stdout).toMatchSnapshot('git.attr.get stdout — paths by flag');
229
+ });
230
+ });
231
+
232
+ when('[t2] paths are piped via @stdin, one with a space', () => {
233
+ then('each path is reported whole, exit 0', () => {
234
+ const result = run({
235
+ args: ['--attr', 'linguist-generated', '--paths', '@stdin'],
236
+ stdin: 'docs/my notes.test.ts\nkeep.test.ts\n',
237
+ });
238
+ expect(result.status).toEqual(0);
239
+ expect(result.stdout).toEqual(
240
+ [
241
+ 'docs/my notes.test.ts: linguist-generated: set',
242
+ 'keep.test.ts: linguist-generated: unset',
243
+ '',
244
+ ].join('\n'),
245
+ );
246
+ expect(result.stderr).toContain('paths: from stdin, one per line');
247
+ expect(result.stdout).toMatchSnapshot('git.attr.get stdout — paths via @stdin');
248
+ expect(result.stderr).toMatchSnapshot('git.attr.get banner — paths via @stdin');
249
+ });
250
+ });
251
+
252
+ when('[t10] a spaced path that does not exist is passed via --paths', () => {
253
+ then('it splits into two paths, each reported, and the banner names the count, exit 0', () => {
254
+ const result = run({
255
+ args: ['--attr', 'linguist-generated', '--paths', 'no such.ts'],
256
+ stdin: null,
257
+ });
258
+ expect(result.status).toEqual(0);
259
+ expect(result.stdout).toEqual(
260
+ [
261
+ 'no: linguist-generated: unspecified',
262
+ 'such.ts: linguist-generated: unspecified',
263
+ '',
264
+ ].join('\n'),
265
+ );
266
+ expect(result.stderr).toContain(
267
+ 'paths: 2, split on spaces; a path with a space goes via @stdin',
268
+ );
269
+ expect(result.stdout).toMatchSnapshot('git.attr.get stdout — an absent spaced path, split');
270
+ expect(result.stderr).toMatchSnapshot('git.attr.get banner — an absent spaced path, split');
271
+ });
272
+ });
273
+
274
+ when('[t9] the path set names no path', () => {
275
+ then('a blank --paths: a ConstraintError that names the fix, before git runs, exit 2', () => {
276
+ const result = run({
277
+ args: ['--attr', 'linguist-generated', '--paths', ' '],
278
+ stdin: null,
279
+ });
280
+ expect(result.status).toEqual(2);
281
+ expect(result.stdout).toEqual('');
282
+ expect(result.stderr).toContain('✋ ConstraintError: --paths named no path');
283
+ expect(result.stderr).not.toContain('MalfunctionError');
284
+ expect(result.stderr).toMatchSnapshot('git.attr.get — a blank --paths');
285
+ });
286
+
287
+ then('an empty pipe to @stdin: a ConstraintError that names the fix, exit 2', () => {
288
+ const result = run({
289
+ args: ['--attr', 'linguist-generated', '--paths', '@stdin'],
290
+ stdin: '',
291
+ });
292
+ expect(result.status).toEqual(2);
293
+ expect(result.stdout).toEqual('');
294
+ expect(result.stderr).toContain(
295
+ '✋ ConstraintError: --paths @stdin got no path from the pipe',
296
+ );
297
+ expect(result.stderr).toMatchSnapshot('git.attr.get — an empty pipe to @stdin');
298
+ });
299
+ });
300
+
301
+ when('[t8] an attribute that carries a value is asked', () => {
302
+ then('stdout holds the value git computes, exit 0', () => {
303
+ const result = run({
304
+ args: ['--attr', 'merge', '--paths', 'yarn.lock a.ts'],
305
+ stdin: null,
306
+ });
307
+ expect(result.status).toEqual(0);
308
+ expect(result.stdout).toEqual(
309
+ ['yarn.lock: merge: theirs', 'a.ts: merge: unspecified', ''].join('\n'),
310
+ );
311
+ expect(result.stdout).toMatchSnapshot('git.attr.get stdout — a value attribute');
312
+ });
313
+ });
314
+
315
+ when('[t3] bad input is given', () => {
316
+ const cases = [
317
+ { slug: 'no args', args: [] as string[] },
318
+ { slug: '--attr with no value', args: ['--paths', 'a.ts', '--attr'] },
319
+ { slug: '--paths with no value', args: ['--attr', 'diff', '--paths'] },
320
+ { slug: 'a flag where a value belongs', args: ['--attr', '--paths', 'a.ts'] },
321
+ { slug: 'an unknown option', args: ['--path', 'a.ts'] },
322
+ { slug: 'an invalid attr name', args: ['--attr', '!bad', '--paths', 'a.ts'] },
323
+ ];
324
+ cases.forEach((thisCase) =>
325
+ then(`${thisCase.slug}: a ConstraintError that names the fix, stdout empty, exit 2`, () => {
326
+ const result = run({ args: thisCase.args, stdin: null });
327
+ expect(result.status).toEqual(2);
328
+ expect(result.stdout).toEqual('');
329
+ expect(result.stderr).toContain('✋ ConstraintError:');
330
+ expect(result.stderr).toContain('fix:');
331
+ expect(result.stderr).toMatchSnapshot(`git.attr.get — ${thisCase.slug}`);
332
+ }),
333
+ );
334
+ });
335
+
336
+ when('[t4] --paths @stdin is run from a terminal, with no pipe', () => {
337
+ then('a ConstraintError names the pipe to add, before git waits on the terminal, exit 2', () => {
338
+ const result = runSkillOnTerminal({
339
+ skill: 'git.attr.get',
340
+ args: ['--attr', 'linguist-generated', '--paths', '@stdin'],
341
+ cwd: tempDir,
342
+ });
343
+ expect(result.status).toEqual(2);
344
+ expect(result.output).toContain(
345
+ '✋ ConstraintError: --paths @stdin needs paths piped in',
346
+ );
347
+ expect(result.output).toMatchSnapshot('git.attr.get — @stdin on a terminal');
348
+ });
349
+ });
350
+
351
+ when('[t5] git itself fails', () => {
352
+ /**
353
+ * .mock = one git subcommand, via a shim on PATH that fails it and passes every other call
354
+ * .why = once `rev-parse` finds the repo, the attr name is valid, and each path sits in
355
+ * the repo ([t6] proves the outside path), no real input makes `check-attr` fail;
356
+ * and a repo broken enough to fail `rev-parse` is not one a test can build
357
+ * portably. the shim reaches the branch where git breaks for another reason
358
+ * .real = [t1] and [t2] run the real `git check-attr`; [case2] the real `rev-parse` failure
359
+ */
360
+ const shims = useBeforeAll(async () => ({
361
+ checkAttr: (
362
+ await genGitShim({
363
+ dir: path.join(tempDir, '.shim-check-attr'),
364
+ subcommand: 'check-attr',
365
+ })
366
+ ).dir,
367
+ revParse: (
368
+ await genGitShim({
369
+ dir: path.join(tempDir, '.shim-rev-parse'),
370
+ subcommand: 'rev-parse',
371
+ })
372
+ ).dir,
373
+ }));
374
+
375
+ then('check-attr fails: a MalfunctionError names the step, exit 1', () => {
376
+ const result = run({
377
+ args: ['--attr', 'linguist-generated', '--paths', 'a.ts'],
378
+ stdin: null,
379
+ env: { PATH: `${shims.checkAttr}:${process.env.PATH}` },
380
+ });
381
+ expect(result.status).toEqual(1);
382
+ expect(result.stdout).toEqual('');
383
+ expect(result.stderr).toContain('💥 MalfunctionError: git check-attr failed');
384
+ // the full stderr: the banner, git's own message, then the error that points to it
385
+ expect(asMasked({ text: result.stderr, tempDir })).toMatchSnapshot(
386
+ 'git.attr.get — git check-attr failed',
387
+ );
388
+ });
389
+
390
+ then('rev-parse fails for a reason other than no repo: a MalfunctionError with git\'s message, exit 1', () => {
391
+ const result = run({
392
+ args: ['--attr', 'linguist-generated', '--paths', 'a.ts'],
393
+ stdin: null,
394
+ env: { PATH: `${shims.revParse}:${process.env.PATH}` },
395
+ });
396
+ expect(result.status).toEqual(1);
397
+ expect(result.stderr).toContain('fatal: simulated failure');
398
+ expect(result.stderr).toContain('💥 MalfunctionError: git rev-parse failed');
399
+ expect(result.stderr).not.toContain('ConstraintError');
400
+ expect(result.stderr).toMatchSnapshot('git.attr.get — git rev-parse failed');
401
+ });
402
+ });
403
+
404
+ when('[t6] a path outside the repo is given', () => {
405
+ then("a ConstraintError, with git's message kept, exit 2", () => {
406
+ const result = run({
407
+ args: ['--attr', 'linguist-generated', '--paths', '/etc/hostname'],
408
+ stdin: null,
409
+ });
410
+ expect(result.status).toEqual(2);
411
+ expect(result.stdout).toEqual('');
412
+ expect(result.stderr).toContain("'/etc/hostname' is outside repository");
413
+ expect(result.stderr).toContain('✋ ConstraintError: a path lies outside this repo');
414
+ // the full stderr: the banner, git's own message, then the error that names the fix
415
+ expect(asMasked({ text: result.stderr, tempDir })).toMatchSnapshot(
416
+ 'git.attr.get — a path outside the repo',
417
+ );
418
+ });
419
+ });
420
+
421
+ when('[t7] a file with a space is passed via --paths, which splits it', () => {
422
+ useBeforeAll(async () => {
423
+ await fs.mkdir(path.join(tempDir, 'docs'), { recursive: true });
424
+ await fs.writeFile(path.join(tempDir, 'docs', 'my notes.test.ts'), '');
425
+ return {};
426
+ });
427
+
428
+ then('a ConstraintError names the @stdin call that keeps it whole, exit 2', () => {
429
+ const result = run({
430
+ args: ['--attr', 'linguist-generated', '--paths', 'docs/my notes.test.ts'],
431
+ stdin: null,
432
+ });
433
+ expect(result.status).toEqual(2);
434
+ expect(result.stdout).toEqual('');
435
+ expect(result.stderr).toContain(
436
+ "✋ ConstraintError: 'docs/my notes.test.ts' holds a space",
437
+ );
438
+ expect(result.stderr).toContain('--paths @stdin');
439
+ expect(result.stderr).toMatchSnapshot('git.attr.get — a path with a space via --paths');
440
+ });
441
+ });
442
+ });
443
+
444
+ given('[case2] git.attr.get, outside any git repo', () => {
445
+ const tempDir = genTempDir({ slug: 'skill-git-attr-get-norepo' });
446
+
447
+ when('[t0] a valid call is made', () => {
448
+ then('a ConstraintError names the fix, not a raw git fatal, exit 2', () => {
449
+ const result = runSkill({
450
+ skill: 'git.attr.get',
451
+ args: ['--attr', 'diff', '--paths', 'a.ts'],
452
+ cwd: tempDir,
453
+ stdin: null,
454
+ env: { GIT_CEILING_DIRECTORIES: path.dirname(tempDir) },
455
+ });
456
+ expect(result.status).toEqual(2);
457
+ expect(result.stderr).toContain('✋ ConstraintError: not inside a git repo');
458
+ expect(result.stderr).not.toContain('fatal:');
459
+ expect(result.stderr).toMatchSnapshot('git.attr.get — outside a repo');
460
+ });
461
+ });
462
+ });
463
+
464
+ given('[case3] declapract.self.apply, in a git repo with no declapract config', () => {
465
+ const tempDir = genTempDir({
466
+ slug: 'skill-declapract-self-apply',
467
+ git: true,
468
+ symlink: [{ at: 'node_modules', to: 'node_modules' }],
469
+ });
470
+ const run = (input: { args: string[] }) =>
471
+ runSkill({
472
+ skill: 'declapract.self.apply',
473
+ args: input.args,
474
+ cwd: tempDir,
475
+ stdin: null,
476
+ env: {},
477
+ });
478
+
479
+ when('[t0] --help is asked', () => {
480
+ then('it prints usage, options, and guarantee to stdout, exit 0', () => {
481
+ const result = run({ args: ['--help'] });
482
+ expect(result.status).toEqual(0);
483
+ expect(result.stdout).toContain('usage:');
484
+ expect(result.stdout).toContain('--build');
485
+ expect(result.stdout).not.toContain('set -euo pipefail');
486
+ expect(result.stdout).not.toMatch(/^#/m); // plain help, no comment markers
487
+ expect(result.stdout).toMatchSnapshot('declapract.self.apply --help');
488
+ });
489
+
490
+ then('the --skill, --repo, and --role args rhx passes are skipped, so help still prints', () => {
491
+ const result = run({
492
+ args: ['--skill', 'declapract.self.apply', '--repo', '.this', '--role', 'any', '--help'],
493
+ });
494
+ expect(result.status).toEqual(0);
495
+ expect(result.stdout).toEqual(run({ args: ['--help'] }).stdout);
496
+ });
497
+ });
498
+
499
+ when('[t1] bad input is given', () => {
500
+ const cases = [
501
+ { slug: 'no args', args: [] as string[] },
502
+ { slug: '--practice with no value', args: ['--file', '.gitattributes', '--practice'] },
503
+ { slug: '--file with no value', args: ['--practice', 'git', '--file'] },
504
+ {
505
+ slug: '--build with no value',
506
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build'],
507
+ },
508
+ { slug: 'a flag where a value belongs', args: ['--practice', '--file', '.gitattributes'] },
509
+ { slug: 'an unknown option', args: ['--practise', 'git'] },
510
+ {
511
+ slug: 'a build mode outside run or skip',
512
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'later'],
513
+ },
514
+ { slug: 'a --file above the repo root', args: ['--practice', 'git', '--file', '../x'] },
515
+ { slug: 'a --practice of ..', args: ['--practice', '..', '--file', '.gitattributes'] },
516
+ { slug: 'a --practice with a slash', args: ['--practice', 'git/x', '--file', '.gitattributes'] },
517
+ { slug: 'an absolute --file', args: ['--practice', 'git', '--file', '/tmp/x'] },
518
+ ];
519
+ cases.forEach((thisCase) =>
520
+ then(`${thisCase.slug}: a ConstraintError that names the fix, exit 2`, () => {
521
+ const result = run({ args: thisCase.args });
522
+ expect(result.status).toEqual(2);
523
+ expect(result.stderr).toContain('✋ ConstraintError:');
524
+ expect(result.stderr).toContain('fix:');
525
+ expect(result.stderr).toMatchSnapshot(
526
+ `declapract.self.apply — ${thisCase.slug}`,
527
+ );
528
+ }),
529
+ );
530
+ });
531
+
532
+ when('[t2] the repo has no declapract.use.yml', () => {
533
+ then('a ConstraintError names the absent config, before any build, exit 2', () => {
534
+ const result = run({
535
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'run'],
536
+ });
537
+ expect(result.status).toEqual(2);
538
+ expect(result.stderr).toContain(
539
+ '✋ ConstraintError: no declapract.use.yml at the repo root',
540
+ );
541
+ expect(result.stdout).not.toContain('🐢 lets ride...');
542
+ expect(
543
+ asMasked({ text: result.stderr, tempDir }),
544
+ ).toMatchSnapshot('declapract.self.apply — no declapract config');
545
+ });
546
+ });
547
+
548
+ /**
549
+ * .what = writes a use config whose declarations hold an empty `git` practice and no use cases
550
+ * .why = the config and practice checks pass, so the build and the apply each get to run,
551
+ * and the apply fails for a reason no real practice can cause on demand. idempotent,
552
+ * so each case that needs it writes it, and no case leans on another's order
553
+ */
554
+ const genConfigWithAbsentPractices = async () => {
555
+ await fs.mkdir(path.join(tempDir, 'declarations', 'practices', 'git'), { recursive: true });
556
+ await fs.writeFile(
557
+ path.join(tempDir, 'declarations', 'declapract.declare.yml'),
558
+ 'declare:\n practices: practices\n use-cases: useCases.yml\n',
559
+ );
560
+ await fs.writeFile(
561
+ path.join(tempDir, 'declapract.use.yml'),
562
+ "declarations: 'declarations/declapract.declare.yml'\nuseCase: typescript-project\n",
563
+ );
564
+ };
565
+
566
+ when('[t3] the build step fails', () => {
567
+ useBeforeAll(async () => genConfigWithAbsentPractices());
568
+
569
+ then('a MalfunctionError names the build, exit 1', () => {
570
+ // the temp repo has no package.json, so `npm run build` has no build to run
571
+ const result = run({
572
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'run'],
573
+ });
574
+ expect(result.status).toEqual(1);
575
+ expect(result.stderr).toContain('💥 MalfunctionError: build failed');
576
+ // sliced at the error: npm's own output above it names a debug log file whose name holds a clock
577
+ expect(
578
+ result.stderr.slice(result.stderr.indexOf('💥')),
579
+ ).toMatchSnapshot('declapract.self.apply — build failed');
580
+ });
581
+ });
582
+
583
+ when('[t4] the apply step fails', () => {
584
+ useBeforeAll(async () => genConfigWithAbsentPractices());
585
+
586
+ then('a MalfunctionError names the apply, exit 1', () => {
587
+ const result = run({
588
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
589
+ });
590
+ expect(result.status).toEqual(1);
591
+ expect(result.stderr).toContain('💥 MalfunctionError: apply failed');
592
+ // sliced at the error: declapract's own output above it is a stack trace, with this
593
+ // host's install paths, color codes, and the mktemp path of the isolated root
594
+ expect(result.stderr).toContain('UserInputError');
595
+ expect(
596
+ result.stderr.slice(result.stderr.indexOf('💥')),
597
+ ).toMatchSnapshot('declapract.self.apply — apply failed');
598
+ });
599
+ });
600
+
601
+ when('[t5] git rev-parse fails for a reason other than no repo', () => {
602
+ /**
603
+ * .mock = `git rev-parse`, via a shim on PATH that fails it and passes every other call
604
+ * .why = a repo broken enough to fail `rev-parse` for another reason is not one a test
605
+ * can build portably
606
+ * .real = [case5] runs the real `rev-parse` failure outside a repo
607
+ */
608
+ const shim = useBeforeAll(async () =>
609
+ genGitShim({
610
+ dir: path.join(tempDir, '.shim-rev-parse'),
611
+ subcommand: 'rev-parse',
612
+ }),
613
+ );
614
+
615
+ then("a MalfunctionError, with git's message kept, exit 1", () => {
616
+ const result = runSkill({
617
+ skill: 'declapract.self.apply',
618
+ args: ['--practice', 'git', '--file', '.gitattributes'],
619
+ cwd: tempDir,
620
+ stdin: null,
621
+ env: { PATH: `${shim.dir}:${process.env.PATH}` },
622
+ });
623
+ expect(result.status).toEqual(1);
624
+ expect(result.stderr).toContain('fatal: simulated failure');
625
+ expect(result.stderr).toContain('💥 MalfunctionError: git rev-parse failed');
626
+ expect(result.stderr).not.toContain('ConstraintError');
627
+ expect(result.stderr).toMatchSnapshot(
628
+ 'declapract.self.apply — git rev-parse failed',
629
+ );
630
+ });
631
+ });
632
+
633
+ when('[t6] the use config names no declarations path', () => {
634
+ useBeforeAll(async () => {
635
+ await fs.writeFile(
636
+ path.join(tempDir, 'declapract.use.yml'),
637
+ 'useCase: typescript-project\n',
638
+ );
639
+ });
640
+
641
+ then('a ConstraintError names the absent key, exit 2', () => {
642
+ const result = run({
643
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
644
+ });
645
+ expect(result.status).toEqual(2);
646
+ expect(result.stderr).toContain(
647
+ '✋ ConstraintError: declapract.use.yml names no declarations path',
648
+ );
649
+ expect(result.stderr).toMatchSnapshot(
650
+ 'declapract.self.apply — use config names no declarations',
651
+ );
652
+ });
653
+ });
654
+
655
+ when('[t7] the use config names a declarations path that holds no declare config', () => {
656
+ useBeforeAll(async () => {
657
+ await fs.writeFile(
658
+ path.join(tempDir, 'declapract.use.yml'),
659
+ "declarations: 'declarations-absent/declapract.declare.yml'\nuseCase: typescript-project\n",
660
+ );
661
+ });
662
+
663
+ then('a ConstraintError names the path it read, exit 2', () => {
664
+ const result = run({
665
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
666
+ });
667
+ expect(result.status).toEqual(2);
668
+ expect(result.stderr).toContain(
669
+ '✋ ConstraintError: no declare config at declarations-absent/declapract.declare.yml',
670
+ );
671
+ expect(result.stderr).toMatchSnapshot(
672
+ 'declapract.self.apply — declare config absent',
673
+ );
674
+ });
675
+ });
676
+
677
+ when('[t8] the declare config names a practices dir that is absent, as before a build', () => {
678
+ useBeforeAll(async () => {
679
+ await fs.mkdir(path.join(tempDir, 'declarations-unbuilt'), { recursive: true });
680
+ await fs.writeFile(
681
+ path.join(tempDir, 'declarations-unbuilt', 'declapract.declare.yml'),
682
+ 'declare:\n practices: dist/practices\n use-cases: dist/useCases.yml\n',
683
+ );
684
+ await fs.writeFile(
685
+ path.join(tempDir, 'declapract.use.yml'),
686
+ "declarations: 'declarations-unbuilt/declapract.declare.yml'\nuseCase: typescript-project\n",
687
+ );
688
+ });
689
+
690
+ then('a ConstraintError names the practice, finds none, and names --build run, exit 2', () => {
691
+ const result = run({
692
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
693
+ });
694
+ expect(result.status).toEqual(2);
695
+ expect(result.stderr).toContain(
696
+ "✋ ConstraintError: no practice 'git' in dist/practices, which holds none",
697
+ );
698
+ expect(result.stderr).toContain(
699
+ 'fix: rhx declapract.self.apply --practice git --file .gitattributes --build run',
700
+ );
701
+ expect(result.stderr).toMatchSnapshot('declapract.self.apply — no practices found');
702
+ });
703
+ });
704
+ });
705
+
706
+ given('[case4] declapract.self.apply, in a repo whose .gitattributes holds the legacy git blocks', () => {
707
+ const tempDir = genTempDir({
708
+ slug: 'skill-declapract-self-apply-legacy',
709
+ clone: './src/practices/git/.test/assets/repo-with-legacy-gitattributes',
710
+ git: true,
711
+ symlink: [
712
+ { at: 'declarations', to: './src/.test/assets/git/declarations' },
713
+ { at: 'node_modules', to: 'node_modules' },
714
+ ],
715
+ });
716
+
717
+ /**
718
+ * .what = a symlink cycle under .temp/, as leftover test repos leave in a real repo
719
+ * .why = declapract globs from its root with symlinks followed, and its walk for
720
+ * .gitignore files honors no .gitignore. an apply rooted in this repo walks the
721
+ * cycle and never ends (in this repo's own tree it ran out of memory). the skill
722
+ * applies in an isolated root, so the cycle is never walked; this clamps that
723
+ */
724
+ useBeforeAll(async () => {
725
+ await fs.mkdir(path.join(tempDir, '.temp'), { recursive: true });
726
+ await fs.symlink('..', path.join(tempDir, '.temp', 'loop'));
727
+ });
728
+
729
+ when('[t0] the git practice is applied to .gitattributes', () => {
730
+ const result = useBeforeAll(async () =>
731
+ runSkill({
732
+ skill: 'declapract.self.apply',
733
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
734
+ cwd: tempDir,
735
+ stdin: null,
736
+ env: {},
737
+ }),
738
+ );
739
+
740
+ then('it exits 0', () => {
741
+ expect(result.status).toEqual(0);
742
+ });
743
+
744
+ then('stdout opens with the banner, and closes with the diff stat of the one file', () => {
745
+ const lines = result.stdout.trimEnd().split('\n');
746
+ expect(lines[0]).toEqual('🐢 lets ride...');
747
+ expect(lines[2]).toEqual(
748
+ '🐚 declapract.self.apply --practice git --file .gitattributes --build skip',
749
+ );
750
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
751
+ expect(tail[0]).toEqual('🐢 righteous! applied');
752
+ // the outcome of this apply, apart from the diff vs HEAD, so a converged file never
753
+ // reads as one this apply rewrote
754
+ expect(tail[1]).toEqual(' ├─ .gitattributes: rewritten');
755
+ expect(tail[2]).toMatch(/^ {3}└─ vs HEAD: 1 file changed/);
756
+ });
757
+
758
+ then('the full stdout, banner to close, with the apply output passed through between', () => {
759
+ // whole, as a human reads it, less the bytes that vary per run (see asStdoutStable)
760
+ expect(result.stdout).toContain(' ✓ evaluated practice:git');
761
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot(
762
+ 'declapract.self.apply — full stdout',
763
+ );
764
+ });
765
+
766
+ then('the file now holds the tagged git sections', async () => {
767
+ const contents = await fs.readFile(
768
+ path.join(tempDir, '.gitattributes'),
769
+ 'utf-8',
770
+ );
771
+ expect(contents).toContain('# [git] exclude package locks from git diff');
772
+ });
773
+ });
774
+
775
+ when('[t1] the apply runs again, and the final git diff fails', () => {
776
+ /**
777
+ * .mock = `git diff`, via a shim on PATH that fails it and passes every other call
778
+ * .why = a `git diff --stat` of one path in a sound repo does not fail on real input
779
+ * .real = [t0] runs the real `git diff --stat`
780
+ */
781
+ const result = useBeforeAll(async () => {
782
+ const shim = await genGitShim({
783
+ dir: path.join(tempDir, '.shim-diff'),
784
+ subcommand: 'diff',
785
+ });
786
+ return runSkill({
787
+ skill: 'declapract.self.apply',
788
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
789
+ cwd: tempDir,
790
+ stdin: null,
791
+ env: { PATH: `${shim.dir}:${process.env.PATH}` },
792
+ });
793
+ });
794
+
795
+ then('a MalfunctionError names the diff, exit 1', () => {
796
+ expect(result.status).toEqual(1);
797
+ // the diff runs before the close prints, so a failed diff leaves no half tree on stdout
798
+ expect(result.stdout).not.toContain('🐢 righteous! applied');
799
+ expect(result.stdout).toContain(' ✓ evaluated practice:git');
800
+ expect(result.stderr).toContain('💥 MalfunctionError: diff failed');
801
+ // the full stderr: git's own message, then the error that points to it
802
+ expect(asMasked({ text: result.stderr, tempDir })).toMatchSnapshot(
803
+ 'declapract.self.apply — diff failed',
804
+ );
805
+ });
806
+ });
807
+
808
+ when('[t2] the converged file is committed, then the apply runs again', () => {
809
+ const result = useBeforeAll(async () => {
810
+ // commit the converged file, so HEAD and the file agree
811
+ const commit = spawnSync(
812
+ 'bash',
813
+ [
814
+ '-c',
815
+ 'git add .gitattributes && git -c user.name="Test Human" -c user.email=human@test.com commit -q -m "converge" -- .gitattributes',
816
+ ],
817
+ { cwd: tempDir, encoding: 'utf8', env: asSkillEnv({ env: {} }) },
818
+ );
819
+ if (commit.status !== 0)
820
+ throw new MalfunctionError('the commit of the converged file failed', {
821
+ stderr: commit.stderr,
822
+ });
823
+ return runSkill({
824
+ skill: 'declapract.self.apply',
825
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
826
+ cwd: tempDir,
827
+ stdin: null,
828
+ env: {},
829
+ });
830
+ });
831
+
832
+ then('it says the file is unchanged, and that it matches HEAD, exit 0', () => {
833
+ expect(result.status).toEqual(0);
834
+ const lines = result.stdout.trimEnd().split('\n');
835
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
836
+ expect(tail).toEqual([
837
+ '🐢 righteous! applied',
838
+ ' ├─ .gitattributes: unchanged, already converged',
839
+ ' └─ vs HEAD: no diff',
840
+ ]);
841
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot(
842
+ 'declapract.self.apply — applied, converged, no diff',
843
+ );
844
+ });
845
+ });
846
+ });
847
+
848
+ given('[case7] declapract.self.apply, in a repo with real declarations, asked for aught they do not hold', () => {
849
+ const tempDir = genTempDir({
850
+ slug: 'skill-declapract-self-apply-unheld',
851
+ clone: './src/practices/git/.test/assets/repo-with-legacy-gitattributes',
852
+ git: true,
853
+ symlink: [
854
+ { at: 'declarations', to: './src/.test/assets/git/declarations' },
855
+ { at: 'node_modules', to: 'node_modules' },
856
+ ],
857
+ });
858
+
859
+ when('[t0] a practice the declarations do not hold is named', () => {
860
+ then('a ConstraintError names the practice and lists the held ones, before the apply, exit 2', () => {
861
+ const result = runSkill({
862
+ skill: 'declapract.self.apply',
863
+ args: ['--practice', 'gitt', '--file', '.gitattributes', '--build', 'skip'],
864
+ cwd: tempDir,
865
+ stdin: null,
866
+ env: {},
867
+ });
868
+ expect(result.status).toEqual(2);
869
+ expect(result.stderr).toContain("✋ ConstraintError: no practice 'gitt' in practices");
870
+ expect(result.stderr).toContain(' ├─ held practices');
871
+ expect(result.stderr).toContain(' │ ├─ git\n');
872
+ expect(result.stderr).toContain(
873
+ ' └─ fix: rhx declapract.self.apply --practice git --file .gitattributes',
874
+ );
875
+ expect(result.stdout).not.toContain('🐢 righteous! applied');
876
+ expect(result.stderr).toMatchSnapshot('declapract.self.apply — unknown practice');
877
+ });
878
+ });
879
+
880
+ when('[t1] a file that no fix of the practice writes is named', () => {
881
+ const result = useBeforeAll(async () =>
882
+ runSkill({
883
+ skill: 'declapract.self.apply',
884
+ args: ['--practice', 'git', '--file', 'no-such-file.txt', '--build', 'skip'],
885
+ cwd: tempDir,
886
+ stdin: null,
887
+ env: {},
888
+ }),
889
+ );
890
+
891
+ then('it says the file was absent before and after, never "converged", exit 0', () => {
892
+ expect(result.status).toEqual(0);
893
+ const lines = result.stdout.trimEnd().split('\n');
894
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
895
+ expect(tail).toEqual([
896
+ '🐢 righteous! applied',
897
+ ' ├─ no-such-file.txt: absent before and after, no fix wrote it',
898
+ ' └─ vs HEAD: no diff, absent at HEAD too',
899
+ ]);
900
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot('declapract.self.apply — applied, absent before and after');
901
+ });
902
+ });
903
+
904
+ when('[t2] HEAD never held the file, and the apply writes it', () => {
905
+ const result = useBeforeAll(async () => {
906
+ // drop .gitattributes from HEAD, as a repo that never had one
907
+ const drop = spawnSync(
908
+ 'bash',
909
+ [
910
+ '-c',
911
+ 'git rm -q .gitattributes && git -c user.name="Test Human" -c user.email=human@test.com commit -q -m "drop"',
912
+ ],
913
+ { cwd: tempDir, encoding: 'utf8', env: asSkillEnv({ env: {} }) },
914
+ );
915
+ if (drop.status !== 0)
916
+ throw new MalfunctionError('the drop of .gitattributes from HEAD failed', {
917
+ stderr: drop.stderr,
918
+ });
919
+ return runSkill({
920
+ skill: 'declapract.self.apply',
921
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
922
+ cwd: tempDir,
923
+ stdin: null,
924
+ env: {},
925
+ });
926
+ });
927
+
928
+ then('it says the file was written, and that HEAD lacks it, never "no diff", exit 0', () => {
929
+ expect(result.status).toEqual(0);
930
+ const lines = result.stdout.trimEnd().split('\n');
931
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
932
+ expect(tail).toEqual([
933
+ '🐢 righteous! applied',
934
+ ' ├─ .gitattributes: written',
935
+ ' └─ vs HEAD: new file, absent from HEAD',
936
+ ]);
937
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot('declapract.self.apply — applied, written, absent from HEAD');
938
+ });
939
+ });
940
+
941
+ when('[t4] a --file in a subdirectory, which no fix touches', () => {
942
+ const result = useBeforeAll(async () => {
943
+ // a nested file, so the copy into the isolated root and back each make its dir
944
+ await fs.mkdir(path.join(tempDir, 'docs', 'deep'), { recursive: true });
945
+ await fs.writeFile(path.join(tempDir, 'docs', 'deep', 'keep.txt'), 'kept\n');
946
+ return runSkill({
947
+ skill: 'declapract.self.apply',
948
+ args: ['--practice', 'git', '--file', 'docs/deep/keep.txt', '--build', 'skip'],
949
+ cwd: tempDir,
950
+ stdin: null,
951
+ env: {},
952
+ });
953
+ });
954
+
955
+ then('the nested file comes back byte for byte, exit 0', async () => {
956
+ expect(result.status).toEqual(0);
957
+ const lines = result.stdout.trimEnd().split('\n');
958
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
959
+ expect(tail).toEqual([
960
+ '🐢 righteous! applied',
961
+ ' ├─ docs/deep/keep.txt: unchanged, already converged',
962
+ ' └─ vs HEAD: new file, absent from HEAD',
963
+ ]);
964
+ expect(await fs.readFile(path.join(tempDir, 'docs', 'deep', 'keep.txt'), 'utf-8')).toEqual(
965
+ 'kept\n',
966
+ );
967
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot(
968
+ 'declapract.self.apply — a nested file, untouched',
969
+ );
970
+ });
971
+ });
972
+
973
+ when('[t3] declarations: names the dir that holds the declare config, as this repo does', () => {
974
+ const result = useBeforeAll(async () => {
975
+ await fs.writeFile(
976
+ path.join(tempDir, 'declapract.use.yml'),
977
+ 'declarations: ./declarations\nuseCase: typescript-project\n',
978
+ );
979
+ return runSkill({
980
+ skill: 'declapract.self.apply',
981
+ args: ['--practice', 'git', '--file', '.gitattributes', '--build', 'skip'],
982
+ cwd: tempDir,
983
+ stdin: null,
984
+ env: {},
985
+ });
986
+ });
987
+
988
+ then('the dir form finds declapract.declare.yml within, and the apply runs, exit 0', () => {
989
+ expect(result.status).toEqual(0);
990
+ expect(result.stdout).toContain(' ✓ evaluated practice:git');
991
+ expect(result.stdout).toContain(' ├─ .gitattributes: unchanged, already converged');
992
+ });
993
+ });
994
+ });
995
+
996
+ given('[case6] declapract.self.apply, in a repo that lacks the file, with a build to run', () => {
997
+ const tempDir = genTempDir({
998
+ slug: 'skill-declapract-self-apply-fresh',
999
+ clone: './src/practices/git/.test/assets/repo-with-legacy-gitattributes',
1000
+ git: true,
1001
+ symlink: [
1002
+ { at: 'declarations', to: './src/.test/assets/git/declarations' },
1003
+ { at: 'node_modules', to: 'node_modules' },
1004
+ ],
1005
+ });
1006
+
1007
+ /**
1008
+ * .what = drops the .gitattributes, gives the repo a build that succeeds, and plants a
1009
+ * deprecated rhachet.use.ts
1010
+ * .why = a repo that lacks the file is the first apply an adopter meets (`written`); the
1011
+ * default `--build run` must succeed end to end; and the rhachet practice's
1012
+ * `deprecated-use-file` fix deletes its file, the one real path to `removed`
1013
+ */
1014
+ useBeforeAll(async () => {
1015
+ await fs.rm(path.join(tempDir, '.gitattributes'));
1016
+ await fs.writeFile(
1017
+ path.join(tempDir, 'package.json'),
1018
+ `${JSON.stringify(
1019
+ {
1020
+ name: 'test-project-gitattributes',
1021
+ version: '1.0.0',
1022
+ scripts: { build: 'echo build-ran' },
1023
+ },
1024
+ null,
1025
+ 2,
1026
+ )}\n`,
1027
+ );
1028
+ await fs.writeFile(path.join(tempDir, 'rhachet.use.ts'), 'export {};\n');
1029
+ return {};
1030
+ });
1031
+
1032
+ when('[t0] the git practice is applied with the default build', () => {
1033
+ const result = useBeforeAll(async () =>
1034
+ runSkill({
1035
+ skill: 'declapract.self.apply',
1036
+ args: ['--practice', 'git', '--file', '.gitattributes'],
1037
+ cwd: tempDir,
1038
+ stdin: null,
1039
+ env: {},
1040
+ }),
1041
+ );
1042
+
1043
+ then('the build runs, the file is written, exit 0', () => {
1044
+ expect(result.status).toEqual(0);
1045
+ expect(result.stdout).toContain(' ├─ build: run');
1046
+ expect(result.stdout).toContain('build-ran');
1047
+ const lines = result.stdout.trimEnd().split('\n');
1048
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
1049
+ expect(tail[1]).toEqual(' ├─ .gitattributes: written');
1050
+ // the close only: npm's own lines above it carry warnings that vary with the host's env
1051
+ expect(`${tail.join('\n')}\n`).toMatchSnapshot('declapract.self.apply — applied, written');
1052
+ });
1053
+
1054
+ then('the file now holds the tagged git sections', async () => {
1055
+ const contents = await fs.readFile(path.join(tempDir, '.gitattributes'), 'utf-8');
1056
+ expect(contents).toContain('# [git] exclude package locks from git diff');
1057
+ });
1058
+ });
1059
+
1060
+ when('[t1] the rhachet practice is applied to the deprecated rhachet.use.ts', () => {
1061
+ const result = useBeforeAll(async () =>
1062
+ runSkill({
1063
+ skill: 'declapract.self.apply',
1064
+ args: ['--practice', 'rhachet', '--file', 'rhachet.use.ts', '--build', 'skip'],
1065
+ cwd: tempDir,
1066
+ stdin: null,
1067
+ env: {},
1068
+ }),
1069
+ );
1070
+
1071
+ then('it says the file was removed, exit 0', () => {
1072
+ expect(result.status).toEqual(0);
1073
+ const lines = result.stdout.trimEnd().split('\n');
1074
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
1075
+ expect(tail).toEqual([
1076
+ '🐢 righteous! applied',
1077
+ ' ├─ rhachet.use.ts: removed',
1078
+ ' └─ vs HEAD: no diff, absent at HEAD too',
1079
+ ]);
1080
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot('declapract.self.apply — applied, removed');
1081
+ });
1082
+
1083
+ then('the file is gone from the repo', async () => {
1084
+ await expect(fs.access(path.join(tempDir, 'rhachet.use.ts'))).rejects.toThrow();
1085
+ });
1086
+ });
1087
+
1088
+ when('[t2] a committed rhachet.use.ts is removed by the fix', () => {
1089
+ const result = useBeforeAll(async () => {
1090
+ // plant and commit the file, so its removal shows in the diff vs HEAD
1091
+ await fs.writeFile(path.join(tempDir, 'rhachet.use.ts'), 'export {};\n');
1092
+ const commit = spawnSync(
1093
+ 'bash',
1094
+ [
1095
+ '-c',
1096
+ 'git add rhachet.use.ts && git -c user.name="Test Human" -c user.email=human@test.com commit -q -m "plant" -- rhachet.use.ts',
1097
+ ],
1098
+ { cwd: tempDir, encoding: 'utf8', env: asSkillEnv({ env: {} }) },
1099
+ );
1100
+ if (commit.status !== 0)
1101
+ throw new MalfunctionError('the commit of rhachet.use.ts failed', {
1102
+ stderr: commit.stderr,
1103
+ });
1104
+ return runSkill({
1105
+ skill: 'declapract.self.apply',
1106
+ args: ['--practice', 'rhachet', '--file', 'rhachet.use.ts', '--build', 'skip'],
1107
+ cwd: tempDir,
1108
+ stdin: null,
1109
+ env: {},
1110
+ });
1111
+ });
1112
+
1113
+ then('it says the file was removed, and the diff vs HEAD names the deletion, exit 0', () => {
1114
+ expect(result.status).toEqual(0);
1115
+ const lines = result.stdout.trimEnd().split('\n');
1116
+ const tail = lines.slice(lines.indexOf('🐢 righteous! applied'));
1117
+ expect(tail).toEqual([
1118
+ '🐢 righteous! applied',
1119
+ ' ├─ rhachet.use.ts: removed',
1120
+ ' └─ vs HEAD: 1 file changed, 1 deletion(-)',
1121
+ ]);
1122
+ expect(asStdoutStable({ stdout: result.stdout })).toMatchSnapshot(
1123
+ 'declapract.self.apply — applied, removed, tracked',
1124
+ );
1125
+ });
1126
+ });
1127
+ });
1128
+
1129
+ given('[case5] declapract.self.apply, outside any git repo', () => {
1130
+ const tempDir = genTempDir({ slug: 'skill-declapract-self-apply-norepo' });
1131
+
1132
+ when('[t0] a valid call is made', () => {
1133
+ then('a ConstraintError names the fix, not a raw git fatal, exit 2', () => {
1134
+ const result = runSkill({
1135
+ skill: 'declapract.self.apply',
1136
+ args: ['--practice', 'git', '--file', '.gitattributes'],
1137
+ cwd: tempDir,
1138
+ stdin: null,
1139
+ env: { GIT_CEILING_DIRECTORIES: path.dirname(tempDir) },
1140
+ });
1141
+ expect(result.status).toEqual(2);
1142
+ expect(result.stderr).toContain('✋ ConstraintError: not inside a git repo');
1143
+ expect(result.stderr).not.toContain('fatal:');
1144
+ expect(result.stderr).toMatchSnapshot(
1145
+ 'declapract.self.apply — outside a repo',
1146
+ );
1147
+ });
1148
+ });
1149
+ });
1150
+ });