@litfamily/litcodex 1.0.1 → 1.0.3

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 (211) hide show
  1. package/README.md +22 -23
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +2 -38
  4. package/dist/install/generated-skill-payload-hashes.d.ts +12 -17
  5. package/dist/install/generated-skill-payload-hashes.js +12 -17
  6. package/dist/install/skill-catalog.d.ts +1 -1
  7. package/dist/install/skill-catalog.js +1 -6
  8. package/dist/install/skill-resource-hashes.d.ts +1 -1
  9. package/dist/install/skill-resource-hashes.js +1 -1
  10. package/marketplace/plugins/litcodex/.codex-plugin/plugin.json +1 -1
  11. package/marketplace/plugins/litcodex/components/auto-update/package.json +1 -1
  12. package/marketplace/plugins/litcodex/components/comment-checker/package.json +1 -1
  13. package/marketplace/plugins/litcodex/components/git-bash/package.json +1 -1
  14. package/marketplace/plugins/litcodex/components/lit-loop/directive.md +1 -1
  15. package/marketplace/plugins/litcodex/components/lit-loop/directives/browser-drive.md +1 -1
  16. package/marketplace/plugins/litcodex/components/lit-loop/directives/deep-interview.md +3 -3
  17. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-comprehend.md +1 -1
  18. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-crucible.md +1 -1
  19. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-handoff.md +2 -2
  20. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-init.md +1 -1
  21. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-plan.md +2 -2
  22. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-recap.md +1 -1
  23. package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-scientific-visualization.md +2 -2
  24. package/marketplace/plugins/litcodex/components/lit-loop/directives/litgoal.md +1 -1
  25. package/marketplace/plugins/litcodex/components/lit-loop/directives/litresearch.md +1 -1
  26. package/marketplace/plugins/litcodex/components/lit-loop/directives/litwork.md +2 -2
  27. package/marketplace/plugins/litcodex/components/lit-loop/directives/review-work.md +1 -1
  28. package/marketplace/plugins/litcodex/components/lit-loop/directives/start-work.md +1 -1
  29. package/marketplace/plugins/litcodex/components/lit-loop/dist/cli.js +3 -20
  30. package/marketplace/plugins/litcodex/components/lit-loop/dist/codex-hook.d.ts +5 -5
  31. package/marketplace/plugins/litcodex/components/lit-loop/dist/codex-hook.js +20 -19
  32. package/marketplace/plugins/litcodex/components/lit-loop/dist/directive.js +1 -1
  33. package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.d.ts +2 -1
  34. package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.js +4 -27
  35. package/marketplace/plugins/litcodex/components/lit-loop/dist/lit-mark.d.ts +2 -0
  36. package/marketplace/plugins/litcodex/components/lit-loop/dist/lit-mark.js +49 -0
  37. package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.d.ts +0 -2
  38. package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.js +0 -2
  39. package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.d.ts +1 -3
  40. package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.js +1 -10
  41. package/marketplace/plugins/litcodex/components/lit-loop/package.json +1 -1
  42. package/marketplace/plugins/litcodex/components/lsp/package.json +1 -1
  43. package/marketplace/plugins/litcodex/components/rules/dist/static-injection.js +2 -2
  44. package/marketplace/plugins/litcodex/components/rules/package.json +1 -1
  45. package/marketplace/plugins/litcodex/components/start-work-continuation/package.json +1 -1
  46. package/marketplace/plugins/litcodex/components/telemetry/package.json +1 -1
  47. package/marketplace/plugins/litcodex/components/wikify-knowledge/package.json +1 -1
  48. package/marketplace/plugins/litcodex/hooks/hooks.json +19 -19
  49. package/marketplace/plugins/litcodex/skills/autoconference/SKILL.md +1 -1
  50. package/marketplace/plugins/litcodex/skills/autoresearch/SKILL.md +1 -1
  51. package/marketplace/plugins/litcodex/skills/browser-drive/SKILL.md +3 -3
  52. package/marketplace/plugins/litcodex/skills/browser-drive/scripts/capability-probe.mjs +13 -5
  53. package/marketplace/plugins/litcodex/skills/coding-session-audit/SKILL.md +2 -2
  54. package/marketplace/plugins/litcodex/skills/comment-checker/SKILL.md +1 -1
  55. package/marketplace/plugins/litcodex/skills/debugging/SKILL.md +1 -1
  56. package/marketplace/plugins/litcodex/skills/deep-interview/SKILL.md +3 -3
  57. package/marketplace/plugins/litcodex/skills/frontend-ui-ux/SKILL.md +1 -1
  58. package/marketplace/plugins/litcodex/skills/frontend-ui-ux/references/complete-contract.md +1 -1
  59. package/marketplace/plugins/litcodex/skills/lit-burnoff/SKILL.md +1 -1
  60. package/marketplace/plugins/litcodex/skills/lit-burnoff-file/SKILL.md +1 -1
  61. package/marketplace/plugins/litcodex/skills/lit-code/SKILL.md +1 -1
  62. package/marketplace/plugins/litcodex/skills/lit-commit/SKILL.md +1 -1
  63. package/marketplace/plugins/litcodex/skills/lit-comprehend/SKILL.md +1 -1
  64. package/marketplace/plugins/litcodex/skills/lit-crucible/SKILL.md +1 -1
  65. package/marketplace/plugins/litcodex/skills/lit-fetch/SKILL.md +1 -1
  66. package/marketplace/plugins/litcodex/skills/lit-handoff/SKILL.md +4 -4
  67. package/marketplace/plugins/litcodex/skills/lit-init/SKILL.md +1 -1
  68. package/marketplace/plugins/litcodex/skills/lit-korean/SKILL.md +1 -1
  69. package/marketplace/plugins/litcodex/skills/lit-loop/SKILL.md +1 -1
  70. package/marketplace/plugins/litcodex/skills/lit-plan/SKILL.md +1 -1
  71. package/marketplace/plugins/litcodex/skills/lit-recap/SKILL.md +1 -1
  72. package/marketplace/plugins/litcodex/skills/lit-scientific-visualization/SKILL.md +4 -4
  73. package/marketplace/plugins/litcodex/skills/lit-team/SKILL.md +1 -1
  74. package/marketplace/plugins/litcodex/skills/litcodex-contribute-bug-fix/SKILL.md +1 -1
  75. package/marketplace/plugins/litcodex/skills/litcodex-doctor/SKILL.md +1 -1
  76. package/marketplace/plugins/litcodex/skills/litcodex-report-bug/SKILL.md +1 -1
  77. package/marketplace/plugins/litcodex/skills/litgoal/SKILL.md +1 -1
  78. package/marketplace/plugins/litcodex/skills/litresearch/SKILL.md +2 -2
  79. package/marketplace/plugins/litcodex/skills/litwork/SKILL.md +1 -1
  80. package/marketplace/plugins/litcodex/skills/lsp/SKILL.md +1 -1
  81. package/marketplace/plugins/litcodex/skills/lsp-setup/SKILL.md +1 -1
  82. package/marketplace/plugins/litcodex/skills/refactor/SKILL.md +1 -1
  83. package/marketplace/plugins/litcodex/skills/review-work/SKILL.md +1 -1
  84. package/marketplace/plugins/litcodex/skills/rules/SKILL.md +1 -1
  85. package/marketplace/plugins/litcodex/skills/start-work/SKILL.md +1 -1
  86. package/marketplace/plugins/litcodex/skills/structural-search/SKILL.md +1 -1
  87. package/marketplace/plugins/litcodex/skills/visual-qa/SKILL.md +1 -1
  88. package/marketplace/plugins/litcodex/skills/visual-qa/references/complete-contract.md +1 -1
  89. package/marketplace/plugins/litcodex/skills/wikify/SKILL.md +1 -1
  90. package/node_modules/@litcodex/lit-loop/README.md +1 -7
  91. package/node_modules/@litcodex/lit-loop/directive.md +1 -1
  92. package/node_modules/@litcodex/lit-loop/directives/browser-drive.md +1 -1
  93. package/node_modules/@litcodex/lit-loop/directives/deep-interview.md +3 -3
  94. package/node_modules/@litcodex/lit-loop/directives/lit-comprehend.md +1 -1
  95. package/node_modules/@litcodex/lit-loop/directives/lit-crucible.md +1 -1
  96. package/node_modules/@litcodex/lit-loop/directives/lit-handoff.md +2 -2
  97. package/node_modules/@litcodex/lit-loop/directives/lit-init.md +1 -1
  98. package/node_modules/@litcodex/lit-loop/directives/lit-plan.md +2 -2
  99. package/node_modules/@litcodex/lit-loop/directives/lit-recap.md +1 -1
  100. package/node_modules/@litcodex/lit-loop/directives/lit-scientific-visualization.md +2 -2
  101. package/node_modules/@litcodex/lit-loop/directives/litgoal.md +1 -1
  102. package/node_modules/@litcodex/lit-loop/directives/litresearch.md +1 -1
  103. package/node_modules/@litcodex/lit-loop/directives/litwork.md +2 -2
  104. package/node_modules/@litcodex/lit-loop/directives/review-work.md +1 -1
  105. package/node_modules/@litcodex/lit-loop/directives/start-work.md +1 -1
  106. package/node_modules/@litcodex/lit-loop/dist/cli.js +3 -20
  107. package/node_modules/@litcodex/lit-loop/dist/codex-hook.d.ts +5 -5
  108. package/node_modules/@litcodex/lit-loop/dist/codex-hook.js +20 -19
  109. package/node_modules/@litcodex/lit-loop/dist/directive.js +1 -1
  110. package/node_modules/@litcodex/lit-loop/dist/hook-cli.d.ts +2 -1
  111. package/node_modules/@litcodex/lit-loop/dist/hook-cli.js +4 -27
  112. package/node_modules/@litcodex/lit-loop/dist/lit-mark.d.ts +2 -0
  113. package/node_modules/@litcodex/lit-loop/dist/lit-mark.js +49 -0
  114. package/node_modules/@litcodex/lit-loop/dist/markers.d.ts +0 -2
  115. package/node_modules/@litcodex/lit-loop/dist/markers.js +0 -2
  116. package/node_modules/@litcodex/lit-loop/dist/modes.d.ts +1 -3
  117. package/node_modules/@litcodex/lit-loop/dist/modes.js +1 -10
  118. package/node_modules/@litcodex/lit-loop/package.json +1 -1
  119. package/node_modules/@litcodex/lit-loop/skills/browser-drive/SKILL.md +3 -3
  120. package/node_modules/@litcodex/lit-loop/skills/browser-drive/scripts/capability-probe.mjs +13 -5
  121. package/node_modules/@litcodex/lit-loop/skills/deep-interview/SKILL.md +3 -3
  122. package/node_modules/@litcodex/lit-loop/skills/lit-burnoff/SKILL.md +1 -1
  123. package/node_modules/@litcodex/lit-loop/skills/lit-burnoff-file/SKILL.md +1 -1
  124. package/node_modules/@litcodex/lit-loop/skills/lit-code/SKILL.md +1 -1
  125. package/node_modules/@litcodex/lit-loop/skills/lit-commit/SKILL.md +1 -1
  126. package/node_modules/@litcodex/lit-loop/skills/lit-comprehend/SKILL.md +1 -1
  127. package/node_modules/@litcodex/lit-loop/skills/lit-crucible/SKILL.md +1 -1
  128. package/node_modules/@litcodex/lit-loop/skills/lit-fetch/SKILL.md +1 -1
  129. package/node_modules/@litcodex/lit-loop/skills/lit-handoff/SKILL.md +4 -4
  130. package/node_modules/@litcodex/lit-loop/skills/lit-init/SKILL.md +1 -1
  131. package/node_modules/@litcodex/lit-loop/skills/lit-korean/SKILL.md +1 -1
  132. package/node_modules/@litcodex/lit-loop/skills/lit-loop/SKILL.md +1 -1
  133. package/node_modules/@litcodex/lit-loop/skills/lit-plan/SKILL.md +1 -1
  134. package/node_modules/@litcodex/lit-loop/skills/lit-recap/SKILL.md +1 -1
  135. package/node_modules/@litcodex/lit-loop/skills/lit-scientific-visualization/SKILL.md +4 -4
  136. package/node_modules/@litcodex/lit-loop/skills/lit-team/SKILL.md +1 -1
  137. package/node_modules/@litcodex/lit-loop/skills/litgoal/SKILL.md +1 -1
  138. package/node_modules/@litcodex/lit-loop/skills/litresearch/SKILL.md +2 -2
  139. package/node_modules/@litcodex/lit-loop/skills/litwork/SKILL.md +1 -1
  140. package/node_modules/@litcodex/lit-loop/skills/review-work/SKILL.md +1 -1
  141. package/node_modules/@litcodex/lit-loop/skills/start-work/SKILL.md +1 -1
  142. package/package.json +2 -2
  143. package/readme-assets/badge-version.svg +1 -1
  144. package/readme-assets/cover-motion.webp +0 -0
  145. package/marketplace/plugins/litcodex/components/lit-loop/directives/skill-observer.md +0 -105
  146. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.d.ts +0 -16
  147. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.js +0 -227
  148. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.d.ts +0 -13
  149. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.js +0 -12
  150. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.d.ts +0 -14
  151. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.js +0 -112
  152. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.d.ts +0 -19
  153. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.js +0 -435
  154. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
  155. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.js +0 -145
  156. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.d.ts +0 -18
  157. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.js +0 -43
  158. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.d.ts +0 -28
  159. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.js +0 -702
  160. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.d.ts +0 -32
  161. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.js +0 -667
  162. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
  163. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.js +0 -524
  164. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.d.ts +0 -81
  165. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.js +0 -246
  166. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.d.ts +0 -6
  167. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.js +0 -119
  168. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.d.ts +0 -8
  169. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.js +0 -111
  170. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.d.ts +0 -3
  171. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.js +0 -116
  172. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.d.ts +0 -6
  173. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.js +0 -12
  174. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.d.ts +0 -18
  175. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.js +0 -946
  176. package/marketplace/plugins/litcodex/skills/skill-observer/SKILL.md +0 -215
  177. package/marketplace/plugins/litcodex/skills/skill-observer/agents/openai.yaml +0 -6
  178. package/marketplace/plugins/litcodex/skills/skill-observer/references/review-contract.md +0 -77
  179. package/node_modules/@litcodex/lit-loop/directives/skill-observer.md +0 -105
  180. package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.d.ts +0 -16
  181. package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.js +0 -227
  182. package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.d.ts +0 -13
  183. package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.js +0 -12
  184. package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.d.ts +0 -14
  185. package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.js +0 -112
  186. package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.d.ts +0 -19
  187. package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.js +0 -435
  188. package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
  189. package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.js +0 -145
  190. package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.d.ts +0 -18
  191. package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.js +0 -43
  192. package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.d.ts +0 -28
  193. package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.js +0 -702
  194. package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.d.ts +0 -32
  195. package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.js +0 -667
  196. package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
  197. package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.js +0 -524
  198. package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.d.ts +0 -81
  199. package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.js +0 -246
  200. package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.d.ts +0 -6
  201. package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.js +0 -119
  202. package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.d.ts +0 -8
  203. package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.js +0 -111
  204. package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.d.ts +0 -3
  205. package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.js +0 -116
  206. package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.d.ts +0 -6
  207. package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.js +0 -12
  208. package/node_modules/@litcodex/lit-loop/dist/skill-observer.d.ts +0 -18
  209. package/node_modules/@litcodex/lit-loop/dist/skill-observer.js +0 -946
  210. package/node_modules/@litcodex/lit-loop/skills/skill-observer/SKILL.md +0 -215
  211. package/node_modules/@litcodex/lit-loop/skills/skill-observer/references/review-contract.md +0 -77
