@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.
- package/README.md +22 -23
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -38
- package/dist/install/generated-skill-payload-hashes.d.ts +12 -17
- package/dist/install/generated-skill-payload-hashes.js +12 -17
- package/dist/install/skill-catalog.d.ts +1 -1
- package/dist/install/skill-catalog.js +1 -6
- package/dist/install/skill-resource-hashes.d.ts +1 -1
- package/dist/install/skill-resource-hashes.js +1 -1
- package/marketplace/plugins/litcodex/.codex-plugin/plugin.json +1 -1
- package/marketplace/plugins/litcodex/components/auto-update/package.json +1 -1
- package/marketplace/plugins/litcodex/components/comment-checker/package.json +1 -1
- package/marketplace/plugins/litcodex/components/git-bash/package.json +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directive.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/browser-drive.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/deep-interview.md +3 -3
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-comprehend.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-crucible.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-handoff.md +2 -2
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-init.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-plan.md +2 -2
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-recap.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/lit-scientific-visualization.md +2 -2
- package/marketplace/plugins/litcodex/components/lit-loop/directives/litgoal.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/litresearch.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/litwork.md +2 -2
- package/marketplace/plugins/litcodex/components/lit-loop/directives/review-work.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/directives/start-work.md +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/dist/cli.js +3 -20
- package/marketplace/plugins/litcodex/components/lit-loop/dist/codex-hook.d.ts +5 -5
- package/marketplace/plugins/litcodex/components/lit-loop/dist/codex-hook.js +20 -19
- package/marketplace/plugins/litcodex/components/lit-loop/dist/directive.js +1 -1
- package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.d.ts +2 -1
- package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.js +4 -27
- package/marketplace/plugins/litcodex/components/lit-loop/dist/lit-mark.d.ts +2 -0
- package/marketplace/plugins/litcodex/components/lit-loop/dist/lit-mark.js +49 -0
- package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.d.ts +0 -2
- package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.js +0 -2
- package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.d.ts +1 -3
- package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.js +1 -10
- package/marketplace/plugins/litcodex/components/lit-loop/package.json +1 -1
- package/marketplace/plugins/litcodex/components/lsp/package.json +1 -1
- package/marketplace/plugins/litcodex/components/rules/dist/static-injection.js +2 -2
- package/marketplace/plugins/litcodex/components/rules/package.json +1 -1
- package/marketplace/plugins/litcodex/components/start-work-continuation/package.json +1 -1
- package/marketplace/plugins/litcodex/components/telemetry/package.json +1 -1
- package/marketplace/plugins/litcodex/components/wikify-knowledge/package.json +1 -1
- package/marketplace/plugins/litcodex/hooks/hooks.json +19 -19
- package/marketplace/plugins/litcodex/skills/autoconference/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/autoresearch/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/browser-drive/SKILL.md +3 -3
- package/marketplace/plugins/litcodex/skills/browser-drive/scripts/capability-probe.mjs +13 -5
- package/marketplace/plugins/litcodex/skills/coding-session-audit/SKILL.md +2 -2
- package/marketplace/plugins/litcodex/skills/comment-checker/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/debugging/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/deep-interview/SKILL.md +3 -3
- package/marketplace/plugins/litcodex/skills/frontend-ui-ux/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/frontend-ui-ux/references/complete-contract.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-burnoff/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-burnoff-file/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-code/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-commit/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-comprehend/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-crucible/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-fetch/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-handoff/SKILL.md +4 -4
- package/marketplace/plugins/litcodex/skills/lit-init/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-korean/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-loop/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-plan/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-recap/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lit-scientific-visualization/SKILL.md +4 -4
- package/marketplace/plugins/litcodex/skills/lit-team/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/litcodex-contribute-bug-fix/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/litcodex-doctor/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/litcodex-report-bug/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/litgoal/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/litresearch/SKILL.md +2 -2
- package/marketplace/plugins/litcodex/skills/litwork/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lsp/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/lsp-setup/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/refactor/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/review-work/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/rules/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/start-work/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/structural-search/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/visual-qa/SKILL.md +1 -1
- package/marketplace/plugins/litcodex/skills/visual-qa/references/complete-contract.md +1 -1
- package/marketplace/plugins/litcodex/skills/wikify/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/README.md +1 -7
- package/node_modules/@litcodex/lit-loop/directive.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/browser-drive.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/deep-interview.md +3 -3
- package/node_modules/@litcodex/lit-loop/directives/lit-comprehend.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/lit-crucible.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/lit-handoff.md +2 -2
- package/node_modules/@litcodex/lit-loop/directives/lit-init.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/lit-plan.md +2 -2
- package/node_modules/@litcodex/lit-loop/directives/lit-recap.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/lit-scientific-visualization.md +2 -2
- package/node_modules/@litcodex/lit-loop/directives/litgoal.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/litresearch.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/litwork.md +2 -2
- package/node_modules/@litcodex/lit-loop/directives/review-work.md +1 -1
- package/node_modules/@litcodex/lit-loop/directives/start-work.md +1 -1
- package/node_modules/@litcodex/lit-loop/dist/cli.js +3 -20
- package/node_modules/@litcodex/lit-loop/dist/codex-hook.d.ts +5 -5
- package/node_modules/@litcodex/lit-loop/dist/codex-hook.js +20 -19
- package/node_modules/@litcodex/lit-loop/dist/directive.js +1 -1
- package/node_modules/@litcodex/lit-loop/dist/hook-cli.d.ts +2 -1
- package/node_modules/@litcodex/lit-loop/dist/hook-cli.js +4 -27
- package/node_modules/@litcodex/lit-loop/dist/lit-mark.d.ts +2 -0
- package/node_modules/@litcodex/lit-loop/dist/lit-mark.js +49 -0
- package/node_modules/@litcodex/lit-loop/dist/markers.d.ts +0 -2
- package/node_modules/@litcodex/lit-loop/dist/markers.js +0 -2
- package/node_modules/@litcodex/lit-loop/dist/modes.d.ts +1 -3
- package/node_modules/@litcodex/lit-loop/dist/modes.js +1 -10
- package/node_modules/@litcodex/lit-loop/package.json +1 -1
- package/node_modules/@litcodex/lit-loop/skills/browser-drive/SKILL.md +3 -3
- package/node_modules/@litcodex/lit-loop/skills/browser-drive/scripts/capability-probe.mjs +13 -5
- package/node_modules/@litcodex/lit-loop/skills/deep-interview/SKILL.md +3 -3
- package/node_modules/@litcodex/lit-loop/skills/lit-burnoff/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-burnoff-file/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-code/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-commit/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-comprehend/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-crucible/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-fetch/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-handoff/SKILL.md +4 -4
- package/node_modules/@litcodex/lit-loop/skills/lit-init/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-korean/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-loop/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-plan/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-recap/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/lit-scientific-visualization/SKILL.md +4 -4
- package/node_modules/@litcodex/lit-loop/skills/lit-team/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/litgoal/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/litresearch/SKILL.md +2 -2
- package/node_modules/@litcodex/lit-loop/skills/litwork/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/review-work/SKILL.md +1 -1
- package/node_modules/@litcodex/lit-loop/skills/start-work/SKILL.md +1 -1
- package/package.json +2 -2
- package/readme-assets/badge-version.svg +1 -1
- package/readme-assets/cover-motion.webp +0 -0
- package/marketplace/plugins/litcodex/components/lit-loop/directives/skill-observer.md +0 -105
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.d.ts +0 -16
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.js +0 -227
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.d.ts +0 -13
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.js +0 -12
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.d.ts +0 -14
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.js +0 -112
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.d.ts +0 -19
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.js +0 -435
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.js +0 -145
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.d.ts +0 -18
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.js +0 -43
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.d.ts +0 -28
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.js +0 -702
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.d.ts +0 -32
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.js +0 -667
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.js +0 -524
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.d.ts +0 -81
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.js +0 -246
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.d.ts +0 -6
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.js +0 -119
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.d.ts +0 -8
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.js +0 -111
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.d.ts +0 -3
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.js +0 -116
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.d.ts +0 -6
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.js +0 -12
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.d.ts +0 -18
- package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.js +0 -946
- package/marketplace/plugins/litcodex/skills/skill-observer/SKILL.md +0 -215
- package/marketplace/plugins/litcodex/skills/skill-observer/agents/openai.yaml +0 -6
- package/marketplace/plugins/litcodex/skills/skill-observer/references/review-contract.md +0 -77
- package/node_modules/@litcodex/lit-loop/directives/skill-observer.md +0 -105
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.d.ts +0 -16
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.js +0 -227
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.d.ts +0 -13
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.js +0 -12
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.d.ts +0 -14
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.js +0 -112
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.d.ts +0 -19
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.js +0 -435
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.js +0 -145
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.d.ts +0 -18
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.js +0 -43
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.d.ts +0 -28
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.js +0 -702
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.d.ts +0 -32
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.js +0 -667
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.js +0 -524
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.d.ts +0 -81
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.js +0 -246
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.d.ts +0 -6
- package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.js +0 -119
- package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.d.ts +0 -8
- package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.js +0 -111
- package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.d.ts +0 -3
- package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.js +0 -116
- package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.d.ts +0 -6
- package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.js +0 -12
- package/node_modules/@litcodex/lit-loop/dist/skill-observer.d.ts +0 -18
- package/node_modules/@litcodex/lit-loop/dist/skill-observer.js +0 -946
- package/node_modules/@litcodex/lit-loop/skills/skill-observer/SKILL.md +0 -215
- 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 {};
|