@rt-tools/agent-kit 0.8.3 → 0.9.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 (132) hide show
  1. package/README.md +12 -0
  2. package/assets/checks/board.github.mjs +48 -1
  3. package/assets/checks/check-board.github.mjs +84 -1
  4. package/assets/checks/check-lib-layers.mjs +13 -524
  5. package/assets/checks/check-specs.mjs +11 -782
  6. package/assets/checks/check-styles.mjs +185 -15
  7. package/assets/checks/lib-boundaries.mjs +143 -0
  8. package/assets/checks/lib-common.mjs +149 -0
  9. package/assets/checks/lib-domains.mjs +205 -0
  10. package/assets/checks/lib-manifests.mjs +60 -0
  11. package/assets/checks/lib-reexports.mjs +101 -0
  12. package/assets/checks/rt-kit-checks.config.mjs +17 -0
  13. package/assets/checks/spec-anchors.mjs +297 -0
  14. package/assets/checks/spec-common.mjs +222 -0
  15. package/assets/checks/spec-contract.mjs +152 -0
  16. package/assets/checks/spec-scenarios.mjs +201 -0
  17. package/assets/defaults/project.sh +8 -0
  18. package/assets/hooks/git-guard-push-tests.sh +8 -4
  19. package/assets/hooks/skill-gate.sh +1 -1
  20. package/assets/hooks/sql-guard-parse.sh +187 -0
  21. package/assets/hooks/sql-guard-request.sh +117 -0
  22. package/assets/hooks/sql-guard-target.sh +134 -0
  23. package/assets/hooks/sql-guard-write.sh +212 -0
  24. package/assets/hooks/sql-guard.sh +26 -596
  25. package/assets/hooks/waiting-turn-guard.sh +42 -13
  26. package/assets/laws/delivery.md +7 -0
  27. package/assets/laws/work-conduct.md +9 -0
  28. package/assets/patterns/admin-lists-screen.md +25 -14
  29. package/assets/patterns/admin-nav-item.md +1 -1
  30. package/assets/patterns/component-structure-new.md +1 -1
  31. package/assets/patterns/entity-aside.md +4 -2
  32. package/assets/patterns/observability-record.md +9 -0
  33. package/assets/patterns/shared-code-new.md +2 -2
  34. package/assets/patterns/task-flow-close.md +7 -1
  35. package/assets/rules/git-workflow.azure.md +7 -0
  36. package/assets/rules/git-workflow.github.md +41 -0
  37. package/assets/rules/git-workflow.gitlab.md +7 -0
  38. package/assets/rules/lib-layers.md +4 -0
  39. package/assets/rules/lists.md +10 -10
  40. package/assets/rules/shared-code.md +1 -1
  41. package/assets/rules/task-flow.md +47 -7
  42. package/assets/rules/testing.md +31 -0
  43. package/assets/rules/typescript-conventions.md +7 -0
  44. package/assets/skills/agent-kit.md +36 -0
  45. package/assets/templates/proposal.md +21 -0
  46. package/bin/agent-kit.d.ts.map +1 -1
  47. package/bin/agent-kit.js +115 -87
  48. package/bin/agent-kit.js.map +1 -1
  49. package/index.d.ts +1 -0
  50. package/index.d.ts.map +1 -1
  51. package/index.js +1 -0
  52. package/index.js.map +1 -1
  53. package/lib/argv.d.ts.map +1 -1
  54. package/lib/argv.js +6 -4
  55. package/lib/argv.js.map +1 -1
  56. package/lib/assets.d.ts.map +1 -1
  57. package/lib/assets.js +2 -1
  58. package/lib/assets.js.map +1 -1
  59. package/lib/cargo.d.ts +20 -0
  60. package/lib/cargo.d.ts.map +1 -1
  61. package/lib/cargo.js.map +1 -1
  62. package/lib/cascade.d.ts +55 -0
  63. package/lib/cascade.d.ts.map +1 -0
  64. package/lib/cascade.js +131 -0
  65. package/lib/cascade.js.map +1 -0
  66. package/lib/catalog.d.ts +0 -75
  67. package/lib/catalog.d.ts.map +1 -1
  68. package/lib/catalog.js +44 -127
  69. package/lib/catalog.js.map +1 -1
  70. package/lib/commands.d.ts.map +1 -1
  71. package/lib/commands.js +152 -85
  72. package/lib/commands.js.map +1 -1
  73. package/lib/companion.d.ts.map +1 -1
  74. package/lib/companion.js +5 -5
  75. package/lib/companion.js.map +1 -1
  76. package/lib/config.d.ts +2 -0
  77. package/lib/config.d.ts.map +1 -1
  78. package/lib/config.js +7 -5
  79. package/lib/config.js.map +1 -1
  80. package/lib/enroll.d.ts +56 -0
  81. package/lib/enroll.d.ts.map +1 -0
  82. package/lib/enroll.js +123 -0
  83. package/lib/enroll.js.map +1 -0
  84. package/lib/freshness.d.ts.map +1 -1
  85. package/lib/freshness.js +31 -17
  86. package/lib/freshness.js.map +1 -1
  87. package/lib/hooks-map.d.ts +30 -0
  88. package/lib/hooks-map.d.ts.map +1 -1
  89. package/lib/hooks-map.js +80 -18
  90. package/lib/hooks-map.js.map +1 -1
  91. package/lib/integrity.d.ts +1 -2
  92. package/lib/integrity.d.ts.map +1 -1
  93. package/lib/integrity.js +0 -1
  94. package/lib/integrity.js.map +1 -1
  95. package/lib/observations.d.ts.map +1 -1
  96. package/lib/observations.js +25 -12
  97. package/lib/observations.js.map +1 -1
  98. package/lib/order.d.ts +10 -0
  99. package/lib/order.d.ts.map +1 -0
  100. package/lib/order.js +14 -0
  101. package/lib/order.js.map +1 -0
  102. package/lib/picker.d.ts.map +1 -1
  103. package/lib/picker.js +8 -2
  104. package/lib/picker.js.map +1 -1
  105. package/lib/plan.js +1 -1
  106. package/lib/plan.js.map +1 -1
  107. package/lib/proposals.d.ts.map +1 -1
  108. package/lib/proposals.js +25 -8
  109. package/lib/proposals.js.map +1 -1
  110. package/lib/sections.js +1 -1
  111. package/lib/sections.js.map +1 -1
  112. package/lib/ship.d.ts.map +1 -1
  113. package/lib/ship.js +9 -1
  114. package/lib/ship.js.map +1 -1
  115. package/lib/shipment.d.ts.map +1 -1
  116. package/lib/shipment.js +14 -10
  117. package/lib/shipment.js.map +1 -1
  118. package/lib/snapshot.d.ts.map +1 -1
  119. package/lib/snapshot.js +2 -1
  120. package/lib/snapshot.js.map +1 -1
  121. package/lib/stamp.js +1 -1
  122. package/lib/stamp.js.map +1 -1
  123. package/lib/sync.d.ts +12 -2
  124. package/lib/sync.d.ts.map +1 -1
  125. package/lib/sync.js +11 -10
  126. package/lib/sync.js.map +1 -1
  127. package/lib/vars.d.ts.map +1 -1
  128. package/lib/vars.js +2 -3
  129. package/lib/vars.js.map +1 -1
  130. package/package.json +1 -1
  131. package/rt-tools-agent-kit-0.9.0.tgz +0 -0
  132. package/rt-tools-agent-kit-0.8.3.tgz +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAmB,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAgB,IAAI,EAAqB,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC7G,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAwB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,KAAK,GAAsB;IAC7B,qBAAqB;IACrB,EAAE;IACF,mEAAmE;IACnE,8DAA8D;IAC9D,6DAA6D;IAC7D,+EAA+E;IAC/E,qEAAqE;IACrE,yFAAyF;IACzF,wDAAwD;IACxD,gFAAgF;IAChF,8FAA8F;IAC9F,uEAAuE;IACvE,wEAAwE;IACxE,EAAE;IACF,gEAAgE;IAChE,EAAE;IACF,2BAA2B;IAC3B,EAAE;IACF,6DAA6D;IAC7D,yEAAyE;IACzE,+DAA+D;IAC/D,EAAE;IACF,8EAA8E;IAC9E,EAAE;IACF,gFAAgF;IAChF,oEAAoE;CACvE,CAAC;AAEF;;;GAGG;AACH,MAAM,aAAa,GAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,aAAa,GAAsB;IACrC,8CAA8C;IAC9C,uEAAuE;IACvE,oEAAoE;CACvE,CAAC;AAEF;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY;IAC/B,MAAM,GAAG,GAAW,eAAe,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAsC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAG7G,CAAC;IAEF,OAAO;QACH,IAAI;QACJ,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC;QAC9B,yFAAyF;QACzF,uDAAuD;QACvD,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC;KACxC,CAAC;AACN,CAAC;AAED,8FAA8F;AAC9F,SAAS,QAAQ,CAAC,IAAY;IAC1B,IAAI,CAAC;QACD,OAAO,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;YACpE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACtC,CAAC,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,IAAuB,EAAE,IAAY,EAAE,QAAgB;IACrE,MAAM,KAAK,GAAW,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC,OAAO,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtE,CAAC;AAED,MAAM,SAAS,GAAmD,CAAC,KAAc,EAA8B,EAAE,CAC7G,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AAEnE;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAAC,IAAuB,EAAE,SAAiB;IAClE,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAA+B,WAAW,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,MAAM,GAAW,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEpD,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,KAAK,GAAa,MAAM;aACzB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1C,MAAM,CAAC,OAAO,CAAC,CAAC;QACrB,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAElE,OAAO,OAAO,CAAC,MAAM;YACjB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,8BAA8B,CAAC,EAAE;YAC7G,CAAC,CAAC,GAAG,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACZ,OAAO;YACH,IAAI,EAAE,CAAC;YACP,KAAK,EAAE;gBACH,uCAAuC;gBACvC,mEAAmE;gBACnE,oCAAoC;aACvC;SACJ,CAAC;IACN,CAAC;IAED,MAAM,OAAO,GAAuB,OAAO;SACtC,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;SAClE,GAAG,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAExG,OAAO,GAAG,CAAC,OAAO,EAAE,wCAAwC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,WAAW,CAAC,IAAuB,EAAE,SAAiB;IACjE,MAAM,IAAI,GAAqB,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,MAAM,GAAW,QAAQ,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5D,MAAM,KAAK,GAA+B,CAAC,KAAa,EAAW,EAAE,CACjE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAqB,EAAW,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QAElF,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjB,OAAO;oBACH,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE;wBACH,uBAAuB,IAAI,CAAC,IAAI,qBAAqB,MAAM,EAAE;wBAC7D,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAqB,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;qBAC1F;iBACJ,CAAC;YACN,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;YAC3B,SAAS;QACb,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACjD,SAAS;QACb,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACZ,OAAO;gBACH,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE;oBACH,uCAAuC;oBACvC,yBAAyB,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAqB,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAChI;aACJ,CAAC;QACN,CAAC;QAED,MAAM,MAAM,GAAkB,MAAM,MAAM,CACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAqB,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,EACrH,IAAI,CAAC,QAAQ,CAChB,CAAC;QACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAuB;IAC9C,MAAM,OAAO,GAAW,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAiB,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1F,QAAQ,OAAO,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,CAAC;YACV,MAAM,SAAS,GAAiD,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;YACxG,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBACvB,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,mCAAmC,CAAC,EAAE,CAAC;YACrE,CAAC;YAED,MAAM,QAAQ,GAAsD,MAAM,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3G,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtB,OAAO,QAAQ,CAAC;YACpB,CAAC;YAED,OAAO,QAAQ,KAAK,IAAI;gBACpB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,mCAAmC,CAAC,EAAE;gBAC3D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,MAAM;YACP,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM;YACP,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/C,KAAK,OAAO,CAAC,CAAC,CAAC;YACX,MAAM,MAAM,GAAW,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;YAE5D,OAAO,KAAK,CAAC,GAAG,EAAE;gBACd,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY;gBAC/E,6EAA6E;gBAC7E,gFAAgF;gBAChF,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC5C,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;aAChC,CAAC,CAAC;QACP,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,oFAAoF;YACpF,kFAAkF;YAClF,6EAA6E;YAC7E,2EAA2E;YAC3E,MAAM,OAAO,GAAsB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YAChF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACjB,OAAO;oBACH,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,CAAC,oCAAoC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC;iBAC1F,CAAC;YACN,CAAC;YAED,OAAO,OAAO,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAClC,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAC1B,8EAA8E;gBAC9E,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;aAC/C,CAAC,CAAC;QACP,CAAC;QACD,KAAK,QAAQ;YACT,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,KAAK,OAAO;YACR,OAAO,KAAK,CACR,GAAG,EACH,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAa,EAAW,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CACtH,CAAC;QACN;YACI,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,wBAAwB,OAAO,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IACtH,CAAC;AACL,CAAC;AAED,MAAM,OAAO,GAAsB,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAC/B,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\n return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n } catch {\n return '';\n }\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const known: (value: string) => boolean = (value: string): boolean =>\n axis.options.some((option: IOptionOfAxis): boolean => option.value === value);\n\n if (spoken) {\n if (!known(spoken)) {\n return {\n code: 1,\n lines: [\n `такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`,\n `есть: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n chosen[axis.name] = spoken;\n continue;\n }\n\n if (argv.includes('--all')) {\n chosen[axis.name] = axis.options[0]?.value ?? '';\n continue;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n `назови вид флагом \\`--${axis.name} <вид>\\`: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n\n const answer: string | null = await askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n if (answer === null) {\n return null;\n }\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n\n switch (command) {\n case 'init': {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n }\n case 'list':\n return list(env);\n case 'sync':\n return sync(env, argv.includes('--check'));\n case 'stats': {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n }\n case 'propose': {\n // Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый\n // довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в\n // приём всё накопленное, и по выводу это не отличалось от «команда ничего не\n // сделала». Прочие команды такого разбора не знают — их действие обратимо.\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n }\n case 'doctor':\n return doctor(env);\n case 'adopt':\n return adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n );\n default:\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
1
+ {"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { CONFIG_PATH, IConfig, readConfig } from '../lib/config.js';\nimport { enroll, httpEnroll } from '../lib/enroll.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose, treeSlugOf } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n ' enroll --code <код> завести дерево по приглашению владельца и положить его токен',\n ' enroll --force перезаписать уже лежащий токен намеренно',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\n // eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым\n return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n } catch {\n return '';\n }\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantOfAxis(axis: IAxis, argv: readonly string[]): Promise<string | null | IOutcomeOfCommand> {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const values: readonly string[] = axis.options.map((option: IOptionOfAxis): string => option.value);\n\n if (spoken) {\n return values.includes(spoken)\n ? spoken\n : {\n code: 1,\n lines: [`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`, `есть: ${values.join(', ')}`],\n };\n }\n\n if (argv.includes('--all')) {\n return axis.options[0]?.value ?? '';\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: ['спросить некого: запуск без терминала', `назови вид флагом \\`--${axis.name} <вид>\\`: ${values.join(', ')}`],\n };\n }\n\n return askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n}\n\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const answer: string | null | IOutcomeOfCommand = await variantOfAxis(axis, argv);\n\n if (isOutcome(answer)) {\n return answer;\n }\n\n if (answer === null) {\n return null;\n }\n\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\n/** Заведение настройки: выбор ресурсов и видов, брошенный выбор ничего не пишет. */\nasync function runInit(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n}\n\n/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\nfunction runStats(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n}\n\n/**\n * Отправка накопленного.\n *\n * Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый довод её\n * кончает, а не пропускается молча: вызов ради списка режимов отправил в приём всё накопленное, и\n * по выводу это не отличалось от «команда ничего не сделала». Прочие команды такого разбора не\n * знают — их действие обратимо.\n */\nasync function runPropose(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n}\n\n/** Приписка дерева к приёмнику по коду приглашения. */\nasync function runEnroll(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const config: IConfig | null = readConfig(env.root);\n\n if (!config) {\n return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \\`init\\``] };\n }\n\n return enroll({\n root: env.root,\n intake: config.intake,\n code: optionOf(argv, '--code', ''),\n tree: treeSlugOf(remoteOf(env.root), config.tree),\n token: config.token,\n force: argv.includes('--force'),\n call: httpEnroll,\n });\n}\n\n/** Ветка команды: окружение и доводы строки запуска на входе, вывод и код возврата на выходе. */\ntype TCommandRun = (env: IEnvironment, argv: readonly string[]) => IOutcomeOfCommand | Promise<IOutcomeOfCommand>;\n\n/** Что делает каждая команда строки запуска. Ключ — слово, которым её зовут. */\nconst COMMANDS: Readonly<Record<string, TCommandRun>> = {\n init: runInit,\n list: (env: IEnvironment): IOutcomeOfCommand => list(env),\n sync: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand => sync(env, argv.includes('--check')),\n stats: runStats,\n propose: runPropose,\n enroll: runEnroll,\n doctor: (env: IEnvironment): IOutcomeOfCommand => doctor(env),\n adopt: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand =>\n adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n ),\n};\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n const run: TCommandRun | undefined = Object.hasOwn(COMMANDS, command) ? COMMANDS[command] : undefined;\n\n if (!run) {\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n\n return run(env, argv);\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './lib/assets.js';
2
2
  export * from './lib/cargo.js';
3
+ export * from './lib/cascade.js';
3
4
  export * from './lib/catalog.js';
4
5
  export * from './lib/commands.js';
5
6
  export * from './lib/config.js';
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './lib/assets.js';
2
2
  export * from './lib/cargo.js';
3
+ export * from './lib/cascade.js';
3
4
  export * from './lib/catalog.js';
4
5
  export * from './lib/commands.js';
5
6
  export * from './lib/config.js';
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/cargo.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/cargo.js';\nexport * from './lib/cascade.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
package/lib/argv.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CA6BnG"}
1
+ {"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CA8BnG"}
package/lib/argv.js CHANGED
@@ -31,13 +31,15 @@ export function unknownFlagsIn(argv, known) {
31
31
  const name = spoken.split('=')[0];
32
32
  if (!names.has(name)) {
33
33
  unknown.push(name);
34
- continue;
35
34
  }
36
- // Значение через пробел пропускается вместе со своим доводом: без этого путь, начатый
37
- // с дефиса, читался бы как ещё один незнакомый довод.
38
- if (withValue.has(name) && !spoken.includes('=')) {
35
+ else if (withValue.has(name) && !spoken.includes('=')) {
36
+ // Значение через пробел пропускается вместе со своим доводом: без этого путь, начатый
37
+ // с дефиса, читался бы как ещё один незнакомый довод.
39
38
  index += 1;
40
39
  }
40
+ else {
41
+ // Знакомый довод, у которого значения нет или оно написано через равенство
42
+ }
41
43
  }
42
44
  return unknown;
43
45
  }
package/lib/argv.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"argv.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+FAA+F;AAC/F,MAAM,IAAI,GAAW,IAAI,CAAC;AAE1B,gFAAgF;AAChF,MAAM,WAAW,GAAW,KAAK,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAuB,EAAE,KAAwB;IAC5E,MAAM,SAAS,GAAwB,IAAI,GAAG,CAC1C,KAAK;SACA,MAAM,CAAC,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CACzE,CAAC;IACF,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,IAAI,KAAK,GAAW,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,SAAS;QACb,CAAC;QAED,MAAM,IAAI,GAAW,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,SAAS;QACb,CAAC;QAED,sFAAsF;QACtF,sDAAsD;QACtD,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,KAAK,IAAI,CAAC,CAAC;QACf,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["/**\n * Разбор доводов командной строки.\n *\n * Команда, которая молча пропускает незнакомый довод, отвечает одинаково на «довод лишний» и на\n * «команда ничего не сделала». Там, где единственное действие обратимо, разница стоит повторного\n * запуска; там, где оно необратимо и уходит наружу, — стоит отправленного груза: вызов с\n * доводом справки, сделанный ради списка режимов, отправил в приём всё накопленное.\n */\n\n/** Довод — то, что начинается с дефиса. Всё остальное команда читает как значение или путь. */\nconst FLAG: RegExp = /^-/;\n\n/** Пометка довода, за которым идёт значение: `--root <>` против `--dry-run`. */\nconst TAKES_VALUE: string = ' <>';\n\n/**\n * Доводы вызова, которых команда не знает.\n *\n * Значение, стоящее за доводом с параметром, доводом не считается: `--root /путь` — это один\n * довод и его значение, а не два незнакомых. Набор известных перечисляет и те доводы, что\n * значение принимают, и те, что нет: у пустого набора незнакомо всё, начинающееся с дефиса.\n */\nexport function unknownFlagsIn(argv: readonly string[], known: readonly string[]): readonly string[] {\n const withValue: ReadonlySet<string> = new Set(\n known\n .filter((flag: string): boolean => flag.endsWith(TAKES_VALUE))\n .map((flag: string): string => flag.slice(0, -TAKES_VALUE.length))\n );\n const names: ReadonlySet<string> = new Set(known.map((flag: string): string => flag.replace(TAKES_VALUE, '')));\n const unknown: string[] = [];\n\n for (let index: number = 0; index < argv.length; index += 1) {\n const spoken: string = argv[index];\n if (!FLAG.test(spoken)) {\n continue;\n }\n\n const name: string = spoken.split('=')[0];\n if (!names.has(name)) {\n unknown.push(name);\n continue;\n }\n\n // Значение через пробел пропускается вместе со своим доводом: без этого путь, начатый\n // с дефиса, читался бы как ещё один незнакомый довод.\n if (withValue.has(name) && !spoken.includes('=')) {\n index += 1;\n }\n }\n\n return unknown;\n}\n"]}
1
+ {"version":3,"file":"argv.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+FAA+F;AAC/F,MAAM,IAAI,GAAW,IAAI,CAAC;AAE1B,gFAAgF;AAChF,MAAM,WAAW,GAAW,KAAK,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAuB,EAAE,KAAwB;IAC5E,MAAM,SAAS,GAAwB,IAAI,GAAG,CAC1C,KAAK;SACA,MAAM,CAAC,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CACzE,CAAC;IACF,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,IAAI,KAAK,GAAW,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,SAAS;QACb,CAAC;QAED,MAAM,IAAI,GAAW,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;aAAM,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACtD,sFAAsF;YACtF,sDAAsD;YACtD,KAAK,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACJ,2EAA2E;QAC/E,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["/**\n * Разбор доводов командной строки.\n *\n * Команда, которая молча пропускает незнакомый довод, отвечает одинаково на «довод лишний» и на\n * «команда ничего не сделала». Там, где единственное действие обратимо, разница стоит повторного\n * запуска; там, где оно необратимо и уходит наружу, — стоит отправленного груза: вызов с\n * доводом справки, сделанный ради списка режимов, отправил в приём всё накопленное.\n */\n\n/** Довод — то, что начинается с дефиса. Всё остальное команда читает как значение или путь. */\nconst FLAG: RegExp = /^-/;\n\n/** Пометка довода, за которым идёт значение: `--root <>` против `--dry-run`. */\nconst TAKES_VALUE: string = ' <>';\n\n/**\n * Доводы вызова, которых команда не знает.\n *\n * Значение, стоящее за доводом с параметром, доводом не считается: `--root /путь` — это один\n * довод и его значение, а не два незнакомых. Набор известных перечисляет и те доводы, что\n * значение принимают, и те, что нет: у пустого набора незнакомо всё, начинающееся с дефиса.\n */\nexport function unknownFlagsIn(argv: readonly string[], known: readonly string[]): readonly string[] {\n const withValue: ReadonlySet<string> = new Set(\n known\n .filter((flag: string): boolean => flag.endsWith(TAKES_VALUE))\n .map((flag: string): string => flag.slice(0, -TAKES_VALUE.length))\n );\n const names: ReadonlySet<string> = new Set(known.map((flag: string): string => flag.replace(TAKES_VALUE, '')));\n const unknown: string[] = [];\n\n for (let index: number = 0; index < argv.length; index += 1) {\n const spoken: string = argv[index];\n\n if (!FLAG.test(spoken)) {\n continue;\n }\n\n const name: string = spoken.split('=')[0];\n\n if (!names.has(name)) {\n unknown.push(name);\n } else if (withValue.has(name) && !spoken.includes('=')) {\n // Значение через пробел пропускается вместе со своим доводом: без этого путь, начатый\n // с дефиса, читался бы как ещё один незнакомый довод.\n index += 1;\n } else {\n // Знакомый довод, у которого значения нет или оно написано через равенство\n }\n }\n\n return unknown;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,eAAe,EAAe,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,OAAO,EAA2B,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,MAAM;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAUD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAI9H;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CASnF"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,eAAe,EAAe,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,EAA2B,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,MAAM;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAUD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAI9H;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CASnF"}
package/lib/assets.js CHANGED
@@ -6,7 +6,8 @@
6
6
  * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.
7
7
  */
8
8
  import { join } from 'node:path';
9
- import { chosenEntries, readCatalog } from './catalog.js';
9
+ import { chosenEntries } from './cascade.js';
10
+ import { readCatalog } from './catalog.js';
10
11
  import { SKILL_FILE, SKILL_KINDS } from './config.js';
11
12
  /** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */
12
13
  const extensionOf = (id) => {
package/lib/assets.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAW,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAetE,kFAAkF;AAClF,MAAM,WAAW,GAA2B,CAAC,EAAU,EAAU,EAAE;IAC/D,MAAM,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoD,EAAE,MAAuC;IAClH,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,SAAiB;IAC5D,OAAO,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAU,EAAE,CAAC,CAAC;QAC1F,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC/B,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["/**\n * Что из везомого пакетом взял этот проект и куда оно ложится.\n *\n * Полный набор читает `catalog.ts`, здесь из него остаётся выбранное. Разделено потому, что\n * выбирать приходится раньше, чем раскладывать: `init` спрашивает, какие законы взять, а `list`\n * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.\n */\nimport { join } from 'node:path';\n\nimport { chosenEntries, IEntryOfCatalog, readCatalog } from './catalog.js';\nimport { IConfig, SKILL_FILE, SKILL_KINDS, TKind } from './config.js';\n\nexport interface IAsset {\n /** Идентификатор: `laws/application/money.md`. Он же путь надстройки и ключ в `only` и `skip`. */\n readonly id: string;\n readonly kind: TKind;\n /** Имя без рода, вида и расширения: `delivery`. У скила — имя каталога, которым его зовут. */\n readonly name: string;\n readonly text: string;\n /** Путь в дереве проекта, куда ресурс ложится. */\n readonly target: string;\n /** Запускается ли файл сам по себе: гарда без права на запуск не существует. */\n readonly executable: boolean;\n}\n\n/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */\nconst extensionOf: (id: string) => string = (id: string): string => {\n const dot: number = id.lastIndexOf('.');\n const slash: number = id.lastIndexOf('/');\n\n return dot > slash ? id.slice(dot) : '';\n};\n\n/**\n * Куда ложится ресурс. Скил читается агентом как `<имя>/SKILL.md`, и другого имени у него быть\n * не может: файл, названный по ресурсу, агент не найдёт вовсе. Остальные роды ложатся файлом —\n * по имени, а не по идентификатору: слой законов из идентификатора в путь переезжает, а вид\n * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом\n * дереве нет, а агенту, который правило читает, различать их незачем.\n */\nexport function targetOf(entry: Pick<IEntryOfCatalog, 'id' | 'kind' | 'name'>, layout: Readonly<Record<TKind, string>>): string {\n return SKILL_KINDS.includes(entry.kind)\n ? join(layout[entry.kind], entry.name, SKILL_FILE)\n : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);\n}\n\nexport function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[] {\n return chosenEntries(readCatalog(assetsDir), config).map((entry: IEntryOfCatalog): IAsset => ({\n id: entry.id,\n kind: entry.kind,\n name: entry.name,\n text: entry.text,\n target: targetOf(entry, config.layout),\n executable: entry.executable,\n }));\n}\n"]}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAW,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAetE,kFAAkF;AAClF,MAAM,WAAW,GAA2B,CAAC,EAAU,EAAU,EAAE;IAC/D,MAAM,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoD,EAAE,MAAuC;IAClH,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,SAAiB;IAC5D,OAAO,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAU,EAAE,CAAC,CAAC;QAC1F,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC/B,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["/**\n * Что из везомого пакетом взял этот проект и куда оно ложится.\n *\n * Полный набор читает `catalog.ts`, здесь из него остаётся выбранное. Разделено потому, что\n * выбирать приходится раньше, чем раскладывать: `init` спрашивает, какие законы взять, а `list`\n * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.\n */\nimport { join } from 'node:path';\n\nimport { chosenEntries } from './cascade.js';\nimport { IEntryOfCatalog, readCatalog } from './catalog.js';\nimport { IConfig, SKILL_FILE, SKILL_KINDS, TKind } from './config.js';\n\nexport interface IAsset {\n /** Идентификатор: `laws/application/money.md`. Он же путь надстройки и ключ в `only` и `skip`. */\n readonly id: string;\n readonly kind: TKind;\n /** Имя без рода, вида и расширения: `delivery`. У скила — имя каталога, которым его зовут. */\n readonly name: string;\n readonly text: string;\n /** Путь в дереве проекта, куда ресурс ложится. */\n readonly target: string;\n /** Запускается ли файл сам по себе: гарда без права на запуск не существует. */\n readonly executable: boolean;\n}\n\n/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */\nconst extensionOf: (id: string) => string = (id: string): string => {\n const dot: number = id.lastIndexOf('.');\n const slash: number = id.lastIndexOf('/');\n\n return dot > slash ? id.slice(dot) : '';\n};\n\n/**\n * Куда ложится ресурс. Скил читается агентом как `<имя>/SKILL.md`, и другого имени у него быть\n * не может: файл, названный по ресурсу, агент не найдёт вовсе. Остальные роды ложатся файлом —\n * по имени, а не по идентификатору: слой законов из идентификатора в путь переезжает, а вид\n * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом\n * дереве нет, а агенту, который правило читает, различать их незачем.\n */\nexport function targetOf(entry: Pick<IEntryOfCatalog, 'id' | 'kind' | 'name'>, layout: Readonly<Record<TKind, string>>): string {\n return SKILL_KINDS.includes(entry.kind)\n ? join(layout[entry.kind], entry.name, SKILL_FILE)\n : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);\n}\n\nexport function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[] {\n return chosenEntries(readCatalog(assetsDir), config).map((entry: IEntryOfCatalog): IAsset => ({\n id: entry.id,\n kind: entry.kind,\n name: entry.name,\n text: entry.text,\n target: targetOf(entry, config.layout),\n executable: entry.executable,\n }));\n}\n"]}
package/lib/cargo.d.ts CHANGED
@@ -68,6 +68,26 @@ export interface IPostmortemItem {
68
68
  export interface IPostmortemsCargo extends ICargoHead {
69
69
  readonly items: readonly IPostmortemItem[];
70
70
  }
71
+ /**
72
+ * Обращение дерева за токеном.
73
+ *
74
+ * Имени дерева в нём нет вовсе: его приём берёт из приглашения — принятое из обращения, оно
75
+ * позволило бы назваться чужим именем тому, кто добыл код.
76
+ */
77
+ export interface IEnrollCargo {
78
+ readonly schema: string;
79
+ /** Признак дерева: его дерево считает у себя, а приём только сверяет. */
80
+ readonly tree: string;
81
+ /** Код приглашения, выданный владельцем. Уходит один раз и в журнал не попадает. */
82
+ readonly code: string;
83
+ }
84
+ /** Ответ приёма на годное обращение: токен уходит дереву единственным этим ответом. */
85
+ export interface IEnrollGranted {
86
+ readonly tree: string;
87
+ /** Имя дерева, как его назвал владелец в приглашении. */
88
+ readonly name: string;
89
+ readonly token: string;
90
+ }
71
91
  /** Ответ приёма на принятый груз: дерево и месяц печатаются владельцу отправляющей стороной. */
72
92
  export interface IIntakeAccepted {
73
93
  readonly tree: string;
@@ -1 +1 @@
1
- {"version":3,"file":"cargo.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yFAAyF;AACzF,eAAO,MAAM,oBAAoB,EAAE,MAAY,CAAC;AAEhD,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,EAAE,MAAuB,CAAC;AAExD,kGAAkG;AAClG,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1D,wDAAwD;AACxD,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;CAChC;AAED,wEAAwE;AACxE,MAAM,WAAW,UAAU;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C;AAED,gGAAgG;AAChG,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAC3B"}
1
+ {"version":3,"file":"cargo.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo.ts"],"names":[],"mappings":"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"}
package/lib/cargo.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yFAAyF;AACzF,MAAM,CAAC,MAAM,oBAAoB,GAAW,GAAG,CAAC;AAEhD,uDAAuD;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAW,cAAc,CAAC","sourcesContent":["/**\n * Форма груза: то, что уезжает с дерева в приём.\n *\n * Место объявления одно на обе стороны — правило договорённости приёма. Объявляет его\n * отправляющая сторона: пакет уходит в реестр, и импорт внутренней либы приёма уехал бы в\n * описания его типов и сломал бы установку. Приём берёт форму отсюда, а своей копии не заводит:\n * из двух копий компилируется только одна, а расходятся они молча.\n *\n * Файл держится без единого импорта намеренно: его читает и приём, и всякий, кто ставит пакет,\n * — а всё остальное в пакете написано под запуск из строки запуска.\n */\n\n/** Версия формата запроса приёма. Меняется, когда меняется состав полей самого груза. */\nexport const CARGO_SCHEMA_VERSION: string = '1';\n\n/** Заголовок, которым дерево представляется приёму. */\nexport const TREE_TOKEN_HEADER: string = 'x-tree-token';\n\n/** Род правки надстройки: дерево замещает раздел пакета, дописывает свой или снимает пакетный. */\nexport type TOverrideKind = 'replace' | 'append' | 'drop';\n\n/** Сколько раз что-то встретилось за отрезок сводки. */\nexport interface ICargoCount {\n readonly name: string;\n readonly count: number;\n}\n\n/**\n * Одна правка надстройки. У замещения и снятия заголовок раздела пакетный и общий у всех, потому\n * называется; у своего раздела заголовок придумало дерево — он не уезжает вовсе.\n */\nexport interface ICargoOverride {\n readonly resource: string;\n readonly section: string | null;\n readonly kind: TOverrideKind;\n}\n\n/** Общее у всякого груза: чем разбирать и от какого дерева приехало. */\nexport interface ICargoHead {\n readonly schema: string;\n readonly tree: string;\n}\n\n/** Сводка наблюдений дерева за отрезок дней вместе со снимком надстроек. */\nexport interface ISummaryCargo extends ICargoHead {\n readonly days: number;\n readonly sessions: number;\n readonly loads: readonly ICargoCount[];\n readonly denials: readonly ICargoCount[];\n readonly kinds: readonly ICargoCount[];\n readonly guards: readonly ICargoCount[];\n /** Ресурсы, разложенные в дерево и не загруженные за отрезок ни разу. */\n readonly unused: readonly string[];\n /** Ресурсы пакета, которых дерево не разложило вовсе. */\n readonly unpicked: readonly string[];\n readonly overrides: readonly ICargoOverride[];\n /** Версии схемы строк наблюдения, встреченные за отрезок. Приём их не судит. */\n readonly versions: readonly string[];\n readonly total: number;\n}\n\n/** Одно предложение по слою правил. */\nexport interface IProposalItem {\n readonly text: string;\n readonly address: string;\n readonly resource: string;\n}\n\nexport interface IProposalsCargo extends ICargoHead {\n readonly items: readonly IProposalItem[];\n}\n\n/** Один разбор происшествия: имя файла на дереве и текст целиком. */\nexport interface IPostmortemItem {\n readonly file: string;\n readonly text: string;\n}\n\nexport interface IPostmortemsCargo extends ICargoHead {\n readonly items: readonly IPostmortemItem[];\n}\n\n/** Ответ приёма на принятый груз: дерево и месяц печатаются владельцу отправляющей стороной. */\nexport interface IIntakeAccepted {\n readonly tree: string;\n /** Месяц записи в форме `2026-08`, по всемирному времени приёма. */\n readonly month: string;\n /** Запись месяца заведена этим запросом, а не обновлена. */\n readonly created: boolean;\n /**\n * Сколько записей легло этим запросом и сколько приехало повторно.\n *\n * Есть только у предложений: у них приём отбирает уже приехавшее по признаку, и без этих\n * двух чисел отправитель печатает «уехало» в том числе тогда, когда нового не уехало ничего.\n * Приём прежней редакции их не присылает вовсе — отсюда необязательность.\n */\n readonly added?: number;\n readonly known?: number;\n}\n"]}
1
+ {"version":3,"file":"cargo.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,yFAAyF;AACzF,MAAM,CAAC,MAAM,oBAAoB,GAAW,GAAG,CAAC;AAEhD,uDAAuD;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAW,cAAc,CAAC","sourcesContent":["/**\n * Форма груза: то, что уезжает с дерева в приём.\n *\n * Место объявления одно на обе стороны — правило договорённости приёма. Объявляет его\n * отправляющая сторона: пакет уходит в реестр, и импорт внутренней либы приёма уехал бы в\n * описания его типов и сломал бы установку. Приём берёт форму отсюда, а своей копии не заводит:\n * из двух копий компилируется только одна, а расходятся они молча.\n *\n * Файл держится без единого импорта намеренно: его читает и приём, и всякий, кто ставит пакет,\n * — а всё остальное в пакете написано под запуск из строки запуска.\n */\n\n/** Версия формата запроса приёма. Меняется, когда меняется состав полей самого груза. */\nexport const CARGO_SCHEMA_VERSION: string = '1';\n\n/** Заголовок, которым дерево представляется приёму. */\nexport const TREE_TOKEN_HEADER: string = 'x-tree-token';\n\n/** Род правки надстройки: дерево замещает раздел пакета, дописывает свой или снимает пакетный. */\nexport type TOverrideKind = 'replace' | 'append' | 'drop';\n\n/** Сколько раз что-то встретилось за отрезок сводки. */\nexport interface ICargoCount {\n readonly name: string;\n readonly count: number;\n}\n\n/**\n * Одна правка надстройки. У замещения и снятия заголовок раздела пакетный и общий у всех, потому\n * называется; у своего раздела заголовок придумало дерево — он не уезжает вовсе.\n */\nexport interface ICargoOverride {\n readonly resource: string;\n readonly section: string | null;\n readonly kind: TOverrideKind;\n}\n\n/** Общее у всякого груза: чем разбирать и от какого дерева приехало. */\nexport interface ICargoHead {\n readonly schema: string;\n readonly tree: string;\n}\n\n/** Сводка наблюдений дерева за отрезок дней вместе со снимком надстроек. */\nexport interface ISummaryCargo extends ICargoHead {\n readonly days: number;\n readonly sessions: number;\n readonly loads: readonly ICargoCount[];\n readonly denials: readonly ICargoCount[];\n readonly kinds: readonly ICargoCount[];\n readonly guards: readonly ICargoCount[];\n /** Ресурсы, разложенные в дерево и не загруженные за отрезок ни разу. */\n readonly unused: readonly string[];\n /** Ресурсы пакета, которых дерево не разложило вовсе. */\n readonly unpicked: readonly string[];\n readonly overrides: readonly ICargoOverride[];\n /** Версии схемы строк наблюдения, встреченные за отрезок. Приём их не судит. */\n readonly versions: readonly string[];\n readonly total: number;\n}\n\n/** Одно предложение по слою правил. */\nexport interface IProposalItem {\n readonly text: string;\n readonly address: string;\n readonly resource: string;\n}\n\nexport interface IProposalsCargo extends ICargoHead {\n readonly items: readonly IProposalItem[];\n}\n\n/** Один разбор происшествия: имя файла на дереве и текст целиком. */\nexport interface IPostmortemItem {\n readonly file: string;\n readonly text: string;\n}\n\nexport interface IPostmortemsCargo extends ICargoHead {\n readonly items: readonly IPostmortemItem[];\n}\n\n/**\n * Обращение дерева за токеном.\n *\n * Имени дерева в нём нет вовсе: его приём берёт из приглашения — принятое из обращения, оно\n * позволило бы назваться чужим именем тому, кто добыл код.\n */\nexport interface IEnrollCargo {\n readonly schema: string;\n /** Признак дерева: его дерево считает у себя, а приём только сверяет. */\n readonly tree: string;\n /** Код приглашения, выданный владельцем. Уходит один раз и в журнал не попадает. */\n readonly code: string;\n}\n\n/** Ответ приёма на годное обращение: токен уходит дереву единственным этим ответом. */\nexport interface IEnrollGranted {\n readonly tree: string;\n /** Имя дерева, как его назвал владелец в приглашении. */\n readonly name: string;\n readonly token: string;\n}\n\n/** Ответ приёма на принятый груз: дерево и месяц печатаются владельцу отправляющей стороной. */\nexport interface IIntakeAccepted {\n readonly tree: string;\n /** Месяц записи в форме `2026-08`, по всемирному времени приёма. */\n readonly month: string;\n /** Запись месяца заведена этим запросом, а не обновлена. */\n readonly created: boolean;\n /**\n * Сколько записей легло этим запросом и сколько приехало повторно.\n *\n * Есть только у предложений: у них приём отбирает уже приехавшее по признаку, и без этих\n * двух чисел отправитель печатает «уехало» в том числе тогда, когда нового не уехало ничего.\n * Приём прежней редакции их не присылает вовсе — отсюда необязательность.\n */\n readonly added?: number;\n readonly known?: number;\n}\n"]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Каскад отказа: ресурс, чей родитель не поехал в дерево, снимается вслед за ним.
3
+ *
4
+ * Отдельным модулем от каталога: каталог знает, какие ресурсы бывают, а каскад — как они связаны
5
+ * родством. Связь родителя с потомком читают двое — сверка связности пакета и сама раскладка, —
6
+ * и оба берут её отсюда.
7
+ */
8
+ import { IEntryOfCatalog, ISelection } from './catalog.js';
9
+ /** Ресурс, снятый вслед за отвергнутым родителем. */
10
+ export interface ICascadeCut {
11
+ readonly id: string;
12
+ /** Ближайший родитель: у правила — его закон, у паттерна — его правило. */
13
+ readonly parent: string;
14
+ /**
15
+ * Отвергнутый корень цепочки — то, что дерево действительно отвергло или не выбрало.
16
+ * Ближайшего родителя мало: паттерн уходит вслед за правилом, которого в отказе нет, и
17
+ * искать его там читатель пойдёт зря.
18
+ */
19
+ readonly root: string;
20
+ }
21
+ /**
22
+ * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.
23
+ *
24
+ * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с
25
+ * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по
26
+ * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями
27
+ * переписывал бы шапки всех правил при нём.
28
+ *
29
+ * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит
30
+ * сверка связности пакета, до всякой раскладки в дереве.
31
+ */
32
+ export declare function cascadeCuts(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[];
33
+ /**
34
+ * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.
35
+ *
36
+ * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое
37
+ * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,
38
+ * кто ничего не просил, здесь — тот, кто попросил прямо.
39
+ */
40
+ export declare function namedButCut(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[];
41
+ /**
42
+ * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.
43
+ *
44
+ * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —
45
+ * один ресурс: связь родителя с потомком по одной записи не видна.
46
+ */
47
+ export declare function chosenEntries(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IEntryOfCatalog[];
48
+ /** Строка отказа, которая ничего не снимает. */
49
+ export interface IIdleSkip {
50
+ readonly id: string;
51
+ /** Чем названное ею уже снято: имя отвергнутого родителя, либо пусто — такого ресурса нет. */
52
+ readonly by: string;
53
+ }
54
+ export declare function idleSkips(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IIdleSkip[];
55
+ //# sourceMappingURL=cascade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,eAAe,EAAY,UAAU,EAAE,MAAM,cAAc,CAAC;AAIpF,qDAAqD;AACrD,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAgED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,WAAW,EAAE,CAM9G;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,WAAW,EAAE,CAE9G;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,eAAe,EAAE,CAIpH;AAED,gDAAgD;AAChD,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACvB;AA0BD,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,SAAS,EAAE,CAqB1G"}
package/lib/cascade.js ADDED
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Каскад отказа: ресурс, чей родитель не поехал в дерево, снимается вслед за ним.
3
+ *
4
+ * Отдельным модулем от каталога: каталог знает, какие ресурсы бывают, а каскад — как они связаны
5
+ * родством. Связь родителя с потомком читают двое — сверка связности пакета и сама раскладка, —
6
+ * и оба берут её отсюда.
7
+ */
8
+ import { frontMatterOf, isChosen } from './catalog.js';
9
+ import { matchesVariant } from './variants.js';
10
+ /** Последнее звено имени: `application/money` → `money`. Им ресурсы и ссылаются друг на друга. */
11
+ const shortNameOf = (entry) => entry.name.split('/').pop() ?? entry.name;
12
+ /** Взятые ресурсы одного рода. */
13
+ function chosenOfKind(catalog, selection, kind) {
14
+ return catalog.filter((entry) => entry.kind === kind && isChosen(entry, selection));
15
+ }
16
+ /** Короткие имена взятых ресурсов рода. */
17
+ function takenNames(catalog, selection, kind) {
18
+ return new Set(chosenOfKind(catalog, selection, kind).map(shortNameOf));
19
+ }
20
+ /** Короткие имена всех ресурсов рода, взяты они или нет. */
21
+ function knownNames(catalog, kind) {
22
+ return new Set(catalog.filter((entry) => entry.kind === kind).map(shortNameOf));
23
+ }
24
+ /** Правила, снятые вслед за своим законом. Заодно называет корень цепочки для паттернов при них. */
25
+ function rulesCutByLaws(catalog, selection, rootByRule) {
26
+ const taken = takenNames(catalog, selection, 'laws');
27
+ const known = knownNames(catalog, 'laws');
28
+ const cuts = [];
29
+ for (const entry of chosenOfKind(catalog, selection, 'rules')) {
30
+ const law = frontMatterOf(entry.text).law;
31
+ if (law && known.has(law) && !taken.has(law)) {
32
+ cuts.push({ id: entry.id, parent: law, root: law });
33
+ rootByRule.set(shortNameOf(entry), law);
34
+ }
35
+ }
36
+ return cuts;
37
+ }
38
+ /** Паттерны, снятые вслед за своим правилом: либо оно не взято, либо само ушло за своим законом. */
39
+ function patternsCutByRules(catalog, selection, rootByRule) {
40
+ const taken = takenNames(catalog, selection, 'rules');
41
+ const known = knownNames(catalog, 'rules');
42
+ const cuts = [];
43
+ for (const entry of chosenOfKind(catalog, selection, 'patterns')) {
44
+ const rule = frontMatterOf(entry.text).rule;
45
+ const standing = taken.has(rule) && !rootByRule.has(rule);
46
+ if (rule && known.has(rule) && !standing) {
47
+ cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });
48
+ }
49
+ }
50
+ return cuts;
51
+ }
52
+ /**
53
+ * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.
54
+ *
55
+ * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с
56
+ * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по
57
+ * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями
58
+ * переписывал бы шапки всех правил при нём.
59
+ *
60
+ * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит
61
+ * сверка связности пакета, до всякой раскладки в дереве.
62
+ */
63
+ export function cascadeCuts(catalog, selection) {
64
+ /** Правило, снятое законом: для паттернов при нём корнем цепочки будет этот закон. */
65
+ const rootByRule = new Map();
66
+ const rules = rulesCutByLaws(catalog, selection, rootByRule);
67
+ return [...rules, ...patternsCutByRules(catalog, selection, rootByRule)];
68
+ }
69
+ /**
70
+ * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.
71
+ *
72
+ * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое
73
+ * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,
74
+ * кто ничего не просил, здесь — тот, кто попросил прямо.
75
+ */
76
+ export function namedButCut(catalog, selection) {
77
+ return cascadeCuts(catalog, selection).filter((one) => selection.only.includes(one.id));
78
+ }
79
+ /**
80
+ * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.
81
+ *
82
+ * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —
83
+ * один ресурс: связь родителя с потомком по одной записи не видна.
84
+ */
85
+ export function chosenEntries(catalog, selection) {
86
+ const cut = new Set(cascadeCuts(catalog, selection).map((one) => one.id));
87
+ return catalog.filter((entry) => isChosen(entry, selection) && !cut.has(entry.id));
88
+ }
89
+ /**
90
+ * Строки отказа, которые ничего не снимают: названное ими снято каскадом или в каталоге не
91
+ * значится вовсе.
92
+ *
93
+ * Не отказ, а предупреждение: настройка, верная до обновления пакета, становится лишней сама,
94
+ * без единой правки в дереве, и отбивать за это раскладку значило бы наказывать за вчерашнюю
95
+ * правоту.
96
+ *
97
+ * Строка на ресурс чужого вида лишней не считается никогда: ею дерево гасит отказ о ресурсе,
98
+ * у которого нет подходящего вида, — то есть работу она делает.
99
+ */
100
+ /**
101
+ * Корень цепочки, которой ресурс снят и без этой строки отказа. Пусто — каскад его не трогает.
102
+ *
103
+ * Каскад считается от отбора без самой строки: иначе снятое ею читалось бы как снятое родителем,
104
+ * и лишней оказалась бы любая строка отказа подряд.
105
+ */
106
+ function cutParentOf(catalog, selection, id) {
107
+ const without = { ...selection, skip: selection.skip.filter((one) => one !== id) };
108
+ const cut = cascadeCuts(catalog, without).find((one) => one.id === id);
109
+ return cut ? cut.root : null;
110
+ }
111
+ export function idleSkips(catalog, selection) {
112
+ const idle = [];
113
+ for (const id of selection.skip) {
114
+ const entry = catalog.find((one) => one.id === id);
115
+ if (!entry) {
116
+ idle.push({ id, by: '' });
117
+ }
118
+ else if (matchesVariant(entry.variant, selection.variants)) {
119
+ const by = cutParentOf(catalog, selection, id);
120
+ if (by !== null) {
121
+ idle.push({ id, by });
122
+ }
123
+ }
124
+ else {
125
+ // Строка на ресурс чужого вида работу делает: ею дерево гасит отказ о ресурсе, у
126
+ // которого подходящего вида нет
127
+ }
128
+ }
129
+ return idle;
130
+ }
131
+ //# sourceMappingURL=cascade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascade.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAmB,QAAQ,EAAc,MAAM,cAAc,CAAC;AAEpF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAe/C,kGAAkG;AAClG,MAAM,WAAW,GAAuC,CAAC,KAAsB,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC;AAEtI,kCAAkC;AAClC,SAAS,YAAY,CAAC,OAAmC,EAAE,SAAqB,EAAE,IAAW;IACzF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;AAClH,CAAC;AAED,2CAA2C;AAC3C,SAAS,UAAU,CAAC,OAAmC,EAAE,SAAqB,EAAE,IAAW;IACvF,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,4DAA4D;AAC5D,SAAS,UAAU,CAAC,OAAmC,EAAE,IAAW;IAChE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;AAC9G,CAAC;AAED,oGAAoG;AACpG,SAAS,cAAc,CACnB,OAAmC,EACnC,SAAqB,EACrB,UAA+B;IAE/B,MAAM,KAAK,GAAwB,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAwB,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAkB,EAAE,CAAC;IAE/B,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAM,GAAG,GAAW,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;QAElD,IAAI,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACpD,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,oGAAoG;AACpG,SAAS,kBAAkB,CACvB,OAAmC,EACnC,SAAqB,EACrB,UAAuC;IAEvC,MAAM,KAAK,GAAwB,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAwB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChE,MAAM,IAAI,GAAkB,EAAE,CAAC;IAE/B,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,GAAW,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;QACpD,MAAM,QAAQ,GAAY,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEnE,IAAI,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAClF,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,OAAmC,EAAE,SAAqB;IAClF,sFAAsF;IACtF,MAAM,UAAU,GAAwB,IAAI,GAAG,EAAkB,CAAC;IAClE,MAAM,KAAK,GAA2B,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAErF,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAmC,EAAE,SAAqB;IAClF,OAAO,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GAAgB,EAAW,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAClH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAmC,EAAE,SAAqB;IACpF,MAAM,GAAG,GAAwB,IAAI,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAgB,EAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AACjH,CAAC;AASD;;;;;;;;;;GAUG;AACH;;;;;GAKG;AACH,SAAS,WAAW,CAAC,OAAmC,EAAE,SAAqB,EAAE,EAAU;IACvF,MAAM,OAAO,GAAe,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAW,EAAW,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC;IAChH,MAAM,GAAG,GAA4B,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,GAAgB,EAAW,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAEtH,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAmC,EAAE,SAAqB;IAChF,MAAM,IAAI,GAAgB,EAAE,CAAC;IAE7B,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAgC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAoB,EAAW,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAE1G,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;aAAM,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,MAAM,EAAE,GAAkB,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;YAE9D,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACd,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1B,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,iFAAiF;YACjF,gCAAgC;QACpC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Каскад отказа: ресурс, чей родитель не поехал в дерево, снимается вслед за ним.\n *\n * Отдельным модулем от каталога: каталог знает, какие ресурсы бывают, а каскад — как они связаны\n * родством. Связь родителя с потомком читают двое — сверка связности пакета и сама раскладка, —\n * и оба берут её отсюда.\n */\n\nimport { frontMatterOf, IEntryOfCatalog, isChosen, ISelection } from './catalog.js';\nimport { TKind } from './config.js';\nimport { matchesVariant } from './variants.js';\n\n/** Ресурс, снятый вслед за отвергнутым родителем. */\nexport interface ICascadeCut {\n readonly id: string;\n /** Ближайший родитель: у правила — его закон, у паттерна — его правило. */\n readonly parent: string;\n /**\n * Отвергнутый корень цепочки — то, что дерево действительно отвергло или не выбрало.\n * Ближайшего родителя мало: паттерн уходит вслед за правилом, которого в отказе нет, и\n * искать его там читатель пойдёт зря.\n */\n readonly root: string;\n}\n\n/** Последнее звено имени: `application/money` → `money`. Им ресурсы и ссылаются друг на друга. */\nconst shortNameOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => entry.name.split('/').pop() ?? entry.name;\n\n/** Взятые ресурсы одного рода. */\nfunction chosenOfKind(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): readonly IEntryOfCatalog[] {\n return catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind && isChosen(entry, selection));\n}\n\n/** Короткие имена взятых ресурсов рода. */\nfunction takenNames(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): ReadonlySet<string> {\n return new Set(chosenOfKind(catalog, selection, kind).map(shortNameOf));\n}\n\n/** Короткие имена всех ресурсов рода, взяты они или нет. */\nfunction knownNames(catalog: readonly IEntryOfCatalog[], kind: TKind): ReadonlySet<string> {\n return new Set(catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind).map(shortNameOf));\n}\n\n/** Правила, снятые вслед за своим законом. Заодно называет корень цепочки для паттернов при них. */\nfunction rulesCutByLaws(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: Map<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'laws');\n const known: ReadonlySet<string> = knownNames(catalog, 'laws');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'rules')) {\n const law: string = frontMatterOf(entry.text).law;\n\n if (law && known.has(law) && !taken.has(law)) {\n cuts.push({ id: entry.id, parent: law, root: law });\n rootByRule.set(shortNameOf(entry), law);\n }\n }\n\n return cuts;\n}\n\n/** Паттерны, снятые вслед за своим правилом: либо оно не взято, либо само ушло за своим законом. */\nfunction patternsCutByRules(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: ReadonlyMap<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'rules');\n const known: ReadonlySet<string> = knownNames(catalog, 'rules');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'patterns')) {\n const rule: string = frontMatterOf(entry.text).rule;\n const standing: boolean = taken.has(rule) && !rootByRule.has(rule);\n\n if (rule && known.has(rule) && !standing) {\n cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });\n }\n }\n\n return cuts;\n}\n\n/**\n * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.\n *\n * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с\n * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по\n * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями\n * переписывал бы шапки всех правил при нём.\n *\n * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит\n * сверка связности пакета, до всякой раскладки в дереве.\n */\nexport function cascadeCuts(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n /** Правило, снятое законом: для паттернов при нём корнем цепочки будет этот закон. */\n const rootByRule: Map<string, string> = new Map<string, string>();\n const rules: readonly ICascadeCut[] = rulesCutByLaws(catalog, selection, rootByRule);\n\n return [...rules, ...patternsCutByRules(catalog, selection, rootByRule)];\n}\n\n/**\n * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.\n *\n * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое\n * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,\n * кто ничего не просил, здесь — тот, кто попросил прямо.\n */\nexport function namedButCut(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n return cascadeCuts(catalog, selection).filter((one: ICascadeCut): boolean => selection.only.includes(one.id));\n}\n\n/**\n * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.\n *\n * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —\n * один ресурс: связь родителя с потомком по одной записи не видна.\n */\nexport function chosenEntries(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IEntryOfCatalog[] {\n const cut: ReadonlySet<string> = new Set(cascadeCuts(catalog, selection).map((one: ICascadeCut): string => one.id));\n\n return catalog.filter((entry: IEntryOfCatalog): boolean => isChosen(entry, selection) && !cut.has(entry.id));\n}\n\n/** Строка отказа, которая ничего не снимает. */\nexport interface IIdleSkip {\n readonly id: string;\n /** Чем названное ею уже снято: имя отвергнутого родителя, либо пусто — такого ресурса нет. */\n readonly by: string;\n}\n\n/**\n * Строки отказа, которые ничего не снимают: названное ими снято каскадом или в каталоге не\n * значится вовсе.\n *\n * Не отказ, а предупреждение: настройка, верная до обновления пакета, становится лишней сама,\n * без единой правки в дереве, и отбивать за это раскладку значило бы наказывать за вчерашнюю\n * правоту.\n *\n * Строка на ресурс чужого вида лишней не считается никогда: ею дерево гасит отказ о ресурсе,\n * у которого нет подходящего вида, — то есть работу она делает.\n */\n/**\n * Корень цепочки, которой ресурс снят и без этой строки отказа. Пусто — каскад его не трогает.\n *\n * Каскад считается от отбора без самой строки: иначе снятое ею читалось бы как снятое родителем,\n * и лишней оказалась бы любая строка отказа подряд.\n */\nfunction cutParentOf(catalog: readonly IEntryOfCatalog[], selection: ISelection, id: string): string | null {\n const without: ISelection = { ...selection, skip: selection.skip.filter((one: string): boolean => one !== id) };\n const cut: ICascadeCut | undefined = cascadeCuts(catalog, without).find((one: ICascadeCut): boolean => one.id === id);\n\n return cut ? cut.root : null;\n}\n\nexport function idleSkips(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IIdleSkip[] {\n const idle: IIdleSkip[] = [];\n\n for (const id of selection.skip) {\n const entry: IEntryOfCatalog | undefined = catalog.find((one: IEntryOfCatalog): boolean => one.id === id);\n\n if (!entry) {\n idle.push({ id, by: '' });\n } else if (matchesVariant(entry.variant, selection.variants)) {\n const by: string | null = cutParentOf(catalog, selection, id);\n\n if (by !== null) {\n idle.push({ id, by });\n }\n } else {\n // Строка на ресурс чужого вида работу делает: ею дерево гасит отказ о ресурсе, у\n // которого подходящего вида нет\n }\n }\n\n return idle;\n}\n"]}