@@ -1,16 +0,0 @@
1
- import type { SkillLedgerEntry, SkillProposal } from "./types.js";
2
- export interface SkillMutationOptions {
3
- readonly env?: NodeJS.ProcessEnv | undefined;
4
- readonly now?: () => Date;
5
- readonly id?: () => string;
6
- }
7
- export interface SkillMutationResult {
8
- readonly proposal: SkillProposal;
9
- readonly ledger: SkillLedgerEntry;
10
- }
11
- export declare function applyProposal(workspaceRoot: string, proposalId: string, options?: SkillMutationOptions): SkillMutationResult;
12
- export declare function rejectProposal(workspaceRoot: string, proposalId: string, options?: SkillMutationOptions): SkillMutationResult;
13
- export declare function rollbackMutation(workspaceRoot: string, entryId: string, options?: SkillMutationOptions): {
14
- readonly proposal?: SkillProposal;
15
- readonly ledger: SkillLedgerEntry;
16
- };
@@ -1,227 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { resolve } from "node:path";
3
- import { decodeSkillItem, snapshotIsAgentOwned, stampMarker } from "./ownership.js";
4
- import { skillLoopPaths } from "./paths.js";
5
- import { appendLedgerEntry, assertTargetNotPinned, readLedger, readProposalRecord, readUsage, snapshotSkill, snapshotsEqual, storeBlob, withAgentMutationLock, withSkillLoopLock, writeProposalRecord, } from "./store.js";
6
- import { recoverMutationJournalWhileLocked, writeMutationJournal } from "./transaction.js";
7
- import { SkillLoopError } from "./types.js";
8
- import { nextAppliedUsage } from "./usage.js";
9
- function now(options) {
10
- return (options.now ?? (() => new Date()))().toISOString();
11
- }
12
- function ledgerId(options) {
13
- return (options.id ?? (() => `ledger-${randomUUID()}`))();
14
- }
15
- function snapshotMap(snapshot) {
16
- return new Map(snapshot.map((item) => [item.file, item]));
17
- }
18
- function assertOwned(paths, snapshot) {
19
- if (!snapshotIsAgentOwned(paths, snapshot)) {
20
- throw new SkillLoopError("TARGET_NOT_AGENT_OWNED", "the existing skill lacks the agent ownership marker");
21
- }
22
- }
23
- function desiredSnapshot(paths, proposal, before) {
24
- const items = snapshotMap(before);
25
- if (proposal.action === "create") {
26
- if (before.length > 0)
27
- throw new SkillLoopError("TARGET_NOT_AGENT_OWNED", "create refuses an existing skill");
28
- const files = proposal.createSpec?.files ?? [];
29
- if (!files.some((file) => file.file === "SKILL.md")) {
30
- throw new SkillLoopError("PROPOSAL_SCHEMA_INVALID", "create requires SKILL.md");
31
- }
32
- for (const file of files) {
33
- const content = file.file === "SKILL.md" ? stampMarker(file.content, proposal.targetSkill) : file.content;
34
- items.set(file.file, { file: file.file, blob: storeBlob(paths, Buffer.from(content, "utf8")) });
35
- }
36
- }
37
- else {
38
- if (before.length === 0)
39
- throw new SkillLoopError("TARGET_NOT_AGENT_OWNED", "the target skill does not exist");
40
- assertOwned(paths, before);
41
- if (proposal.action === "patch") {
42
- const patch = proposal.patch;
43
- if (patch === undefined)
44
- throw new SkillLoopError("PROPOSAL_SCHEMA_INVALID", "the patch is missing");
45
- const current = items.get(patch.file);
46
- if (current === undefined)
47
- throw new SkillLoopError("PATCH_FILE_MISSING", "the patch file does not exist");
48
- const content = decodeSkillItem(paths, current);
49
- const first = content.indexOf(patch.oldString);
50
- if (first < 0 || content.indexOf(patch.oldString, first + patch.oldString.length) >= 0) {
51
- throw new SkillLoopError("PATCH_AMBIGUOUS", "the patch oldString must match exactly once");
52
- }
53
- const updated = `${content.slice(0, first)}${patch.newString}${content.slice(first + patch.oldString.length)}`;
54
- items.set(patch.file, { file: patch.file, blob: storeBlob(paths, Buffer.from(updated, "utf8")) });
55
- }
56
- else if (proposal.action === "add-reference") {
57
- for (const file of proposal.createSpec?.files ?? []) {
58
- if (items.has(file.file))
59
- throw new SkillLoopError("TARGET_FILE_EXISTS", "add-reference refuses an existing file");
60
- items.set(file.file, { file: file.file, blob: storeBlob(paths, Buffer.from(file.content, "utf8")) });
61
- }
62
- }
63
- else if (proposal.action === "archive") {
64
- return [];
65
- }
66
- }
67
- const desired = [...items.values()].sort((left, right) => left.file.localeCompare(right.file));
68
- if (!snapshotIsAgentOwned(paths, desired)) {
69
- throw new SkillLoopError("TARGET_MARKER_INVALID", "the mutation postimage must preserve direct ownership");
70
- }
71
- return desired;
72
- }
73
- export function applyProposal(workspaceRoot, proposalId, options = {}) {
74
- const paths = skillLoopPaths(workspaceRoot, options.env);
75
- return withSkillLoopLock(paths, () => withAgentMutationLock(paths, () => {
76
- const recoveredJournal = recoverMutationJournalWhileLocked(workspaceRoot, options.env, {
77
- operation: "apply",
78
- proposalId,
79
- });
80
- if (recoveredJournal?.operation === "apply" && recoveredJournal.ledger.proposalId === proposalId) {
81
- const recoveredProposal = recoveredJournal.proposalAfter;
82
- if (recoveredProposal === undefined) {
83
- throw new SkillLoopError("TRANSACTION_INVALID", "the recovered apply proposal is missing");
84
- }
85
- return { proposal: recoveredProposal, ledger: recoveredJournal.ledger };
86
- }
87
- let proposal = readProposalRecord(paths, proposalId);
88
- assertTargetNotPinned(paths, proposal.targetSkill);
89
- if (proposal.status !== "pending" && proposal.status !== "approved") {
90
- throw new SkillLoopError("PROPOSAL_STATUS_INVALID", "only pending or approved proposals may be applied");
91
- }
92
- if (proposal.status === "pending") {
93
- proposal = { ...proposal, status: "approved" };
94
- writeProposalRecord(paths, proposal);
95
- }
96
- const current = snapshotSkill(paths, proposal.targetSkill);
97
- let before = current;
98
- let desired;
99
- if (proposal.action === "create" && current.length > 0) {
100
- const expected = desiredSnapshot(paths, proposal, []);
101
- const conflictingLedger = readLedger(workspaceRoot, { env: options.env }).some((entry) => entry.proposalId === proposal.id);
102
- const usage = readUsage(paths);
103
- if (!snapshotsEqual(current, expected) ||
104
- conflictingLedger ||
105
- usage?.skills[proposal.targetSkill] !== undefined) {
106
- throw new SkillLoopError("TRANSACTION_RECONCILIATION_REFUSED", "an interrupted create postimage could not be reconciled exactly");
107
- }
108
- before = [];
109
- desired = expected;
110
- }
111
- else {
112
- desired = desiredSnapshot(paths, proposal, before);
113
- }
114
- const timestamp = now(options);
115
- const ledger = {
116
- schema: "litfamily.skill-ledger/v1",
117
- id: ledgerId(options),
118
- createdAt: timestamp,
119
- proposalId: proposal.id,
120
- actor: "user",
121
- operation: "apply",
122
- targetSkill: proposal.targetSkill,
123
- targetRoot: paths.agentRoot,
124
- before,
125
- after: desired,
126
- };
127
- const applied = { ...proposal, status: "applied", ledgerEntryId: ledger.id };
128
- writeMutationJournal(workspaceRoot, {
129
- schema: "litcodex.skill-transaction/v1",
130
- operation: "apply",
131
- ledger,
132
- proposalAfter: applied,
133
- usageAfter: nextAppliedUsage(paths, proposal.targetSkill, timestamp),
134
- copies: [],
135
- }, options.env);
136
- recoverMutationJournalWhileLocked(workspaceRoot, options.env, { operation: "apply", proposalId });
137
- return { proposal: applied, ledger };
138
- }));
139
- }
140
- export function rejectProposal(workspaceRoot, proposalId, options = {}) {
141
- const paths = skillLoopPaths(workspaceRoot, options.env);
142
- return withSkillLoopLock(paths, () => {
143
- const proposal = readProposalRecord(paths, proposalId);
144
- const committed = readLedger(workspaceRoot, { env: options.env }).find((entry) => entry.operation === "reject" && entry.proposalId === proposal.id);
145
- if (committed !== undefined && proposal.status === "pending") {
146
- const recovered = { ...proposal, status: "rejected", ledgerEntryId: committed.id };
147
- writeProposalRecord(paths, recovered);
148
- return { proposal: recovered, ledger: committed };
149
- }
150
- if (proposal.status !== "pending") {
151
- throw new SkillLoopError("PROPOSAL_STATUS_INVALID", "only a pending proposal may be rejected");
152
- }
153
- const ledger = {
154
- schema: "litfamily.skill-ledger/v1",
155
- id: ledgerId(options),
156
- createdAt: now(options),
157
- proposalId: proposal.id,
158
- actor: "user",
159
- operation: "reject",
160
- targetSkill: proposal.targetSkill,
161
- targetRoot: paths.agentRoot,
162
- before: [],
163
- after: [],
164
- reason: "explicit user rejection",
165
- };
166
- appendLedgerEntry(paths, ledger);
167
- const rejected = { ...proposal, status: "rejected", ledgerEntryId: ledger.id };
168
- writeProposalRecord(paths, rejected);
169
- return { proposal: rejected, ledger };
170
- });
171
- }
172
- export function rollbackMutation(workspaceRoot, entryId, options = {}) {
173
- const paths = skillLoopPaths(workspaceRoot, options.env);
174
- return withSkillLoopLock(paths, () => withAgentMutationLock(paths, () => {
175
- const recoveredJournal = recoverMutationJournalWhileLocked(workspaceRoot, options.env, {
176
- operation: "rollback",
177
- restoresLedgerEntryId: entryId,
178
- });
179
- if (recoveredJournal?.operation === "rollback" && recoveredJournal.ledger.restoresLedgerEntryId === entryId) {
180
- return recoveredJournal.proposalAfter === undefined
181
- ? { ledger: recoveredJournal.ledger }
182
- : { proposal: recoveredJournal.proposalAfter, ledger: recoveredJournal.ledger };
183
- }
184
- const source = readLedger(workspaceRoot, { env: options.env }).find((entry) => entry.id === entryId);
185
- if (source === undefined ||
186
- !["apply", "curator-transition", "rollback"].includes(source.operation)) {
187
- throw new SkillLoopError("ROLLBACK_SOURCE_INVALID", "the rollback source is not eligible");
188
- }
189
- if (resolve(source.targetRoot) !== paths.agentRoot) {
190
- throw new SkillLoopError("ROLLBACK_SOURCE_INVALID", "the rollback source target root mismatched");
191
- }
192
- const current = snapshotSkill(paths, source.targetSkill);
193
- if (!snapshotsEqual(current, source.after)) {
194
- throw new SkillLoopError("ROLLBACK_CAS_MISMATCH", "the target changed after the source mutation");
195
- }
196
- const ledger = {
197
- schema: "litfamily.skill-ledger/v1",
198
- id: ledgerId(options),
199
- createdAt: now(options),
200
- proposalId: source.proposalId,
201
- actor: "user",
202
- operation: "rollback",
203
- targetSkill: source.targetSkill,
204
- targetRoot: paths.agentRoot,
205
- before: current,
206
- after: source.before,
207
- restoresLedgerEntryId: source.id,
208
- };
209
- let proposal;
210
- if (source.proposalId !== null) {
211
- const currentProposal = readProposalRecord(paths, source.proposalId);
212
- proposal = { ...currentProposal, status: "rolled-back", ledgerEntryId: ledger.id };
213
- }
214
- writeMutationJournal(workspaceRoot, {
215
- schema: "litcodex.skill-transaction/v1",
216
- operation: "rollback",
217
- ledger,
218
- ...(proposal === undefined ? {} : { proposalAfter: proposal }),
219
- copies: [],
220
- }, options.env);
221
- recoverMutationJournalWhileLocked(workspaceRoot, options.env, {
222
- operation: "rollback",
223
- restoresLedgerEntryId: entryId,
224
- });
225
- return proposal === undefined ? { ledger } : { proposal, ledger };
226
- }));
227
- }
@@ -1,13 +0,0 @@
1
- export interface SkillLoopConfig {
2
- readonly autoApply: false;
3
- readonly nudgeInterval: number;
4
- readonly curator: {
5
- readonly intervalDays: number;
6
- readonly minimumIdleHours: number;
7
- readonly staleAfterDays: number;
8
- readonly archiveAfterDays: number;
9
- readonly delete: false;
10
- readonly consolidation: false;
11
- };
12
- }
13
- export declare const DEFAULT_SKILL_LOOP_CONFIG: SkillLoopConfig;
@@ -1,12 +0,0 @@
1
- export const DEFAULT_SKILL_LOOP_CONFIG = Object.freeze({
2
- autoApply: false,
3
- nudgeInterval: 10,
4
- curator: Object.freeze({
5
- intervalDays: 7,
6
- minimumIdleHours: 2,
7
- staleAfterDays: 30,
8
- archiveAfterDays: 90,
9
- delete: false,
10
- consolidation: false,
11
- }),
12
- });
@@ -1,14 +0,0 @@
1
- export interface CuratorOptions {
2
- readonly env?: NodeJS.ProcessEnv | undefined;
3
- readonly now?: () => Date;
4
- readonly lastActivityAt?: Date;
5
- readonly id?: () => string;
6
- }
7
- export interface CuratorResult {
8
- readonly stale: readonly string[];
9
- readonly archived: readonly string[];
10
- readonly skipped: readonly string[];
11
- readonly ledgerIds: readonly string[];
12
- }
13
- export declare function runCurator(workspaceRoot: string, options?: CuratorOptions): CuratorResult;
14
- export declare function assertCuratorNeverDeletes(): false;
@@ -1,112 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { DEFAULT_SKILL_LOOP_CONFIG } from "./config.js";
3
- import { snapshotIsAgentOwned } from "./ownership.js";
4
- import { skillLoopPaths } from "./paths.js";
5
- import { readUsage, snapshotSkill, withAgentMutationLock, withSkillLoopLock } from "./store.js";
6
- import { recoverMutationJournalWhileLocked, writeMutationJournal } from "./transaction.js";
7
- import { SkillLoopError } from "./types.js";
8
- import { validateUsageSidecar } from "./usage.js";
9
- const DAY = 24 * 60 * 60 * 1000;
10
- function mostRecent(entry) {
11
- return Math.max(...[entry.created_at, entry.last_used_at, entry.last_viewed_at, entry.last_patched_at, entry.archived_at]
12
- .filter((value) => value !== null)
13
- .map((value) => Date.parse(value)));
14
- }
15
- function nextSidecar(sidecar, skillId, entry, timestamp) {
16
- return {
17
- schema: "litfamily.skill-usage/v1",
18
- updatedAt: timestamp,
19
- skills: { ...sidecar.skills, [skillId]: entry },
20
- };
21
- }
22
- export function runCurator(workspaceRoot, options = {}) {
23
- const paths = skillLoopPaths(workspaceRoot, options.env);
24
- return withSkillLoopLock(paths, () => withAgentMutationLock(paths, () => {
25
- recoverMutationJournalWhileLocked(workspaceRoot, options.env, { operation: "curator-transition" });
26
- const rawUsage = readUsage(paths);
27
- if (rawUsage === null)
28
- return { stale: [], archived: [], skipped: [], ledgerIds: [] };
29
- let sidecar = validateUsageSidecar(rawUsage);
30
- const instant = (options.now ?? (() => new Date()))();
31
- const timestamp = instant.toISOString();
32
- const lastActivity = options.lastActivityAt?.getTime() ?? Date.parse(sidecar.updatedAt);
33
- if (instant.getTime() - lastActivity < DEFAULT_SKILL_LOOP_CONFIG.curator.minimumIdleHours * 60 * 60 * 1000) {
34
- return { stale: [], archived: [], skipped: Object.keys(sidecar.skills).sort(), ledgerIds: [] };
35
- }
36
- const stale = [];
37
- const archived = [];
38
- const skipped = [];
39
- const ledgerIds = [];
40
- for (const skillId of Object.keys(sidecar.skills).sort()) {
41
- const entry = sidecar.skills[skillId];
42
- if (entry === undefined || entry.pinned || entry.state === "archived") {
43
- skipped.push(skillId);
44
- continue;
45
- }
46
- const ageDays = (instant.getTime() - mostRecent(entry)) / DAY;
47
- const transition = entry.state === "active" && ageDays >= DEFAULT_SKILL_LOOP_CONFIG.curator.staleAfterDays
48
- ? "stale"
49
- : entry.state === "stale" && ageDays >= DEFAULT_SKILL_LOOP_CONFIG.curator.archiveAfterDays
50
- ? "archived"
51
- : null;
52
- if (transition === null) {
53
- skipped.push(skillId);
54
- continue;
55
- }
56
- const before = snapshotSkill(paths, skillId);
57
- if (before.length === 0 || !snapshotIsAgentOwned(paths, before)) {
58
- skipped.push(skillId);
59
- continue;
60
- }
61
- const runId = `${timestamp.replace(/[:.]/gu, "-")}-${randomUUID()}`;
62
- const after = transition === "archived" ? [] : before;
63
- const transitioned = {
64
- ...entry,
65
- state: transition,
66
- archived_at: transition === "archived" ? timestamp : null,
67
- };
68
- const updated = nextSidecar(sidecar, skillId, transitioned, timestamp);
69
- const ledger = {
70
- schema: "litfamily.skill-ledger/v1",
71
- id: (options.id ?? (() => `ledger-${randomUUID()}`))(),
72
- createdAt: timestamp,
73
- proposalId: null,
74
- actor: "curator",
75
- operation: "curator-transition",
76
- targetSkill: skillId,
77
- targetRoot: paths.agentRoot,
78
- before,
79
- after,
80
- reason: transition === "archived"
81
- ? "usage exceeded the archive threshold"
82
- : "usage exceeded the stale threshold",
83
- };
84
- writeMutationJournal(workspaceRoot, {
85
- schema: "litcodex.skill-transaction/v1",
86
- operation: "curator-transition",
87
- ledger,
88
- usageAfter: updated,
89
- copies: [
90
- { kind: "backup", relativePath: `${runId}/${skillId}` },
91
- ...(transition === "archived"
92
- ? [{ kind: "archive", relativePath: `${skillId}/${runId}` }]
93
- : []),
94
- ],
95
- }, options.env);
96
- recoverMutationJournalWhileLocked(workspaceRoot, options.env, { operation: "curator-transition" });
97
- sidecar = updated;
98
- ledgerIds.push(ledger.id);
99
- if (transition === "archived")
100
- archived.push(skillId);
101
- else
102
- stale.push(skillId);
103
- }
104
- return { stale, archived, skipped, ledgerIds };
105
- }));
106
- }
107
- export function assertCuratorNeverDeletes() {
108
- if (DEFAULT_SKILL_LOOP_CONFIG.curator.delete !== false) {
109
- throw new SkillLoopError("CURATOR_CONFIG_INVALID", "the curator delete setting must remain false");
110
- }
111
- return false;
112
- }
@@ -1,19 +0,0 @@
1
- interface PendingOptions {
2
- readonly now?: () => Date;
3
- readonly env?: NodeJS.ProcessEnv | undefined;
4
- readonly beforeRead?: ((path: string) => void) | undefined;
5
- /** Test-only race seam; production callers leave this unset. */
6
- readonly afterEnumerate?: (() => void) | undefined;
7
- /** Test-only race seam; production callers leave this unset. */
8
- readonly beforeWrite?: ((path: string) => void) | undefined;
9
- /** Test-only last-boundary race seam; production callers leave this unset. */
10
- readonly afterWriteVerify?: ((path: string) => void) | undefined;
11
- }
12
- export declare function markPendingReviews(workspaceRoot: string, input: unknown, options?: PendingOptions): {
13
- readonly marked: number;
14
- readonly skipped: number;
15
- };
16
- export declare function pendingReviewNotice(workspaceRoot: string, options?: PendingOptions): string | null;
17
- export declare function pendingReviewDirectories(workspaceRoot: string, options?: PendingOptions): string[];
18
- export declare function markReviewsComplete(workspaceRoot: string, timestamp: string): void;
19
- export {};