@paths.design/caws-cli 11.1.5 → 11.1.7
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 +1 -1
- package/dist/init/hook-packs/manifest-claude-code.d.ts +1 -1
- package/dist/init/hook-packs/manifest-claude-code.d.ts.map +1 -1
- package/dist/init/hook-packs/manifest-claude-code.js +59 -6
- package/dist/init/hook-packs/manifest-claude-code.js.map +1 -1
- package/dist/init/hook-packs/types.js +1 -1
- package/dist/init/hook-packs/types.js.map +1 -1
- package/dist/shell/commands/agents.d.ts +49 -0
- package/dist/shell/commands/agents.d.ts.map +1 -0
- package/dist/shell/commands/agents.js +577 -0
- package/dist/shell/commands/agents.js.map +1 -0
- package/dist/shell/commands/claim.d.ts.map +1 -1
- package/dist/shell/commands/claim.js +3 -4
- package/dist/shell/commands/claim.js.map +1 -1
- package/dist/shell/commands/status.d.ts +12 -0
- package/dist/shell/commands/status.d.ts.map +1 -1
- package/dist/shell/commands/status.js +236 -21
- package/dist/shell/commands/status.js.map +1 -1
- package/dist/shell/commands/worktree.d.ts +9 -0
- package/dist/shell/commands/worktree.d.ts.map +1 -1
- package/dist/shell/commands/worktree.js +302 -0
- package/dist/shell/commands/worktree.js.map +1 -1
- package/dist/shell/index.d.ts +4 -2
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +12 -1
- package/dist/shell/index.js.map +1 -1
- package/dist/shell/register.d.ts.map +1 -1
- package/dist/shell/register.js +150 -0
- package/dist/shell/register.js.map +1 -1
- package/dist/shell/render/status.d.ts +7 -1
- package/dist/shell/render/status.d.ts.map +1 -1
- package/dist/shell/render/status.js +72 -0
- package/dist/shell/render/status.js.map +1 -1
- package/dist/store/agents-store.d.ts.map +1 -1
- package/dist/store/agents-store.js +9 -0
- package/dist/store/agents-store.js.map +1 -1
- package/dist/store/apply-patch.d.ts.map +1 -1
- package/dist/store/apply-patch.js +15 -0
- package/dist/store/apply-patch.js.map +1 -1
- package/dist/store/doctor-snapshot.d.ts.map +1 -1
- package/dist/store/doctor-snapshot.js +143 -3
- package/dist/store/doctor-snapshot.js.map +1 -1
- package/dist/store/git-sparse-checkout.d.ts +25 -0
- package/dist/store/git-sparse-checkout.d.ts.map +1 -0
- package/dist/store/git-sparse-checkout.js +101 -0
- package/dist/store/git-sparse-checkout.js.map +1 -0
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +10 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/leases-store.d.ts +89 -0
- package/dist/store/leases-store.d.ts.map +1 -0
- package/dist/store/leases-store.js +369 -0
- package/dist/store/leases-store.js.map +1 -0
- package/dist/store/lifecycle-transaction.d.ts.map +1 -1
- package/dist/store/lifecycle-transaction.js +34 -1
- package/dist/store/lifecycle-transaction.js.map +1 -1
- package/dist/store/rules.d.ts +21 -1
- package/dist/store/rules.d.ts.map +1 -1
- package/dist/store/rules.js +22 -0
- package/dist/store/rules.js.map +1 -1
- package/dist/store/types.d.ts +25 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/worktrees-migration.d.ts +141 -0
- package/dist/store/worktrees-migration.d.ts.map +1 -0
- package/dist/store/worktrees-migration.js +356 -0
- package/dist/store/worktrees-migration.js.map +1 -0
- package/dist/store/worktrees-writer.d.ts.map +1 -1
- package/dist/store/worktrees-writer.js +37 -1
- package/dist/store/worktrees-writer.js.map +1 -1
- package/package.json +2 -2
- package/templates/hook-packs/claude-code/CLAUDE.md +5 -5
- package/templates/hook-packs/claude-code/agent-heartbeat.sh +131 -0
- package/templates/hook-packs/claude-code/agent-register.sh +62 -0
- package/templates/hook-packs/claude-code/agent-stop.sh +51 -0
- package/templates/hook-packs/claude-code/audit.sh +1 -1
- package/templates/hook-packs/claude-code/block-dangerous.sh +1 -1
- package/templates/hook-packs/claude-code/classify_command.py +454 -12
- package/templates/hook-packs/claude-code/dispatch/post_tool_use.sh +1 -1
- package/templates/hook-packs/claude-code/dispatch/pre_tool_use.sh +11 -2
- package/templates/hook-packs/claude-code/dispatch/session_start.sh +6 -2
- package/templates/hook-packs/claude-code/dispatch/stop.sh +7 -2
- package/templates/hook-packs/claude-code/guard-strikes.sh +1 -1
- package/templates/hook-packs/claude-code/lib/parse-input.sh +1 -1
- package/templates/hook-packs/claude-code/lib/run-handlers.sh +1 -1
- package/templates/hook-packs/claude-code/reset-danger-latch.sh +1 -1
- package/templates/hook-packs/claude-code/reset-strikes.sh +1 -1
- package/templates/hook-packs/claude-code/runtime-paths.sh +1 -1
- package/templates/hook-packs/claude-code/scope-guard.sh +1 -1
- package/templates/hook-packs/claude-code/session-caws-status.sh +7 -1
- package/templates/hook-packs/claude-code/session-log.sh +1 -1
- package/templates/hook-packs/claude-code/worktree-guard.sh +130 -4
- package/templates/hook-packs/claude-code/worktree-write-guard.sh +133 -18
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Sparse-checkout helper for CAWS-created worktrees
|
|
3
|
+
// (WORKTREE-SPEC-AUTHORITY-CONTROL-PLANE-001 A1).
|
|
4
|
+
//
|
|
5
|
+
// CAWS state is control-plane. The .caws/specs/ directory exists exactly
|
|
6
|
+
// once for the project, owned by the main checkout. When `caws worktree
|
|
7
|
+
// create` adds a linked worktree, git's default full checkout would
|
|
8
|
+
// materialize .caws/specs/<id>.yaml into the worktree filesystem,
|
|
9
|
+
// producing the v10.2 split-brain authority class: an editable spec
|
|
10
|
+
// copy inside the worktree, divergent from control-plane bytes,
|
|
11
|
+
// silently consulted by anything that walks cwd upward.
|
|
12
|
+
//
|
|
13
|
+
// This helper configures non-cone sparse-checkout on a freshly-added
|
|
14
|
+
// worktree so the .caws/specs/ tree is excluded from checkout. The
|
|
15
|
+
// rest of the worktree is a normal full checkout — the historic
|
|
16
|
+
// objection to sparse-checkout (broken cross-module imports caused by
|
|
17
|
+
// nearly-empty worktrees) is preserved by including everything OTHER
|
|
18
|
+
// than the authority files.
|
|
19
|
+
//
|
|
20
|
+
// Sparse-checkout vs the worktree-guard.sh hook policy: the hook
|
|
21
|
+
// (`.claude/hooks/worktree-guard.sh:52-56`) blocks agent-issued
|
|
22
|
+
// `git sparse-checkout` commands because sparse-checkout can be
|
|
23
|
+
// misused to hide source files and break work. This helper's use is
|
|
24
|
+
// different: it excludes ONLY the .caws/specs/ authority files, never
|
|
25
|
+
// source code, and runs from the CLI writer (via child_process.spawn)
|
|
26
|
+
// which does not go through the Bash tool hook surface. The hook's
|
|
27
|
+
// purpose is preserved.
|
|
28
|
+
//
|
|
29
|
+
// Pattern: `/*` includes everything; `!/.caws/specs/` excludes the
|
|
30
|
+
// authority directory. Non-cone mode is required because cone mode
|
|
31
|
+
// would force enumeration of all top-level directories. Non-cone
|
|
32
|
+
// sparse-checkout requires git 2.27+, which is documented in the
|
|
33
|
+
// spec's non_functional.reliability clause.
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.configureWorktreeSparseCheckout = configureWorktreeSparseCheckout;
|
|
36
|
+
const child_process_1 = require("child_process");
|
|
37
|
+
/**
|
|
38
|
+
* Configure non-cone sparse-checkout on `wtPath` so that `.caws/specs/`
|
|
39
|
+
* is excluded from checkout, then run `git checkout` to materialize the
|
|
40
|
+
* remaining tree.
|
|
41
|
+
*
|
|
42
|
+
* Returns Result-shape `{ ok: true }` on success or `{ ok: false,
|
|
43
|
+
* reason }` on the first failing git invocation. The caller is
|
|
44
|
+
* responsible for compensating side effects (typically by running
|
|
45
|
+
* `git worktree remove --force <wtPath>` on the partially-created
|
|
46
|
+
* worktree).
|
|
47
|
+
*
|
|
48
|
+
* IMPORTANT: this function does NOT call `git worktree add`. The caller
|
|
49
|
+
* must have already added the worktree with `--no-checkout` so that no
|
|
50
|
+
* files have been materialized yet. Calling this on a worktree that
|
|
51
|
+
* was added with a normal full checkout would not retroactively remove
|
|
52
|
+
* already-checked-out `.caws/specs/` files.
|
|
53
|
+
*/
|
|
54
|
+
function configureWorktreeSparseCheckout(wtPath) {
|
|
55
|
+
// 1) Initialize sparse-checkout in non-cone mode.
|
|
56
|
+
const initResult = runGit(wtPath, ['sparse-checkout', 'init', '--no-cone']);
|
|
57
|
+
if (!initResult.ok)
|
|
58
|
+
return { ok: false, reason: initResult.reason, step: 'init' };
|
|
59
|
+
// 2) Set the pattern: include everything, exclude .caws/specs/.
|
|
60
|
+
// Non-cone mode interprets these as gitignore-style patterns
|
|
61
|
+
// relative to the worktree root. The leading slash in '/.caws/specs/'
|
|
62
|
+
// anchors the exclusion to the worktree root (not subdirectories
|
|
63
|
+
// named .caws/specs/ further down — there are none in this
|
|
64
|
+
// project, but the anchor is correct discipline).
|
|
65
|
+
const setResult = runGit(wtPath, [
|
|
66
|
+
'sparse-checkout',
|
|
67
|
+
'set',
|
|
68
|
+
'--no-cone',
|
|
69
|
+
'/*',
|
|
70
|
+
'!/.caws/specs/',
|
|
71
|
+
]);
|
|
72
|
+
if (!setResult.ok)
|
|
73
|
+
return { ok: false, reason: setResult.reason, step: 'set' };
|
|
74
|
+
// 3) Materialize the included files. `git worktree add --no-checkout`
|
|
75
|
+
// leaves the worktree empty; this populates everything sparse-
|
|
76
|
+
// checkout admits.
|
|
77
|
+
const checkoutResult = runGit(wtPath, ['checkout']);
|
|
78
|
+
if (!checkoutResult.ok)
|
|
79
|
+
return { ok: false, reason: checkoutResult.reason, step: 'checkout' };
|
|
80
|
+
return { ok: true };
|
|
81
|
+
}
|
|
82
|
+
function runGit(cwd, args) {
|
|
83
|
+
try {
|
|
84
|
+
const stdout = (0, child_process_1.execFileSync)('git', [...args], {
|
|
85
|
+
cwd,
|
|
86
|
+
encoding: 'utf8',
|
|
87
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
88
|
+
});
|
|
89
|
+
return { ok: true, stdout: stdout.toString() };
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
const cause = e;
|
|
93
|
+
const stderr = cause.stderr instanceof Buffer
|
|
94
|
+
? cause.stderr.toString()
|
|
95
|
+
: typeof cause.stderr === 'string'
|
|
96
|
+
? cause.stderr
|
|
97
|
+
: (cause.message ?? 'unknown git error');
|
|
98
|
+
return { ok: false, reason: stderr.trim() };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=git-sparse-checkout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-sparse-checkout.js","sourceRoot":"","sources":["../../src/store/git-sparse-checkout.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,kDAAkD;AAClD,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,oEAAoE;AACpE,kEAAkE;AAClE,oEAAoE;AACpE,gEAAgE;AAChE,wDAAwD;AACxD,EAAE;AACF,qEAAqE;AACrE,mEAAmE;AACnE,gEAAgE;AAChE,sEAAsE;AACtE,qEAAqE;AACrE,4BAA4B;AAC5B,EAAE;AACF,iEAAiE;AACjE,gEAAgE;AAChE,gEAAgE;AAChE,oEAAoE;AACpE,sEAAsE;AACtE,sEAAsE;AACtE,mEAAmE;AACnE,wBAAwB;AACxB,EAAE;AACF,mEAAmE;AACnE,mEAAmE;AACnE,iEAAiE;AACjE,iEAAiE;AACjE,4CAA4C;;AAqB5C,0EA8BC;AAjDD,iDAA6C;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,+BAA+B,CAC7C,MAAc;IAEd,kDAAkD;IAClD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5E,IAAI,CAAC,UAAU,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAElF,gEAAgE;IAChE,gEAAgE;IAChE,yEAAyE;IACzE,oEAAoE;IACpE,8DAA8D;IAC9D,qDAAqD;IACrD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE;QAC/B,iBAAiB;QACjB,KAAK;QACL,WAAW;QACX,IAAI;QACJ,gBAAgB;KACjB,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAE/E,sEAAsE;IACtE,kEAAkE;IAClE,sBAAsB;IACtB,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,cAAc,CAAC,EAAE;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAExE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,IAAuB;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;YAC5C,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,CAAmD,CAAC;QAClE,MAAM,MAAM,GACV,KAAK,CAAC,MAAM,YAAY,MAAM;YAC5B,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;YACzB,CAAC,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;gBAChC,CAAC,CAAC,KAAK,CAAC,MAAM;gBACd,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,mBAAmB,CAAC,CAAC;QAC/C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9C,CAAC;AACH,CAAC"}
|
package/dist/store/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export { loadWorktrees } from './worktrees-store';
|
|
|
12
12
|
export { loadAgents } from './agents-store';
|
|
13
13
|
export { appendEvent, loadEvents } from './events-store';
|
|
14
14
|
export { applyRegistryPatch } from './apply-patch';
|
|
15
|
+
export { safeLeaseFilename, loadLeases, applyLeasePatch, applyLeasePatches, pruneLeasesByStatus, } from './leases-store';
|
|
16
|
+
export type { LoadLeasesResult, PruneOptions, PruneResult, } from './leases-store';
|
|
15
17
|
export { loadWaivers, writeWaiver, markRevoked } from './waivers-store';
|
|
16
18
|
export type { WaiversLoadResult } from './waivers-store';
|
|
17
19
|
export { initProject, DEFAULT_POLICY_YAML } from './init-store';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAKnD,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,GACf,MAAM,mBAAmB,CAAC"}
|
package/dist/store/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// It is consumed programmatically; no public CLI commands are registered
|
|
6
6
|
// here. CLI command surface lands in Slice 5c.
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.composeStoreSnapshot = exports.composeDoctorSnapshot = exports.DEFAULT_POLICY_YAML = exports.initProject = exports.markRevoked = exports.writeWaiver = exports.loadWaivers = exports.applyRegistryPatch = exports.loadEvents = exports.appendEvent = exports.loadAgents = exports.loadWorktrees = exports.loadPolicy = exports.loadSpecs = exports.readYamlSource = exports.readYamlFile = exports.readJsonFile = exports.writeFileAtomic = exports.fsyncDir = exports.storeDiagnostic = exports.resolveRepoRoot = exports.defaultGitRunner = exports.STORE_RULE_PREFIXES = exports.STORE_RULES = void 0;
|
|
8
|
+
exports.composeStoreSnapshot = exports.composeDoctorSnapshot = exports.DEFAULT_POLICY_YAML = exports.initProject = exports.markRevoked = exports.writeWaiver = exports.loadWaivers = exports.pruneLeasesByStatus = exports.applyLeasePatches = exports.applyLeasePatch = exports.loadLeases = exports.safeLeaseFilename = exports.applyRegistryPatch = exports.loadEvents = exports.appendEvent = exports.loadAgents = exports.loadWorktrees = exports.loadPolicy = exports.loadSpecs = exports.readYamlSource = exports.readYamlFile = exports.readJsonFile = exports.writeFileAtomic = exports.fsyncDir = exports.storeDiagnostic = exports.resolveRepoRoot = exports.defaultGitRunner = exports.STORE_RULE_PREFIXES = exports.STORE_RULES = void 0;
|
|
9
9
|
var rules_1 = require("./rules");
|
|
10
10
|
Object.defineProperty(exports, "STORE_RULES", { enumerable: true, get: function () { return rules_1.STORE_RULES; } });
|
|
11
11
|
Object.defineProperty(exports, "STORE_RULE_PREFIXES", { enumerable: true, get: function () { return rules_1.STORE_RULE_PREFIXES; } });
|
|
@@ -34,6 +34,15 @@ Object.defineProperty(exports, "appendEvent", { enumerable: true, get: function
|
|
|
34
34
|
Object.defineProperty(exports, "loadEvents", { enumerable: true, get: function () { return events_store_1.loadEvents; } });
|
|
35
35
|
var apply_patch_1 = require("./apply-patch");
|
|
36
36
|
Object.defineProperty(exports, "applyRegistryPatch", { enumerable: true, get: function () { return apply_patch_1.applyRegistryPatch; } });
|
|
37
|
+
// ─── leases (MULTI-AGENT-ACTIVITY-REGISTRY-001) ──────────────────────────
|
|
38
|
+
// Lease I/O surface — separate from applyRegistryPatch. LeasePatch is
|
|
39
|
+
// applied ONLY through applyLeasePatch / applyLeasePatches.
|
|
40
|
+
var leases_store_1 = require("./leases-store");
|
|
41
|
+
Object.defineProperty(exports, "safeLeaseFilename", { enumerable: true, get: function () { return leases_store_1.safeLeaseFilename; } });
|
|
42
|
+
Object.defineProperty(exports, "loadLeases", { enumerable: true, get: function () { return leases_store_1.loadLeases; } });
|
|
43
|
+
Object.defineProperty(exports, "applyLeasePatch", { enumerable: true, get: function () { return leases_store_1.applyLeasePatch; } });
|
|
44
|
+
Object.defineProperty(exports, "applyLeasePatches", { enumerable: true, get: function () { return leases_store_1.applyLeasePatches; } });
|
|
45
|
+
Object.defineProperty(exports, "pruneLeasesByStatus", { enumerable: true, get: function () { return leases_store_1.pruneLeasesByStatus; } });
|
|
37
46
|
var waivers_store_1 = require("./waivers-store");
|
|
38
47
|
Object.defineProperty(exports, "loadWaivers", { enumerable: true, get: function () { return waivers_store_1.loadWaivers; } });
|
|
39
48
|
Object.defineProperty(exports, "writeWaiver", { enumerable: true, get: function () { return waivers_store_1.writeWaiver; } });
|
package/dist/store/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":";AAAA,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,+CAA+C;;;AAE/C,iCAA2D;AAAlD,oGAAA,WAAW,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAUzC,yCAIqB;AAHnB,6GAAA,gBAAgB,OAAA;AAChB,4GAAA,eAAe,OAAA;AACf,4GAAA,eAAe,OAAA;AAIjB,+CAA2D;AAAlD,wGAAA,QAAQ,OAAA;AAAE,+GAAA,eAAe,OAAA;AAClC,2CAA4C;AAAnC,0GAAA,YAAY,OAAA;AACrB,2CAA4D;AAAnD,0GAAA,YAAY,OAAA;AAAE,4GAAA,cAAc,OAAA;AAErC,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,+CAA4C;AAAnC,0GAAA,UAAU,OAAA;AACnB,qDAAkD;AAAzC,gHAAA,aAAa,OAAA;AACtB,+CAA4C;AAAnC,0GAAA,UAAU,OAAA;AACnB,+CAAyD;AAAhD,2GAAA,WAAW,OAAA;AAAE,0GAAA,UAAU,OAAA;AAEhC,6CAAmD;AAA1C,iHAAA,kBAAkB,OAAA;AAE3B,iDAAwE;AAA/D,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAG9C,2CAAgE;AAAvD,yGAAA,WAAW,OAAA;AAAE,iHAAA,mBAAmB,OAAA;AAGzC,qDAG2B;AAFzB,wHAAA,qBAAqB,OAAA;AACrB,uHAAA,oBAAoB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":";AAAA,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,+CAA+C;;;AAE/C,iCAA2D;AAAlD,oGAAA,WAAW,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAUzC,yCAIqB;AAHnB,6GAAA,gBAAgB,OAAA;AAChB,4GAAA,eAAe,OAAA;AACf,4GAAA,eAAe,OAAA;AAIjB,+CAA2D;AAAlD,wGAAA,QAAQ,OAAA;AAAE,+GAAA,eAAe,OAAA;AAClC,2CAA4C;AAAnC,0GAAA,YAAY,OAAA;AACrB,2CAA4D;AAAnD,0GAAA,YAAY,OAAA;AAAE,4GAAA,cAAc,OAAA;AAErC,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,+CAA4C;AAAnC,0GAAA,UAAU,OAAA;AACnB,qDAAkD;AAAzC,gHAAA,aAAa,OAAA;AACtB,+CAA4C;AAAnC,0GAAA,UAAU,OAAA;AACnB,+CAAyD;AAAhD,2GAAA,WAAW,OAAA;AAAE,0GAAA,UAAU,OAAA;AAEhC,6CAAmD;AAA1C,iHAAA,kBAAkB,OAAA;AAE3B,4EAA4E;AAC5E,sEAAsE;AACtE,4DAA4D;AAC5D,+CAMwB;AALtB,iHAAA,iBAAiB,OAAA;AACjB,0GAAA,UAAU,OAAA;AACV,+GAAA,eAAe,OAAA;AACf,iHAAA,iBAAiB,OAAA;AACjB,mHAAA,mBAAmB,OAAA;AAQrB,iDAAwE;AAA/D,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAG9C,2CAAgE;AAAvD,yGAAA,WAAW,OAAA;AAAE,iHAAA,mBAAmB,OAAA;AAGzC,qDAG2B;AAFzB,wHAAA,qBAAqB,OAAA;AACrB,uHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type Diagnostic, type LeasePatch, type LeaseRegistry, type Result } from '@paths.design/caws-kernel';
|
|
2
|
+
export interface LoadLeasesResult {
|
|
3
|
+
readonly leases: LeaseRegistry;
|
|
4
|
+
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validate a session_id for filesystem safety, returning the filename
|
|
8
|
+
* to use (with .json suffix) on success.
|
|
9
|
+
*/
|
|
10
|
+
export declare function safeLeaseFilename(sessionId: unknown): Result<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Load all lease files under .caws/leases/.
|
|
13
|
+
*
|
|
14
|
+
* LENIENT per file: a malformed individual lease produces a diagnostic
|
|
15
|
+
* in the returned diagnostics array and is excluded from the registry;
|
|
16
|
+
* the call returns ok with the parseable subset.
|
|
17
|
+
*
|
|
18
|
+
* STRICT on directory: an unreadable .caws/leases/ directory returns
|
|
19
|
+
* err with LEASE_DIR_UNREADABLE. A missing directory returns
|
|
20
|
+
* ok({ leases: {}, diagnostics: [] }) — leases are operational cache;
|
|
21
|
+
* absence is normal.
|
|
22
|
+
*
|
|
23
|
+
* Per-file failure classes (each emits one diagnostic, excludes the file):
|
|
24
|
+
* - filename does not match the lease pattern (skipped silently —
|
|
25
|
+
* these are not lease files, just other content in the dir)
|
|
26
|
+
* - JSON parse failure → LEASE_FILE_MALFORMED
|
|
27
|
+
* - JSON parses but is not an object → LEASE_FILE_MALFORMED
|
|
28
|
+
* - session_id mismatch between filename and content → LEASE_FILE_MALFORMED
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadLeases(cawsDir: string): Result<LoadLeasesResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Apply a single LeasePatch via atomic per-file write.
|
|
33
|
+
*
|
|
34
|
+
* Creates the leases directory if missing. No lock acquired (per spec
|
|
35
|
+
* invariant 11). No event emitted (per spec invariant 10 and doctrine
|
|
36
|
+
* §6 invariant 10).
|
|
37
|
+
*
|
|
38
|
+
* Patch semantics:
|
|
39
|
+
* - write_lease: serialize patch.lease as JSON, atomic-write to
|
|
40
|
+
* <cawsDir>/leases/<safe-session-id>.json.
|
|
41
|
+
* - mark_stopped: read existing lease file; if absent, return ok with
|
|
42
|
+
* a warning diagnostic (NOT a fabricated record); if present,
|
|
43
|
+
* update status='stopped', stopped_at=patch.transitioned_at,
|
|
44
|
+
* last_seen_reason='session_stop'; atomic-write back.
|
|
45
|
+
* - delete_lease: fs.unlinkSync the lease file; idempotent on absence.
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyLeasePatch(cawsDir: string, patch: LeasePatch): Result<{
|
|
48
|
+
readonly wrote: boolean;
|
|
49
|
+
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Apply a batch of lease patches. Per-patch failures do NOT abort the
|
|
53
|
+
* batch — each patch's diagnostics are aggregated into the return.
|
|
54
|
+
*
|
|
55
|
+
* Use for operator commands like prune that emit multiple delete_lease
|
|
56
|
+
* patches. Single-session register/heartbeat/stop go through
|
|
57
|
+
* applyLeasePatch directly.
|
|
58
|
+
*/
|
|
59
|
+
export declare function applyLeasePatches(cawsDir: string, patches: ReadonlyArray<LeasePatch>): Result<{
|
|
60
|
+
readonly applied: number;
|
|
61
|
+
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Operator-invoked prune: delete lease files matching a status + age
|
|
65
|
+
* threshold.
|
|
66
|
+
*
|
|
67
|
+
* Selection: status === target AND (now - reference) > retentionMs, where
|
|
68
|
+
* reference is `stopped_at` for status='stopped' and `last_active` for
|
|
69
|
+
* status='active' (with TTL-based read-side 'stale' bucketing).
|
|
70
|
+
*
|
|
71
|
+
* Default `dryRun: true` (caller must explicitly pass false to delete).
|
|
72
|
+
* Returns count of files that would be / were deleted plus any
|
|
73
|
+
* diagnostics from the delete operations.
|
|
74
|
+
*/
|
|
75
|
+
export interface PruneOptions {
|
|
76
|
+
readonly status: 'stopped' | 'stale';
|
|
77
|
+
/** Active records whose age exceeds this are bucketed as stale for the prune decision. */
|
|
78
|
+
readonly staleTtlMs?: number;
|
|
79
|
+
readonly retentionMs: number;
|
|
80
|
+
readonly now: Date;
|
|
81
|
+
readonly dryRun?: boolean;
|
|
82
|
+
}
|
|
83
|
+
export interface PruneResult {
|
|
84
|
+
readonly candidates: ReadonlyArray<string>;
|
|
85
|
+
readonly deleted: ReadonlyArray<string>;
|
|
86
|
+
readonly diagnostics: ReadonlyArray<Diagnostic>;
|
|
87
|
+
}
|
|
88
|
+
export declare function pruneLeasesByStatus(cawsDir: string, opts: PruneOptions): Result<PruneResult>;
|
|
89
|
+
//# sourceMappingURL=leases-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leases-store.d.ts","sourceRoot":"","sources":["../../src/store/leases-store.ts"],"names":[],"mappings":"AAoCA,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AA+BnC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAuCpE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,CA6FpE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,GAChB,MAAM,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;CAAE,CAAC,CAmGtF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,GACjC,MAAM,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;CAAE,CAAC,CAevF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjD;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,GACjB,MAAM,CAAC,WAAW,CAAC,CAyDrB"}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Agent-lease store — the SOLE I/O surface for .caws/leases/.
|
|
3
|
+
//
|
|
4
|
+
// MULTI-AGENT-ACTIVITY-REGISTRY-001 acceptance A5–A8, A12.
|
|
5
|
+
//
|
|
6
|
+
// Architectural separation (load-bearing — see spec invariant 2):
|
|
7
|
+
//
|
|
8
|
+
// - This module owns ALL lease I/O. apply-patch.ts is NOT extended to
|
|
9
|
+
// handle LeasePatch. Lease writes never flow through applyRegistryPatch.
|
|
10
|
+
// Routing lease writes through the governance apply path would re-merge
|
|
11
|
+
// the operational-cache / governance-state boundary this slice exists
|
|
12
|
+
// to preserve.
|
|
13
|
+
//
|
|
14
|
+
// - Lease writes are NEVER inside lifecycle-transaction. They never block
|
|
15
|
+
// work, never corrupt governance state, and a write failure is warn-
|
|
16
|
+
// and-continue (per doctrine §6 invariant 11).
|
|
17
|
+
//
|
|
18
|
+
// - Lease writes NEVER append events.jsonl (per doctrine §6 invariant 10).
|
|
19
|
+
// Events are durable governance facts; leases are operational cache.
|
|
20
|
+
//
|
|
21
|
+
// - loadLeases is LENIENT per file. A single malformed lease file
|
|
22
|
+
// produces a diagnostic and is excluded from the returned registry;
|
|
23
|
+
// the call still returns ok. Only an unreadable lease directory
|
|
24
|
+
// causes the call to fail.
|
|
25
|
+
//
|
|
26
|
+
// - safeLeaseFilename enforces a strict character allowlist
|
|
27
|
+
// (^[A-Za-z0-9._:-]+$) at the I/O boundary. The kernel constructs
|
|
28
|
+
// records; the store decides what is filesystem-safe. The literal
|
|
29
|
+
// 'unknown' is REFUSED (would collide across all anonymous sessions).
|
|
30
|
+
//
|
|
31
|
+
// - mark_stopped against a missing lease is a warn no-op, NOT a
|
|
32
|
+
// fabricated record. Stopping a session we never registered is
|
|
33
|
+
// evidence of a lifecycle mismatch, not a write opportunity.
|
|
34
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
35
|
+
if (k2 === undefined) k2 = k;
|
|
36
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
37
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
38
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(o, k2, desc);
|
|
41
|
+
}) : (function(o, m, k, k2) {
|
|
42
|
+
if (k2 === undefined) k2 = k;
|
|
43
|
+
o[k2] = m[k];
|
|
44
|
+
}));
|
|
45
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
46
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
47
|
+
}) : function(o, v) {
|
|
48
|
+
o["default"] = v;
|
|
49
|
+
});
|
|
50
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
51
|
+
var ownKeys = function(o) {
|
|
52
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
53
|
+
var ar = [];
|
|
54
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
55
|
+
return ar;
|
|
56
|
+
};
|
|
57
|
+
return ownKeys(o);
|
|
58
|
+
};
|
|
59
|
+
return function (mod) {
|
|
60
|
+
if (mod && mod.__esModule) return mod;
|
|
61
|
+
var result = {};
|
|
62
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
63
|
+
__setModuleDefault(result, mod);
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
})();
|
|
67
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
68
|
+
exports.safeLeaseFilename = safeLeaseFilename;
|
|
69
|
+
exports.loadLeases = loadLeases;
|
|
70
|
+
exports.applyLeasePatch = applyLeasePatch;
|
|
71
|
+
exports.applyLeasePatches = applyLeasePatches;
|
|
72
|
+
exports.pruneLeasesByStatus = pruneLeasesByStatus;
|
|
73
|
+
const fs = __importStar(require("node:fs"));
|
|
74
|
+
const path = __importStar(require("node:path"));
|
|
75
|
+
const caws_kernel_1 = require("@paths.design/caws-kernel");
|
|
76
|
+
const atomic_write_1 = require("./atomic-write");
|
|
77
|
+
const repo_root_1 = require("./repo-root");
|
|
78
|
+
const rules_1 = require("./rules");
|
|
79
|
+
const LEASES_DIRNAME = 'leases';
|
|
80
|
+
/**
|
|
81
|
+
* Strict-allowlist regex for lease filenames.
|
|
82
|
+
*
|
|
83
|
+
* Allowed characters: ASCII letters, digits, dot, underscore, colon,
|
|
84
|
+
* hyphen. This intentionally rejects:
|
|
85
|
+
* - empty string
|
|
86
|
+
* - 'unknown' (parse-input.sh's fallback when hook payload has no
|
|
87
|
+
* session_id; writing 'unknown.json' would collide across every
|
|
88
|
+
* anonymous session)
|
|
89
|
+
* - whitespace
|
|
90
|
+
* - path separators ('/', '\')
|
|
91
|
+
* - parent-directory references ('..')
|
|
92
|
+
* - shell-meta characters
|
|
93
|
+
*
|
|
94
|
+
* UUIDs (8-4-4-4-12 with hyphens) and `caws-<hex>` (resolveSession's mint
|
|
95
|
+
* format) both pass. The regex is the single source of truth; both the
|
|
96
|
+
* kernel and shell layers MUST route filename derivation through
|
|
97
|
+
* safeLeaseFilename, never direct path joins on raw session_id.
|
|
98
|
+
*/
|
|
99
|
+
const LEASE_FILENAME_RE = /^[A-Za-z0-9._:-]+$/;
|
|
100
|
+
/**
|
|
101
|
+
* Validate a session_id for filesystem safety, returning the filename
|
|
102
|
+
* to use (with .json suffix) on success.
|
|
103
|
+
*/
|
|
104
|
+
function safeLeaseFilename(sessionId) {
|
|
105
|
+
if (typeof sessionId !== 'string') {
|
|
106
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_SESSION_ID_INVALID, 'Lease session_id must be a string.', { data: { actual_type: typeof sessionId } }));
|
|
107
|
+
}
|
|
108
|
+
if (sessionId.length === 0) {
|
|
109
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_SESSION_ID_INVALID, 'Lease session_id must be a non-empty string.'));
|
|
110
|
+
}
|
|
111
|
+
if (sessionId === 'unknown') {
|
|
112
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_SESSION_ID_INVALID, "Lease session_id 'unknown' is refused — it would collide across anonymous sessions. " +
|
|
113
|
+
'Hook scripts MUST guard [ -z "$HOOK_SESSION_ID" ] || [ "$HOOK_SESSION_ID" = "unknown" ] before invoking the CLI.', { data: { session_id: sessionId } }));
|
|
114
|
+
}
|
|
115
|
+
if (!LEASE_FILENAME_RE.test(sessionId)) {
|
|
116
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_SESSION_ID_UNSAFE, `Lease session_id "${sessionId}" contains characters outside the strict allowlist ` +
|
|
117
|
+
'^[A-Za-z0-9._:-]+$. Path separators, whitespace, and shell metacharacters are forbidden.', { data: { session_id: sessionId } }));
|
|
118
|
+
}
|
|
119
|
+
return (0, caws_kernel_1.ok)(`${sessionId}.json`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Load all lease files under .caws/leases/.
|
|
123
|
+
*
|
|
124
|
+
* LENIENT per file: a malformed individual lease produces a diagnostic
|
|
125
|
+
* in the returned diagnostics array and is excluded from the registry;
|
|
126
|
+
* the call returns ok with the parseable subset.
|
|
127
|
+
*
|
|
128
|
+
* STRICT on directory: an unreadable .caws/leases/ directory returns
|
|
129
|
+
* err with LEASE_DIR_UNREADABLE. A missing directory returns
|
|
130
|
+
* ok({ leases: {}, diagnostics: [] }) — leases are operational cache;
|
|
131
|
+
* absence is normal.
|
|
132
|
+
*
|
|
133
|
+
* Per-file failure classes (each emits one diagnostic, excludes the file):
|
|
134
|
+
* - filename does not match the lease pattern (skipped silently —
|
|
135
|
+
* these are not lease files, just other content in the dir)
|
|
136
|
+
* - JSON parse failure → LEASE_FILE_MALFORMED
|
|
137
|
+
* - JSON parses but is not an object → LEASE_FILE_MALFORMED
|
|
138
|
+
* - session_id mismatch between filename and content → LEASE_FILE_MALFORMED
|
|
139
|
+
*/
|
|
140
|
+
function loadLeases(cawsDir) {
|
|
141
|
+
const leasesDir = path.join(cawsDir, LEASES_DIRNAME);
|
|
142
|
+
if (!fs.existsSync(leasesDir)) {
|
|
143
|
+
return (0, caws_kernel_1.ok)({ leases: {}, diagnostics: [] });
|
|
144
|
+
}
|
|
145
|
+
let entries;
|
|
146
|
+
try {
|
|
147
|
+
entries = fs.readdirSync(leasesDir);
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_DIR_UNREADABLE, `Lease directory unreadable: ${e.message}`, { subject: leasesDir }));
|
|
151
|
+
}
|
|
152
|
+
const leases = {};
|
|
153
|
+
const diagnostics = [];
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
if (!entry.endsWith('.json'))
|
|
156
|
+
continue;
|
|
157
|
+
const sessionId = entry.slice(0, -'.json'.length);
|
|
158
|
+
if (!LEASE_FILENAME_RE.test(sessionId)) {
|
|
159
|
+
// Not a lease file by our naming convention; ignore silently
|
|
160
|
+
// rather than fabricate a malformed diagnostic for unrelated
|
|
161
|
+
// files an operator may have dropped here.
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const filePath = path.join(leasesDir, entry);
|
|
165
|
+
let raw;
|
|
166
|
+
try {
|
|
167
|
+
raw = fs.readFileSync(filePath, 'utf8');
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
diagnostics.push((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_FILE_MALFORMED, `Lease file unreadable: ${e.message}`, { subject: filePath, data: { session_id: sessionId } }));
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
let parsed;
|
|
174
|
+
try {
|
|
175
|
+
parsed = JSON.parse(raw);
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
diagnostics.push((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_FILE_MALFORMED, `Lease file is not valid JSON: ${e.message}`, { subject: filePath, data: { session_id: sessionId } }));
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
182
|
+
diagnostics.push((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_FILE_MALFORMED, 'Lease file root is not a JSON object.', { subject: filePath, data: { session_id: sessionId } }));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const obj = parsed;
|
|
186
|
+
if (typeof obj['session_id'] !== 'string' || obj['session_id'] !== sessionId) {
|
|
187
|
+
diagnostics.push((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_FILE_MALFORMED, `Lease file session_id "${obj['session_id']}" does not match filename "${sessionId}".`, { subject: filePath, data: { filename_session_id: sessionId, payload_session_id: obj['session_id'] } }));
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// Treat the parsed object as an AgentLease. Field-level shape
|
|
191
|
+
// validation is deferred to a future kernel-side validateAgentLease
|
|
192
|
+
// function; for now, the kernel's TypeScript shape is the structural
|
|
193
|
+
// contract, and ill-typed-but-parseable files load successfully.
|
|
194
|
+
leases[sessionId] = obj;
|
|
195
|
+
}
|
|
196
|
+
return (0, caws_kernel_1.ok)({ leases, diagnostics });
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Apply a single LeasePatch via atomic per-file write.
|
|
200
|
+
*
|
|
201
|
+
* Creates the leases directory if missing. No lock acquired (per spec
|
|
202
|
+
* invariant 11). No event emitted (per spec invariant 10 and doctrine
|
|
203
|
+
* §6 invariant 10).
|
|
204
|
+
*
|
|
205
|
+
* Patch semantics:
|
|
206
|
+
* - write_lease: serialize patch.lease as JSON, atomic-write to
|
|
207
|
+
* <cawsDir>/leases/<safe-session-id>.json.
|
|
208
|
+
* - mark_stopped: read existing lease file; if absent, return ok with
|
|
209
|
+
* a warning diagnostic (NOT a fabricated record); if present,
|
|
210
|
+
* update status='stopped', stopped_at=patch.transitioned_at,
|
|
211
|
+
* last_seen_reason='session_stop'; atomic-write back.
|
|
212
|
+
* - delete_lease: fs.unlinkSync the lease file; idempotent on absence.
|
|
213
|
+
*/
|
|
214
|
+
function applyLeasePatch(cawsDir, patch) {
|
|
215
|
+
const filenameRes = safeLeaseFilename(patch.session_id);
|
|
216
|
+
if (filenameRes.ok === false)
|
|
217
|
+
return filenameRes;
|
|
218
|
+
const filename = filenameRes.value;
|
|
219
|
+
const leasesDir = path.join(cawsDir, LEASES_DIRNAME);
|
|
220
|
+
const filePath = path.join(leasesDir, filename);
|
|
221
|
+
try {
|
|
222
|
+
fs.mkdirSync(leasesDir, { recursive: true });
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_WRITE_FAILED, `Failed to create lease directory: ${e.message}`, { subject: leasesDir }));
|
|
226
|
+
}
|
|
227
|
+
if (patch.kind === 'write_lease') {
|
|
228
|
+
const contents = JSON.stringify(patch.lease, null, 2) + '\n';
|
|
229
|
+
const w = (0, atomic_write_1.writeFileAtomic)(filePath, contents);
|
|
230
|
+
if (w.ok === false)
|
|
231
|
+
return (0, caws_kernel_1.err)(w.errors);
|
|
232
|
+
return (0, caws_kernel_1.ok)({ wrote: true, diagnostics: [] });
|
|
233
|
+
}
|
|
234
|
+
if (patch.kind === 'mark_stopped') {
|
|
235
|
+
if (!fs.existsSync(filePath)) {
|
|
236
|
+
// Stopping a session we never registered is a lifecycle mismatch,
|
|
237
|
+
// not a write opportunity. Surface as a warning diagnostic; do
|
|
238
|
+
// NOT fabricate a historical record.
|
|
239
|
+
const warn = (0, caws_kernel_1.diagnostic)({
|
|
240
|
+
rule: rules_1.STORE_RULES.LEASE_STOP_NO_PRIOR_LEASE,
|
|
241
|
+
authority: 'kernel/diagnostics',
|
|
242
|
+
severity: 'warning',
|
|
243
|
+
message: `mark_stopped: no existing lease for session "${patch.session_id}" — nothing to update.`,
|
|
244
|
+
subject: filePath,
|
|
245
|
+
data: { session_id: patch.session_id },
|
|
246
|
+
});
|
|
247
|
+
return (0, caws_kernel_1.ok)({ wrote: false, diagnostics: [warn] });
|
|
248
|
+
}
|
|
249
|
+
let raw;
|
|
250
|
+
try {
|
|
251
|
+
raw = fs.readFileSync(filePath, 'utf8');
|
|
252
|
+
}
|
|
253
|
+
catch (e) {
|
|
254
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_WRITE_FAILED, `Failed to read existing lease for mark_stopped: ${e.message}`, { subject: filePath }));
|
|
255
|
+
}
|
|
256
|
+
let prior;
|
|
257
|
+
try {
|
|
258
|
+
prior = JSON.parse(raw);
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_FILE_MALFORMED, `Existing lease file is not valid JSON: ${e.message}`, { subject: filePath }));
|
|
262
|
+
}
|
|
263
|
+
const updated = {
|
|
264
|
+
...prior,
|
|
265
|
+
status: 'stopped',
|
|
266
|
+
stopped_at: patch.transitioned_at,
|
|
267
|
+
last_seen_reason: 'session_stop',
|
|
268
|
+
};
|
|
269
|
+
const contents = JSON.stringify(updated, null, 2) + '\n';
|
|
270
|
+
const w = (0, atomic_write_1.writeFileAtomic)(filePath, contents);
|
|
271
|
+
if (w.ok === false)
|
|
272
|
+
return (0, caws_kernel_1.err)(w.errors);
|
|
273
|
+
return (0, caws_kernel_1.ok)({ wrote: true, diagnostics: [] });
|
|
274
|
+
}
|
|
275
|
+
// delete_lease
|
|
276
|
+
if (!fs.existsSync(filePath)) {
|
|
277
|
+
// Idempotent: deleting an absent lease is a no-op success.
|
|
278
|
+
return (0, caws_kernel_1.ok)({ wrote: false, diagnostics: [] });
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
fs.unlinkSync(filePath);
|
|
282
|
+
}
|
|
283
|
+
catch (e) {
|
|
284
|
+
return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LEASE_WRITE_FAILED, `Failed to delete lease file: ${e.message}`, { subject: filePath }));
|
|
285
|
+
}
|
|
286
|
+
return (0, caws_kernel_1.ok)({ wrote: true, diagnostics: [] });
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Apply a batch of lease patches. Per-patch failures do NOT abort the
|
|
290
|
+
* batch — each patch's diagnostics are aggregated into the return.
|
|
291
|
+
*
|
|
292
|
+
* Use for operator commands like prune that emit multiple delete_lease
|
|
293
|
+
* patches. Single-session register/heartbeat/stop go through
|
|
294
|
+
* applyLeasePatch directly.
|
|
295
|
+
*/
|
|
296
|
+
function applyLeasePatches(cawsDir, patches) {
|
|
297
|
+
let applied = 0;
|
|
298
|
+
const diagnostics = [];
|
|
299
|
+
for (const patch of patches) {
|
|
300
|
+
const r = applyLeasePatch(cawsDir, patch);
|
|
301
|
+
if (r.ok === false) {
|
|
302
|
+
diagnostics.push(...r.errors);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (r.value.wrote)
|
|
306
|
+
applied++;
|
|
307
|
+
diagnostics.push(...r.value.diagnostics);
|
|
308
|
+
}
|
|
309
|
+
return (0, caws_kernel_1.ok)({ applied, diagnostics });
|
|
310
|
+
}
|
|
311
|
+
function pruneLeasesByStatus(cawsDir, opts) {
|
|
312
|
+
const dryRun = opts.dryRun ?? true;
|
|
313
|
+
const staleTtlMs = opts.staleTtlMs ?? 30 * 60 * 1000; // 30m default
|
|
314
|
+
const loadRes = loadLeases(cawsDir);
|
|
315
|
+
if (loadRes.ok === false)
|
|
316
|
+
return (0, caws_kernel_1.err)(loadRes.errors);
|
|
317
|
+
const { leases, diagnostics: loadDiags } = loadRes.value;
|
|
318
|
+
const nowMs = opts.now.getTime();
|
|
319
|
+
const candidates = [];
|
|
320
|
+
// Object.values widens index-signature types to unknown[] under
|
|
321
|
+
// strict TS; coerce back to the kernel-declared element type so the
|
|
322
|
+
// loop body can read fields without per-line casts.
|
|
323
|
+
for (const lease of Object.values(leases)) {
|
|
324
|
+
if (opts.status === 'stopped') {
|
|
325
|
+
if (lease.status !== 'stopped')
|
|
326
|
+
continue;
|
|
327
|
+
const stoppedAtMs = lease.stopped_at ? Date.parse(lease.stopped_at) : NaN;
|
|
328
|
+
const reference = Number.isFinite(stoppedAtMs)
|
|
329
|
+
? stoppedAtMs
|
|
330
|
+
: Date.parse(lease.last_active);
|
|
331
|
+
if (!Number.isFinite(reference))
|
|
332
|
+
continue;
|
|
333
|
+
if (nowMs - reference > opts.retentionMs)
|
|
334
|
+
candidates.push(lease.session_id);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
// status === 'stale'
|
|
338
|
+
if (lease.status !== 'active' && lease.status !== 'stopping')
|
|
339
|
+
continue;
|
|
340
|
+
const lastActiveMs = Date.parse(lease.last_active);
|
|
341
|
+
if (!Number.isFinite(lastActiveMs)) {
|
|
342
|
+
// Unparseable → treat as stale for prune purposes.
|
|
343
|
+
candidates.push(lease.session_id);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const age = nowMs - lastActiveMs;
|
|
347
|
+
// Must be stale (age > staleTtl) AND have been stale long enough
|
|
348
|
+
// (age > staleTtl + retention).
|
|
349
|
+
if (age > staleTtlMs && age - staleTtlMs > opts.retentionMs) {
|
|
350
|
+
candidates.push(lease.session_id);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const diagnostics = [...loadDiags];
|
|
355
|
+
const deleted = [];
|
|
356
|
+
if (!dryRun) {
|
|
357
|
+
for (const sessionId of candidates) {
|
|
358
|
+
const r = applyLeasePatch(cawsDir, { kind: 'delete_lease', session_id: sessionId });
|
|
359
|
+
if (r.ok === false) {
|
|
360
|
+
diagnostics.push(...r.errors);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
deleted.push(sessionId);
|
|
364
|
+
diagnostics.push(...r.value.diagnostics);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return (0, caws_kernel_1.ok)({ candidates, deleted, diagnostics });
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=leases-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leases-store.js","sourceRoot":"","sources":["../../src/store/leases-store.ts"],"names":[],"mappings":"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"}
|