@dezycro-ai/agent-plugin 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -98
- package/dist/cli/dezycro.js +50 -0
- package/dist/cli/install.js +7 -0
- package/dist/dezycro-config.d.ts +52 -0
- package/dist/dezycro-config.js +167 -0
- package/dist/gateway/compact-cli.js +8 -0
- package/dist/gateway/proxy.js +35 -0
- package/dist/hooks/lib/router.js +14 -830
- package/dist/schemas/anthropic.d.ts +119 -0
- package/dist/schemas/anthropic.js +43 -0
- package/dist/schemas/dezycro.d.ts +19 -0
- package/dist/schemas/dezycro.js +22 -0
- package/dist/schemas/gateway.d.ts +40 -0
- package/dist/schemas/gateway.js +30 -0
- package/dist/schemas/gating.d.ts +32 -0
- package/dist/schemas/gating.js +15 -0
- package/dist/schemas/index.d.ts +14 -0
- package/dist/schemas/index.js +29 -0
- package/package.json +21 -13
- package/LICENSE +0 -18
- package/bin/resolve-auth.js +0 -112
- package/dist/hooks/lib/authoring.d.ts +0 -118
- package/dist/hooks/lib/authoring.js +0 -277
- package/dist/hooks/lib/command-bus.d.ts +0 -66
- package/dist/hooks/lib/command-bus.js +0 -357
- package/dist/hooks/lib/config.d.ts +0 -28
- package/dist/hooks/lib/config.js +0 -175
- package/dist/hooks/lib/controller-match.d.ts +0 -16
- package/dist/hooks/lib/controller-match.js +0 -96
- package/dist/hooks/lib/coverage.d.ts +0 -17
- package/dist/hooks/lib/coverage.js +0 -66
- package/dist/hooks/lib/hashing.d.ts +0 -8
- package/dist/hooks/lib/hashing.js +0 -49
- package/dist/hooks/lib/logging.d.ts +0 -13
- package/dist/hooks/lib/logging.js +0 -72
- package/dist/hooks/lib/publish-spec.d.ts +0 -17
- package/dist/hooks/lib/publish-spec.js +0 -64
- package/dist/hooks/lib/quality-gate.d.ts +0 -67
- package/dist/hooks/lib/quality-gate.js +0 -187
- package/dist/hooks/lib/router.d.ts +0 -32
- package/dist/hooks/lib/state.d.ts +0 -34
- package/dist/hooks/lib/state.js +0 -245
- package/dist/hooks/lib/undo.d.ts +0 -11
- package/dist/hooks/lib/undo.js +0 -71
- package/dist/hooks/lib/verify.d.ts +0 -28
- package/dist/hooks/lib/verify.js +0 -94
- package/dist/hooks/lib/workbook.d.ts +0 -21
- package/dist/hooks/lib/workbook.js +0 -77
- package/dist/hooks/types.d.ts +0 -293
- package/dist/hooks/types.js +0 -14
- package/install.js +0 -84
- package/setup.js +0 -53
package/dist/hooks/lib/state.js
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* state.ts — atomic read/write of `.dezycro/companion-state.json` per TRD §3.3.
|
|
3
|
-
*
|
|
4
|
-
* Lock acquisition: O_EXCL create of `.dezycro/.companion-state.lock`, retrying
|
|
5
|
-
* with 10ms backoff for up to 500ms. On timeout, the caller no-ops — every
|
|
6
|
-
* write site MUST be idempotent. Stale-lock cleanup is out of scope for V2.0.
|
|
7
|
-
*
|
|
8
|
-
* Hot-path readers (PostToolUse, UserPromptSubmit) call `read()` without the
|
|
9
|
-
* lock — they accept a slightly stale view (TRD §3.3).
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
-
}
|
|
18
|
-
Object.defineProperty(o, k2, desc);
|
|
19
|
-
}) : (function(o, m, k, k2) {
|
|
20
|
-
if (k2 === undefined) k2 = k;
|
|
21
|
-
o[k2] = m[k];
|
|
22
|
-
}));
|
|
23
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
-
}) : function(o, v) {
|
|
26
|
-
o["default"] = v;
|
|
27
|
-
});
|
|
28
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
-
var ownKeys = function(o) {
|
|
30
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
-
var ar = [];
|
|
32
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
-
return ar;
|
|
34
|
-
};
|
|
35
|
-
return ownKeys(o);
|
|
36
|
-
};
|
|
37
|
-
return function (mod) {
|
|
38
|
-
if (mod && mod.__esModule) return mod;
|
|
39
|
-
var result = {};
|
|
40
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
-
__setModuleDefault(result, mod);
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
})();
|
|
45
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports._releaseLock = exports._tryAcquireLock = exports.DEFAULT_COMPANION_STATE = exports.DEFAULT_COMPANION_METRICS = exports.CONTROLLER_EDITS_CAP = exports.HASH_RING_BUFFER_CAP = void 0;
|
|
47
|
-
exports.read = read;
|
|
48
|
-
exports.patch = patch;
|
|
49
|
-
exports.incrementMetric = incrementMetric;
|
|
50
|
-
const fs = __importStar(require("fs"));
|
|
51
|
-
const path = __importStar(require("path"));
|
|
52
|
-
const LOCK_TIMEOUT_MS = 500;
|
|
53
|
-
const LOCK_BACKOFF_MS = 10;
|
|
54
|
-
exports.HASH_RING_BUFFER_CAP = 32;
|
|
55
|
-
exports.CONTROLLER_EDITS_CAP = 64;
|
|
56
|
-
exports.DEFAULT_COMPANION_METRICS = Object.freeze({
|
|
57
|
-
autoDecisionLogs: 0,
|
|
58
|
-
autoIssueLogs: 0,
|
|
59
|
-
autoAssumptionLogs: 0,
|
|
60
|
-
autoTaskStatusLogs: 0,
|
|
61
|
-
undoCount: 0,
|
|
62
|
-
verifyAutoRuns: 0,
|
|
63
|
-
verifyAutoFailures: 0,
|
|
64
|
-
qualityGateFailures: 0,
|
|
65
|
-
contextGateFailures: 0,
|
|
66
|
-
lockContention: 0,
|
|
67
|
-
forceApprovals: 0,
|
|
68
|
-
});
|
|
69
|
-
exports.DEFAULT_COMPANION_STATE = Object.freeze({
|
|
70
|
-
schemaVersion: 1,
|
|
71
|
-
currentSessionId: null,
|
|
72
|
-
authoringMode: false,
|
|
73
|
-
authoringDocId: null,
|
|
74
|
-
authoringDocType: null,
|
|
75
|
-
authoringTranscriptPath: null,
|
|
76
|
-
authoringStartedTs: null,
|
|
77
|
-
pulseCount: 0,
|
|
78
|
-
lastEditTs: null,
|
|
79
|
-
needsSpecPublish: false,
|
|
80
|
-
controllerEditsSinceLastPublish: [],
|
|
81
|
-
coverageSnapshot: null,
|
|
82
|
-
coverageSnapshotTs: null,
|
|
83
|
-
coverageFetchPending: false,
|
|
84
|
-
lastVerifyCompletionTs: null,
|
|
85
|
-
recentDecisionHashes: [],
|
|
86
|
-
recentIssueHashes: [],
|
|
87
|
-
recentAssumptionHashes: [],
|
|
88
|
-
lastAutoWorkbookMutation: null,
|
|
89
|
-
sessionAutoLogCount: 0,
|
|
90
|
-
turnAutoLogCount: 0,
|
|
91
|
-
currentTurnId: 0,
|
|
92
|
-
suppressWorkbookUpdatesUntil: null,
|
|
93
|
-
pendingWorkbookSweep: false,
|
|
94
|
-
pendingWorkbookSweepReason: null,
|
|
95
|
-
lastSeenVerifyCompletionTs: null,
|
|
96
|
-
commandBus: {
|
|
97
|
-
cursor: null,
|
|
98
|
-
lastPollTs: null,
|
|
99
|
-
lastAttemptTs: null,
|
|
100
|
-
consecutiveFailures: 0,
|
|
101
|
-
recentEventIds: [],
|
|
102
|
-
},
|
|
103
|
-
metrics: exports.DEFAULT_COMPANION_METRICS,
|
|
104
|
-
});
|
|
105
|
-
function statePath(repoRoot) {
|
|
106
|
-
return path.join(repoRoot, '.dezycro', 'companion-state.json');
|
|
107
|
-
}
|
|
108
|
-
function lockPath(repoRoot) {
|
|
109
|
-
return path.join(repoRoot, '.dezycro', '.companion-state.lock');
|
|
110
|
-
}
|
|
111
|
-
function tmpPath(repoRoot) {
|
|
112
|
-
return path.join(repoRoot, '.dezycro', '.companion-state.json.tmp');
|
|
113
|
-
}
|
|
114
|
-
function ensureDir(repoRoot) {
|
|
115
|
-
fs.mkdirSync(path.join(repoRoot, '.dezycro'), { recursive: true });
|
|
116
|
-
}
|
|
117
|
-
function cloneDefault() {
|
|
118
|
-
return JSON.parse(JSON.stringify(exports.DEFAULT_COMPANION_STATE));
|
|
119
|
-
}
|
|
120
|
-
function read(repoRoot) {
|
|
121
|
-
const file = statePath(repoRoot);
|
|
122
|
-
try {
|
|
123
|
-
const raw = fs.readFileSync(file, 'utf8');
|
|
124
|
-
const parsed = JSON.parse(raw);
|
|
125
|
-
return {
|
|
126
|
-
...cloneDefault(),
|
|
127
|
-
...parsed,
|
|
128
|
-
metrics: { ...exports.DEFAULT_COMPANION_METRICS, ...(parsed.metrics || {}) },
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
const e = err;
|
|
133
|
-
if (e && e.code === 'ENOENT')
|
|
134
|
-
return cloneDefault();
|
|
135
|
-
// Corrupt JSON — fall back. Caller (Stop hook etc) should still make
|
|
136
|
-
// forward progress; the next successful patch will rewrite.
|
|
137
|
-
return cloneDefault();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function tryAcquireLock(repoRoot) {
|
|
141
|
-
const lp = lockPath(repoRoot);
|
|
142
|
-
const start = Date.now();
|
|
143
|
-
while (Date.now() - start < LOCK_TIMEOUT_MS) {
|
|
144
|
-
try {
|
|
145
|
-
const fd = fs.openSync(lp, 'wx');
|
|
146
|
-
fs.writeSync(fd, String(process.pid));
|
|
147
|
-
fs.closeSync(fd);
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
catch (err) {
|
|
151
|
-
const e = err;
|
|
152
|
-
if (e.code !== 'EEXIST')
|
|
153
|
-
throw err;
|
|
154
|
-
}
|
|
155
|
-
const wait = Date.now() + LOCK_BACKOFF_MS;
|
|
156
|
-
while (Date.now() < wait) { /* spin */ }
|
|
157
|
-
}
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
function releaseLock(repoRoot) {
|
|
161
|
-
try {
|
|
162
|
-
fs.unlinkSync(lockPath(repoRoot));
|
|
163
|
-
}
|
|
164
|
-
catch { /* ignore */ }
|
|
165
|
-
}
|
|
166
|
-
function mergeMetrics(current, incoming) {
|
|
167
|
-
if (!incoming)
|
|
168
|
-
return current;
|
|
169
|
-
return { ...current, ...incoming };
|
|
170
|
-
}
|
|
171
|
-
function appendRing(existing, value, cap) {
|
|
172
|
-
if (!value)
|
|
173
|
-
return existing;
|
|
174
|
-
if (existing.includes(value))
|
|
175
|
-
return existing;
|
|
176
|
-
const next = existing.concat([value]);
|
|
177
|
-
return next.length > cap ? next.slice(next.length - cap) : next;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Atomic patch under O_EXCL lock. Special keys:
|
|
181
|
-
* - metrics: shallow-merged inside (caller can patch one counter).
|
|
182
|
-
* - pushDecisionHash / pushIssueHash / pushAssumptionHash: appended to
|
|
183
|
-
* the corresponding ring buffer (FIFO-capped at 32) instead of replacing.
|
|
184
|
-
* - pushControllerEdit: same idea for controllerEditsSinceLastPublish
|
|
185
|
-
* (FIFO-capped at 64), with replace-by-path semantics.
|
|
186
|
-
*
|
|
187
|
-
* Returns the new state, or null on lock-contention timeout.
|
|
188
|
-
*/
|
|
189
|
-
function patch(repoRoot, _patch) {
|
|
190
|
-
ensureDir(repoRoot);
|
|
191
|
-
if (!tryAcquireLock(repoRoot)) {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
try {
|
|
195
|
-
const current = read(repoRoot);
|
|
196
|
-
const incoming = _patch || {};
|
|
197
|
-
const next = { ...current };
|
|
198
|
-
for (const key of Object.keys(incoming)) {
|
|
199
|
-
const value = incoming[key];
|
|
200
|
-
if (key === 'metrics') {
|
|
201
|
-
next.metrics = mergeMetrics(current.metrics, value);
|
|
202
|
-
}
|
|
203
|
-
else if (key === 'pushDecisionHash') {
|
|
204
|
-
next.recentDecisionHashes = appendRing(current.recentDecisionHashes, value, exports.HASH_RING_BUFFER_CAP);
|
|
205
|
-
}
|
|
206
|
-
else if (key === 'pushIssueHash') {
|
|
207
|
-
next.recentIssueHashes = appendRing(current.recentIssueHashes, value, exports.HASH_RING_BUFFER_CAP);
|
|
208
|
-
}
|
|
209
|
-
else if (key === 'pushAssumptionHash') {
|
|
210
|
-
next.recentAssumptionHashes = appendRing(current.recentAssumptionHashes, value, exports.HASH_RING_BUFFER_CAP);
|
|
211
|
-
}
|
|
212
|
-
else if (key === 'pushControllerEdit') {
|
|
213
|
-
const edit = value;
|
|
214
|
-
const existing = current.controllerEditsSinceLastPublish.filter((e) => e.path !== edit.path);
|
|
215
|
-
const appended = existing.concat([edit]);
|
|
216
|
-
next.controllerEditsSinceLastPublish =
|
|
217
|
-
appended.length > exports.CONTROLLER_EDITS_CAP
|
|
218
|
-
? appended.slice(appended.length - exports.CONTROLLER_EDITS_CAP)
|
|
219
|
-
: appended;
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
// Plain top-level field override.
|
|
223
|
-
next[key] = value;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
const tmp = tmpPath(repoRoot);
|
|
227
|
-
const fd = fs.openSync(tmp, 'w');
|
|
228
|
-
fs.writeSync(fd, JSON.stringify(next, null, 2));
|
|
229
|
-
fs.fsyncSync(fd);
|
|
230
|
-
fs.closeSync(fd);
|
|
231
|
-
fs.renameSync(tmp, statePath(repoRoot));
|
|
232
|
-
return next;
|
|
233
|
-
}
|
|
234
|
-
finally {
|
|
235
|
-
releaseLock(repoRoot);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/** Bump a metric by 1 atomically. Returns null on lock contention. */
|
|
239
|
-
function incrementMetric(repoRoot, metricKey, delta = 1) {
|
|
240
|
-
const current = read(repoRoot).metrics[metricKey] || 0;
|
|
241
|
-
return patch(repoRoot, { metrics: { [metricKey]: current + delta } });
|
|
242
|
-
}
|
|
243
|
-
// Exposed for tests:
|
|
244
|
-
exports._tryAcquireLock = tryAcquireLock;
|
|
245
|
-
exports._releaseLock = releaseLock;
|
package/dist/hooks/lib/undo.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* undo.ts — detects undo phrases in user messages and builds the directive
|
|
3
|
-
* that asks the agent to reverse the last auto-workbook mutation
|
|
4
|
-
* (TRD §5.3.3).
|
|
5
|
-
*/
|
|
6
|
-
import type { LastAutoWorkbookMutation, ReversalDirective } from '../types';
|
|
7
|
-
export declare const UNDO_PHRASES: readonly string[];
|
|
8
|
-
export declare function isUndoMessage(userMessage: unknown): boolean;
|
|
9
|
-
export declare function buildReversalDirective(mutation: LastAutoWorkbookMutation | null): ReversalDirective | null;
|
|
10
|
-
/** TRD §5.3.3: undo window is currentTurnId == createdInTurnId + 1. */
|
|
11
|
-
export declare function isInUndoWindow(mutation: LastAutoWorkbookMutation | null, currentTurnId: number): boolean;
|
package/dist/hooks/lib/undo.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* undo.ts — detects undo phrases in user messages and builds the directive
|
|
3
|
-
* that asks the agent to reverse the last auto-workbook mutation
|
|
4
|
-
* (TRD §5.3.3).
|
|
5
|
-
*/
|
|
6
|
-
'use strict';
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.UNDO_PHRASES = void 0;
|
|
9
|
-
exports.isUndoMessage = isUndoMessage;
|
|
10
|
-
exports.buildReversalDirective = buildReversalDirective;
|
|
11
|
-
exports.isInUndoWindow = isInUndoWindow;
|
|
12
|
-
exports.UNDO_PHRASES = Object.freeze([
|
|
13
|
-
'undo that',
|
|
14
|
-
'no, wrong',
|
|
15
|
-
'revert that',
|
|
16
|
-
'undo the last log',
|
|
17
|
-
'wrong, undo',
|
|
18
|
-
]);
|
|
19
|
-
function isUndoMessage(userMessage) {
|
|
20
|
-
if (typeof userMessage !== 'string')
|
|
21
|
-
return false;
|
|
22
|
-
const m = userMessage.toLowerCase().trim();
|
|
23
|
-
if (!m)
|
|
24
|
-
return false;
|
|
25
|
-
for (let i = 0; i < exports.UNDO_PHRASES.length; i += 1) {
|
|
26
|
-
if (m.includes(exports.UNDO_PHRASES[i]))
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
function buildReversalDirective(mutation) {
|
|
32
|
-
if (!mutation || !mutation.tool || !mutation.entityId)
|
|
33
|
-
return null;
|
|
34
|
-
const id = mutation.entityId;
|
|
35
|
-
switch (mutation.tool) {
|
|
36
|
-
case 'add_decision':
|
|
37
|
-
return {
|
|
38
|
-
tool: 'update_decision',
|
|
39
|
-
args: { id, status: 'INVALIDATED', reason: 'undo by user' },
|
|
40
|
-
humanLine: `Reverting the last auto-logged decision (${id.slice(0, 8)}\u2026) — marking INVALIDATED.`,
|
|
41
|
-
};
|
|
42
|
-
case 'add_issue':
|
|
43
|
-
return {
|
|
44
|
-
tool: 'update_issue',
|
|
45
|
-
args: { id, status: 'CANCELLED', reason: 'undo by user' },
|
|
46
|
-
humanLine: `Reverting the last auto-logged issue (${id.slice(0, 8)}\u2026) — marking CANCELLED.`,
|
|
47
|
-
};
|
|
48
|
-
case 'add_assumption':
|
|
49
|
-
return {
|
|
50
|
-
tool: 'update_issue',
|
|
51
|
-
args: { id, status: 'INVALIDATED', kind: 'ASSUMPTION', reason: 'undo by user' },
|
|
52
|
-
humanLine: `Reverting the last auto-logged assumption (${id.slice(0, 8)}\u2026) — marking INVALIDATED.`,
|
|
53
|
-
};
|
|
54
|
-
case 'update_task':
|
|
55
|
-
if (!mutation.priorStatus)
|
|
56
|
-
return null;
|
|
57
|
-
return {
|
|
58
|
-
tool: 'update_task',
|
|
59
|
-
args: { id, status: mutation.priorStatus },
|
|
60
|
-
humanLine: `Reverting the last auto-task-status change — restoring ${id.slice(0, 8)}\u2026 to ${mutation.priorStatus}.`,
|
|
61
|
-
};
|
|
62
|
-
default:
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/** TRD §5.3.3: undo window is currentTurnId == createdInTurnId + 1. */
|
|
67
|
-
function isInUndoWindow(mutation, currentTurnId) {
|
|
68
|
-
if (!mutation || typeof mutation.createdInTurnId !== 'number')
|
|
69
|
-
return false;
|
|
70
|
-
return currentTurnId === mutation.createdInTurnId + 1;
|
|
71
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* verify.ts — verify-evidence helpers for the pillar-1 pre-DONE gate
|
|
3
|
-
* (TRD §5.1).
|
|
4
|
-
*
|
|
5
|
-
* The PreToolUse hook does NOT shell out to the verifier binary — that lives
|
|
6
|
-
* in the `/dezycro:verify` skill. The hook's job is to detect "this path-linked
|
|
7
|
-
* task is transitioning to DONE/PUSHED without recent passing verifier
|
|
8
|
-
* evidence" and block with a structured message telling the agent to run
|
|
9
|
-
* `/dezycro:verify --path <p>` first.
|
|
10
|
-
*
|
|
11
|
-
* Evidence source: `.dezycro/state.json` (the pre-Companion local state file
|
|
12
|
-
* written by the V1 verify skill). Per-path coverage isn't recorded there in
|
|
13
|
-
* V1 — any recent passing run counts as covering all paths. V2.1 should
|
|
14
|
-
* record covered-paths explicitly.
|
|
15
|
-
*/
|
|
16
|
-
export interface HasRecentPassingVerifyOpts {
|
|
17
|
-
repoRoot?: string;
|
|
18
|
-
paths?: string[];
|
|
19
|
-
maxAgeMinutes?: number;
|
|
20
|
-
}
|
|
21
|
-
export declare function hasRecentPassingVerify(opts: HasRecentPassingVerifyOpts): boolean;
|
|
22
|
-
export interface BuildBlockReasonOpts {
|
|
23
|
-
paths?: string[];
|
|
24
|
-
status?: string;
|
|
25
|
-
}
|
|
26
|
-
export declare function buildBlockReason(opts: BuildBlockReasonOpts): {
|
|
27
|
-
reason: string;
|
|
28
|
-
};
|
package/dist/hooks/lib/verify.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* verify.ts — verify-evidence helpers for the pillar-1 pre-DONE gate
|
|
3
|
-
* (TRD §5.1).
|
|
4
|
-
*
|
|
5
|
-
* The PreToolUse hook does NOT shell out to the verifier binary — that lives
|
|
6
|
-
* in the `/dezycro:verify` skill. The hook's job is to detect "this path-linked
|
|
7
|
-
* task is transitioning to DONE/PUSHED without recent passing verifier
|
|
8
|
-
* evidence" and block with a structured message telling the agent to run
|
|
9
|
-
* `/dezycro:verify --path <p>` first.
|
|
10
|
-
*
|
|
11
|
-
* Evidence source: `.dezycro/state.json` (the pre-Companion local state file
|
|
12
|
-
* written by the V1 verify skill). Per-path coverage isn't recorded there in
|
|
13
|
-
* V1 — any recent passing run counts as covering all paths. V2.1 should
|
|
14
|
-
* record covered-paths explicitly.
|
|
15
|
-
*/
|
|
16
|
-
'use strict';
|
|
17
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
-
if (k2 === undefined) k2 = k;
|
|
19
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
-
}
|
|
23
|
-
Object.defineProperty(o, k2, desc);
|
|
24
|
-
}) : (function(o, m, k, k2) {
|
|
25
|
-
if (k2 === undefined) k2 = k;
|
|
26
|
-
o[k2] = m[k];
|
|
27
|
-
}));
|
|
28
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
-
}) : function(o, v) {
|
|
31
|
-
o["default"] = v;
|
|
32
|
-
});
|
|
33
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
-
var ownKeys = function(o) {
|
|
35
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
-
var ar = [];
|
|
37
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
-
return ar;
|
|
39
|
-
};
|
|
40
|
-
return ownKeys(o);
|
|
41
|
-
};
|
|
42
|
-
return function (mod) {
|
|
43
|
-
if (mod && mod.__esModule) return mod;
|
|
44
|
-
var result = {};
|
|
45
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
-
__setModuleDefault(result, mod);
|
|
47
|
-
return result;
|
|
48
|
-
};
|
|
49
|
-
})();
|
|
50
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
-
exports.hasRecentPassingVerify = hasRecentPassingVerify;
|
|
52
|
-
exports.buildBlockReason = buildBlockReason;
|
|
53
|
-
const fs = __importStar(require("fs"));
|
|
54
|
-
const path = __importStar(require("path"));
|
|
55
|
-
function hasRecentPassingVerify(opts) {
|
|
56
|
-
const o = opts || {};
|
|
57
|
-
const repoRoot = o.repoRoot;
|
|
58
|
-
const maxAgeMinutes = typeof o.maxAgeMinutes === 'number' ? o.maxAgeMinutes : 60;
|
|
59
|
-
if (!repoRoot)
|
|
60
|
-
return false;
|
|
61
|
-
const file = path.join(repoRoot, '.dezycro', 'state.json');
|
|
62
|
-
let parsed;
|
|
63
|
-
try {
|
|
64
|
-
const raw = fs.readFileSync(file, 'utf8');
|
|
65
|
-
parsed = JSON.parse(raw);
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
if (!parsed || typeof parsed !== 'object')
|
|
71
|
-
return false;
|
|
72
|
-
const lastVerifyTs = parsed.lastVerifyTs;
|
|
73
|
-
const lastVerifyRunId = parsed.lastVerifyRunId;
|
|
74
|
-
if (!lastVerifyTs || !lastVerifyRunId)
|
|
75
|
-
return false;
|
|
76
|
-
const ts = Date.parse(lastVerifyTs);
|
|
77
|
-
if (!Number.isFinite(ts))
|
|
78
|
-
return false;
|
|
79
|
-
const ageMs = Date.now() - ts;
|
|
80
|
-
if (ageMs < 0)
|
|
81
|
-
return false;
|
|
82
|
-
if (ageMs > maxAgeMinutes * 60 * 1000)
|
|
83
|
-
return false;
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
function buildBlockReason(opts) {
|
|
87
|
-
const o = opts || {};
|
|
88
|
-
const paths = o.paths || [];
|
|
89
|
-
const status = o.status || 'DONE';
|
|
90
|
-
const pathList = paths.length > 0 ? paths.join(',') : '<paths>';
|
|
91
|
-
const reason = 'Cannot mark task ' + status + ' — no recent passing verifier run found for the linked paths. ' +
|
|
92
|
-
'Run `/dezycro:verify --path ' + pathList + '` first to attach passing verifier evidence, then retry.';
|
|
93
|
-
return { reason };
|
|
94
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* workbook.ts — builds the sweep directive that the Stop hook injects into
|
|
3
|
-
* the agent's next assistant turn (TRD §5.3.1).
|
|
4
|
-
*
|
|
5
|
-
* Design choice: the runner does NOT call an LLM itself. It builds a
|
|
6
|
-
* structured directive that tells the agent to (a) scan its own recent
|
|
7
|
-
* context per the P-1 schema, (b) for each high-confidence candidate that
|
|
8
|
-
* passes caps + dedup, call the corresponding MCP workbook tool, and (c)
|
|
9
|
-
* print the announce line per the template.
|
|
10
|
-
*/
|
|
11
|
-
import type { EntityKind } from './hashing';
|
|
12
|
-
import type { SweepDirectiveOpts } from '../types';
|
|
13
|
-
export declare const ANNOUNCE_TEMPLATES: Readonly<Record<"decision" | "issue" | "assumption" | "task_status", string>>;
|
|
14
|
-
/** Build the Stop-hook directive payload. */
|
|
15
|
-
export declare function buildSweepDirective(opts: SweepDirectiveOpts): string;
|
|
16
|
-
export declare function buildCapHitMessage(sessionAutoLogCount: number | string): string;
|
|
17
|
-
/**
|
|
18
|
-
* Detect the entityKind from a tool name string. Returns null if not a
|
|
19
|
-
* tracked workbook tool.
|
|
20
|
-
*/
|
|
21
|
-
export declare function entityKindForTool(toolName: string | null | undefined): EntityKind | null;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* workbook.ts — builds the sweep directive that the Stop hook injects into
|
|
3
|
-
* the agent's next assistant turn (TRD §5.3.1).
|
|
4
|
-
*
|
|
5
|
-
* Design choice: the runner does NOT call an LLM itself. It builds a
|
|
6
|
-
* structured directive that tells the agent to (a) scan its own recent
|
|
7
|
-
* context per the P-1 schema, (b) for each high-confidence candidate that
|
|
8
|
-
* passes caps + dedup, call the corresponding MCP workbook tool, and (c)
|
|
9
|
-
* print the announce line per the template.
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.ANNOUNCE_TEMPLATES = void 0;
|
|
14
|
-
exports.buildSweepDirective = buildSweepDirective;
|
|
15
|
-
exports.buildCapHitMessage = buildCapHitMessage;
|
|
16
|
-
exports.entityKindForTool = entityKindForTool;
|
|
17
|
-
exports.ANNOUNCE_TEMPLATES = Object.freeze({
|
|
18
|
-
decision: "Logging decision: {{summary}} — reason: {{reason}}. Say 'undo that' if wrong.",
|
|
19
|
-
issue: "Logging issue ({{severity}}): {{summary}}. Say 'undo that' if wrong.",
|
|
20
|
-
assumption: "Logging assumption: {{summary}} — rationale: {{rationale}}. Say 'undo that' if wrong.",
|
|
21
|
-
task_status: "Marking task {{task_id}} as {{proposed_status}} — rationale: {{rationale}}. Say 'undo that' if wrong.",
|
|
22
|
-
});
|
|
23
|
-
const CAP_HIT_MESSAGE = "Auto-logging paused — {{count}} entries logged this session. Type /dezycro:sync to log manually.";
|
|
24
|
-
/** Build the Stop-hook directive payload. */
|
|
25
|
-
function buildSweepDirective(opts) {
|
|
26
|
-
const t = opts.thresholds || {};
|
|
27
|
-
const turnLeft = Math.max(0, Number(opts.perTurnSlotsLeft) || 0);
|
|
28
|
-
const sessionLeft = Math.max(0, Number(opts.perSessionSlotsLeft) || 0);
|
|
29
|
-
if (turnLeft <= 0 || sessionLeft <= 0) {
|
|
30
|
-
return CAP_HIT_MESSAGE.replace('{{count}}', String(sessionLeft <= 0 ? 'session-cap' : 'turn-cap'));
|
|
31
|
-
}
|
|
32
|
-
const slotsLeft = Math.min(turnLeft, sessionLeft);
|
|
33
|
-
const ring = (opts.recentHashes || []).filter(Boolean);
|
|
34
|
-
const lines = [
|
|
35
|
-
'[Dezycro Companion]',
|
|
36
|
-
`Feature: ${formatFeature(opts.activeFeatureName, opts.activeFeatureId)}. Slots: ${slotsLeft} (${turnLeft}/turn, ${sessionLeft}/session).`,
|
|
37
|
-
'',
|
|
38
|
-
`Scan since your last message for committed signals to log:`,
|
|
39
|
-
` - Decision (conf \u2265 ${t.decision ?? 0.85}) — committed technical/product choice`,
|
|
40
|
-
` - Issue (conf \u2265 ${t.issue ?? 0.80}) — current blocker/bug`,
|
|
41
|
-
` - Assumption (conf \u2265 ${t.assumption ?? 0.90}) — unverified belief affecting impl`,
|
|
42
|
-
` - Task-status (conf \u2265 ${t.taskStatus ?? 0.90}) — task is now DONE/PUSHED`,
|
|
43
|
-
'',
|
|
44
|
-
'Skip: hypotheticals, brainstorming, implementation-obvious details, ephemeral content, intent statements while authoring a PRD/TRD.',
|
|
45
|
-
];
|
|
46
|
-
if (ring.length > 0) {
|
|
47
|
-
lines.push(`Already-logged hashes (skip dupes): ${ring.join(', ')}`);
|
|
48
|
-
}
|
|
49
|
-
lines.push('', 'For each surviving candidate (max ' + slotsLeft + '): print the announce line verbatim and call the matching MCP tool.', ' decision: "' + exports.ANNOUNCE_TEMPLATES.decision + '" \u2192 mcp__dezycro(-dev)?__add_decision', ' issue: "' + exports.ANNOUNCE_TEMPLATES.issue + '" \u2192 mcp__dezycro(-dev)?__add_issue', ' assumption: "' + exports.ANNOUNCE_TEMPLATES.assumption + '" \u2192 mcp__dezycro(-dev)?__add_assumption', ' task_status: "' + exports.ANNOUNCE_TEMPLATES.task_status + '" \u2192 mcp__dezycro(-dev)?__update_task', '', 'If nothing meets the bar, simply continue with whatever the user asked next — do NOT output any acknowledgment line. The hook will silence itself for trivial turns.');
|
|
50
|
-
return lines.join('\n');
|
|
51
|
-
}
|
|
52
|
-
function formatFeature(name, id) {
|
|
53
|
-
if (!id)
|
|
54
|
-
return '(none — skip if no feature is active)';
|
|
55
|
-
const shortId = String(id).slice(0, 8);
|
|
56
|
-
return name ? `${name} (${shortId}\u2026)` : shortId + '\u2026';
|
|
57
|
-
}
|
|
58
|
-
function buildCapHitMessage(sessionAutoLogCount) {
|
|
59
|
-
return CAP_HIT_MESSAGE.replace('{{count}}', String(sessionAutoLogCount));
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Detect the entityKind from a tool name string. Returns null if not a
|
|
63
|
-
* tracked workbook tool.
|
|
64
|
-
*/
|
|
65
|
-
function entityKindForTool(toolName) {
|
|
66
|
-
if (typeof toolName !== 'string')
|
|
67
|
-
return null;
|
|
68
|
-
if (/add_decision$/.test(toolName))
|
|
69
|
-
return 'decision';
|
|
70
|
-
if (/add_issue$/.test(toolName))
|
|
71
|
-
return 'issue';
|
|
72
|
-
if (/add_assumption$/.test(toolName))
|
|
73
|
-
return 'assumption';
|
|
74
|
-
if (/update_task$/.test(toolName))
|
|
75
|
-
return 'task-status';
|
|
76
|
-
return null;
|
|
77
|
-
}
|