@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
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* coverage.ts — deterministic coverage-snapshot formatter (TRD §5.4.2).
|
|
3
|
-
*
|
|
4
|
-
* One-liner format:
|
|
5
|
-
* Coverage: N path[s] uncovered, M endpoint[s] not in spec, K baseline[s] stale
|
|
6
|
-
*
|
|
7
|
-
* Zero-count segments are omitted. If all counts are zero, returns null.
|
|
8
|
-
*/
|
|
9
|
-
'use strict';
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.formatOneLiner = formatOneLiner;
|
|
12
|
-
exports.formatDelta = formatDelta;
|
|
13
|
-
exports.fetch = fetch;
|
|
14
|
-
function plural(n, word) {
|
|
15
|
-
return `${n} ${word}${n === 1 ? '' : 's'}`;
|
|
16
|
-
}
|
|
17
|
-
function snapshotCounts(snapshot) {
|
|
18
|
-
if (!snapshot || typeof snapshot !== 'object')
|
|
19
|
-
return null;
|
|
20
|
-
return {
|
|
21
|
-
uncoveredPaths: Number(snapshot.uncoveredPaths ?? 0) || 0,
|
|
22
|
-
endpointsNotInSpec: Number(snapshot.endpointsNotInSpec ?? 0) || 0,
|
|
23
|
-
staleBaselines: Number(snapshot.staleBaselines ?? 0) || 0,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
function formatOneLiner(snapshot) {
|
|
27
|
-
const c = snapshotCounts(snapshot);
|
|
28
|
-
if (!c)
|
|
29
|
-
return null;
|
|
30
|
-
const segments = [];
|
|
31
|
-
if (c.uncoveredPaths > 0)
|
|
32
|
-
segments.push(`${plural(c.uncoveredPaths, 'path')} uncovered`);
|
|
33
|
-
if (c.endpointsNotInSpec > 0)
|
|
34
|
-
segments.push(`${plural(c.endpointsNotInSpec, 'endpoint')} not in spec`);
|
|
35
|
-
if (c.staleBaselines > 0)
|
|
36
|
-
segments.push(`${plural(c.staleBaselines, 'baseline')} stale`);
|
|
37
|
-
if (segments.length === 0)
|
|
38
|
-
return null;
|
|
39
|
-
return `Coverage: ${segments.join(', ')}`;
|
|
40
|
-
}
|
|
41
|
-
function formatDelta(prev, next) {
|
|
42
|
-
const a = snapshotCounts(prev);
|
|
43
|
-
const b = snapshotCounts(next);
|
|
44
|
-
if (!b)
|
|
45
|
-
return null;
|
|
46
|
-
if (!a)
|
|
47
|
-
return formatOneLiner(next);
|
|
48
|
-
const deltas = [
|
|
49
|
-
['paths uncovered', b.uncoveredPaths - a.uncoveredPaths],
|
|
50
|
-
['endpoints not in spec', b.endpointsNotInSpec - a.endpointsNotInSpec],
|
|
51
|
-
['baselines stale', b.staleBaselines - a.staleBaselines],
|
|
52
|
-
];
|
|
53
|
-
const nonZero = deltas.filter(([, d]) => d !== 0);
|
|
54
|
-
if (nonZero.length === 0)
|
|
55
|
-
return null;
|
|
56
|
-
const parts = nonZero.map(([label, d]) => `${d > 0 ? '+' : ''}${d} ${label}`);
|
|
57
|
-
return `Coverage delta since last verify: ${parts.join(', ')}`;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Detached coverage-fetch entry point. Deferred to V2.1 — for V2.0 the
|
|
61
|
-
* /dezycro:verify skill calls get_coverage_report directly and updates
|
|
62
|
-
* state via `companion-runner state --patch=…`.
|
|
63
|
-
*/
|
|
64
|
-
async function fetch(_featureId) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hashing.ts — content-hash dedup for auto-logged workbook items (TRD §3.4).
|
|
3
|
-
*
|
|
4
|
-
* SHA-1 of `lowercase(<entity-kind>::<summary>::<linked-task-id-or-empty>)`
|
|
5
|
-
* truncated to 16 hex chars.
|
|
6
|
-
*/
|
|
7
|
-
export type EntityKind = 'decision' | 'issue' | 'assumption' | 'task-status';
|
|
8
|
-
export declare function hashCandidate(entityKind: EntityKind | string, summary: string, linkedTaskId: string | null): string;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hashing.ts — content-hash dedup for auto-logged workbook items (TRD §3.4).
|
|
3
|
-
*
|
|
4
|
-
* SHA-1 of `lowercase(<entity-kind>::<summary>::<linked-task-id-or-empty>)`
|
|
5
|
-
* truncated to 16 hex chars.
|
|
6
|
-
*/
|
|
7
|
-
'use strict';
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.hashCandidate = hashCandidate;
|
|
43
|
-
const crypto = __importStar(require("crypto"));
|
|
44
|
-
function hashCandidate(entityKind, summary, linkedTaskId) {
|
|
45
|
-
const kind = String(entityKind || '').toLowerCase().trim();
|
|
46
|
-
const text = String(summary || '').toLowerCase().trim().replace(/\s+/g, ' ');
|
|
47
|
-
const link = String(linkedTaskId || '').toLowerCase().trim();
|
|
48
|
-
return crypto.createHash('sha1').update(`${kind}::${text}::${link}`).digest('hex').slice(0, 16);
|
|
49
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* logging.ts — JSON-lines logger for Companion.
|
|
3
|
-
*
|
|
4
|
-
* Writes to `.dezycro/companion.log` per TRD §12 (Observability). Best-effort:
|
|
5
|
-
* never throws upstream — a logging failure must never break a hook.
|
|
6
|
-
*/
|
|
7
|
-
type Fields = Record<string, unknown> | undefined;
|
|
8
|
-
/** Append a single JSON-lines record to `<repoRoot>/.dezycro/companion.log`. */
|
|
9
|
-
export declare function append(repoRoot: string, record: Record<string, unknown>): void;
|
|
10
|
-
export declare function info(repoRoot: string, event: string, fields?: Fields): void;
|
|
11
|
-
export declare function warn(repoRoot: string, event: string, fields?: Fields): void;
|
|
12
|
-
export declare function error(repoRoot: string, event: string, fields?: Fields): void;
|
|
13
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* logging.ts — JSON-lines logger for Companion.
|
|
3
|
-
*
|
|
4
|
-
* Writes to `.dezycro/companion.log` per TRD §12 (Observability). Best-effort:
|
|
5
|
-
* never throws upstream — a logging failure must never break a hook.
|
|
6
|
-
*/
|
|
7
|
-
'use strict';
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.append = append;
|
|
43
|
-
exports.info = info;
|
|
44
|
-
exports.warn = warn;
|
|
45
|
-
exports.error = error;
|
|
46
|
-
const fs = __importStar(require("fs"));
|
|
47
|
-
const path = __importStar(require("path"));
|
|
48
|
-
const LOG_FILENAME = 'companion.log';
|
|
49
|
-
/** Append a single JSON-lines record to `<repoRoot>/.dezycro/companion.log`. */
|
|
50
|
-
function append(repoRoot, record) {
|
|
51
|
-
try {
|
|
52
|
-
const dezycroDir = path.join(repoRoot, '.dezycro');
|
|
53
|
-
if (!fs.existsSync(dezycroDir)) {
|
|
54
|
-
// We don't create the dir here — Companion init owns that.
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const line = JSON.stringify({ ts: new Date().toISOString(), ...record }) + '\n';
|
|
58
|
-
fs.appendFileSync(path.join(dezycroDir, LOG_FILENAME), line, { encoding: 'utf8' });
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
// Swallow — logging must never propagate.
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function info(repoRoot, event, fields) {
|
|
65
|
-
append(repoRoot, { level: 'info', event, ...(fields || {}) });
|
|
66
|
-
}
|
|
67
|
-
function warn(repoRoot, event, fields) {
|
|
68
|
-
append(repoRoot, { level: 'warn', event, ...(fields || {}) });
|
|
69
|
-
}
|
|
70
|
-
function error(repoRoot, event, fields) {
|
|
71
|
-
append(repoRoot, { level: 'error', event, ...(fields || {}) });
|
|
72
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* publish-spec.ts — helper consumed by the `/dezycro:verify` skill to detect
|
|
3
|
-
* pending controller edits and announce + chain `/dezycro:publish-spec` before
|
|
4
|
-
* verifying (TRD §5.2).
|
|
5
|
-
*
|
|
6
|
-
* The hook layer does NOT run this. PostToolUse:edit sets `needsSpecPublish`
|
|
7
|
-
* + appends to `controllerEditsSinceLastPublish` (in router.ts); the verify
|
|
8
|
-
* skill reads via `needsPublishBeforeVerify`, announces, chains publish-spec,
|
|
9
|
-
* then runs verify. After publish-spec completes the skill clears the flags.
|
|
10
|
-
*/
|
|
11
|
-
export interface PublishCheckResult {
|
|
12
|
-
needed: boolean;
|
|
13
|
-
controllerPaths: string[];
|
|
14
|
-
lastEditTs: string | null;
|
|
15
|
-
}
|
|
16
|
-
export declare function needsPublishBeforeVerify(repoRoot: string | null | undefined): PublishCheckResult;
|
|
17
|
-
export declare function buildAnnouncement(controllerPaths: string[]): string;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* publish-spec.ts — helper consumed by the `/dezycro:verify` skill to detect
|
|
3
|
-
* pending controller edits and announce + chain `/dezycro:publish-spec` before
|
|
4
|
-
* verifying (TRD §5.2).
|
|
5
|
-
*
|
|
6
|
-
* The hook layer does NOT run this. PostToolUse:edit sets `needsSpecPublish`
|
|
7
|
-
* + appends to `controllerEditsSinceLastPublish` (in router.ts); the verify
|
|
8
|
-
* skill reads via `needsPublishBeforeVerify`, announces, chains publish-spec,
|
|
9
|
-
* then runs verify. After publish-spec completes the skill clears the flags.
|
|
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.needsPublishBeforeVerify = needsPublishBeforeVerify;
|
|
47
|
-
exports.buildAnnouncement = buildAnnouncement;
|
|
48
|
-
const state = __importStar(require("./state"));
|
|
49
|
-
function needsPublishBeforeVerify(repoRoot) {
|
|
50
|
-
if (!repoRoot)
|
|
51
|
-
return { needed: false, controllerPaths: [], lastEditTs: null };
|
|
52
|
-
const s = state.read(repoRoot);
|
|
53
|
-
const edits = Array.isArray(s.controllerEditsSinceLastPublish)
|
|
54
|
-
? s.controllerEditsSinceLastPublish
|
|
55
|
-
: [];
|
|
56
|
-
const controllerPaths = edits.map((e) => e && e.path).filter(Boolean);
|
|
57
|
-
const lastEditTs = edits.length > 0 ? (edits[edits.length - 1].editedTs || null) : null;
|
|
58
|
-
const needed = Boolean(s.needsSpecPublish) && controllerPaths.length > 0;
|
|
59
|
-
return { needed, controllerPaths, lastEditTs };
|
|
60
|
-
}
|
|
61
|
-
function buildAnnouncement(controllerPaths) {
|
|
62
|
-
const list = (controllerPaths || []).join(', ');
|
|
63
|
-
return 'Controllers changed since last published spec: ' + list + '. Publishing spec before verify.';
|
|
64
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* quality-gate.ts — deterministic TRD-approval checks + code-side enforcement
|
|
3
|
-
* of the P-9 LLM result. TRD §5.5.3 QUALITY_GATE and §6.9 enforcement notes.
|
|
4
|
-
*
|
|
5
|
-
* No LLM calls live here. The skill markdown is responsible for invoking P-9;
|
|
6
|
-
* `enforceP9Result` is the tamper-proof code-side guard run against P-9's
|
|
7
|
-
* structured output.
|
|
8
|
-
*/
|
|
9
|
-
export declare const INVENTION_KEYWORDS: readonly string[];
|
|
10
|
-
export interface RequiredHeading {
|
|
11
|
-
id: string;
|
|
12
|
-
pattern: RegExp;
|
|
13
|
-
}
|
|
14
|
-
export declare const REQUIRED_TRD_HEADINGS: readonly RequiredHeading[];
|
|
15
|
-
export declare const PLACEHOLDER_REGEX: RegExp;
|
|
16
|
-
export declare const MIN_TRD_LENGTH = 1000;
|
|
17
|
-
export declare const PILLAR_HEADING_REGEX: RegExp;
|
|
18
|
-
export declare const MIN_CONTEXT_CATEGORIES: readonly string[];
|
|
19
|
-
export declare const MIN_CONTEXT_EVIDENCE_CHARS = 80;
|
|
20
|
-
export declare const MIN_P9_SCORE = 0.85;
|
|
21
|
-
export declare function parsePrdPillarNames(prdContent: string | null | undefined): string[];
|
|
22
|
-
export interface BlockingIssue {
|
|
23
|
-
section: string;
|
|
24
|
-
issue: string;
|
|
25
|
-
required_fix: string;
|
|
26
|
-
}
|
|
27
|
-
export interface DeterministicGateResult {
|
|
28
|
-
passed: boolean;
|
|
29
|
-
blockingIssues: BlockingIssue[];
|
|
30
|
-
deterministic: true;
|
|
31
|
-
}
|
|
32
|
-
export declare function deterministicTrdGate(opts: {
|
|
33
|
-
trdContent: string | null | undefined;
|
|
34
|
-
prdContent: string | null | undefined;
|
|
35
|
-
}): DeterministicGateResult;
|
|
36
|
-
export interface MinContextGateInput {
|
|
37
|
-
discoverySummary: {
|
|
38
|
-
confirmed_context?: Record<string, string[]>;
|
|
39
|
-
likely_conventions?: Record<string, string[]>;
|
|
40
|
-
[extra: string]: unknown;
|
|
41
|
-
} | null;
|
|
42
|
-
answeredCategories: Record<string, string[]> | null;
|
|
43
|
-
}
|
|
44
|
-
export interface MinContextGateResult {
|
|
45
|
-
ready: boolean;
|
|
46
|
-
missing: Record<string, string[]>;
|
|
47
|
-
}
|
|
48
|
-
export declare function minContextGate(opts: MinContextGateInput): MinContextGateResult;
|
|
49
|
-
export interface P9Output {
|
|
50
|
-
approved?: boolean;
|
|
51
|
-
score?: number;
|
|
52
|
-
suspected_inventions?: Array<{
|
|
53
|
-
claim?: string;
|
|
54
|
-
}>;
|
|
55
|
-
blocking_issues?: Array<{
|
|
56
|
-
issue?: string;
|
|
57
|
-
}>;
|
|
58
|
-
}
|
|
59
|
-
export interface P9EnforcementResult {
|
|
60
|
-
passed: boolean;
|
|
61
|
-
reason: string | null;
|
|
62
|
-
score: number;
|
|
63
|
-
suspectedInventions: Array<{
|
|
64
|
-
claim?: string;
|
|
65
|
-
}>;
|
|
66
|
-
}
|
|
67
|
-
export declare function enforceP9Result(p9Output: P9Output | null | undefined): P9EnforcementResult;
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* quality-gate.ts — deterministic TRD-approval checks + code-side enforcement
|
|
3
|
-
* of the P-9 LLM result. TRD §5.5.3 QUALITY_GATE and §6.9 enforcement notes.
|
|
4
|
-
*
|
|
5
|
-
* No LLM calls live here. The skill markdown is responsible for invoking P-9;
|
|
6
|
-
* `enforceP9Result` is the tamper-proof code-side guard run against P-9's
|
|
7
|
-
* structured output.
|
|
8
|
-
*/
|
|
9
|
-
'use strict';
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.MIN_P9_SCORE = exports.MIN_CONTEXT_EVIDENCE_CHARS = exports.MIN_CONTEXT_CATEGORIES = exports.PILLAR_HEADING_REGEX = exports.MIN_TRD_LENGTH = exports.PLACEHOLDER_REGEX = exports.REQUIRED_TRD_HEADINGS = exports.INVENTION_KEYWORDS = void 0;
|
|
12
|
-
exports.parsePrdPillarNames = parsePrdPillarNames;
|
|
13
|
-
exports.deterministicTrdGate = deterministicTrdGate;
|
|
14
|
-
exports.minContextGate = minContextGate;
|
|
15
|
-
exports.enforceP9Result = enforceP9Result;
|
|
16
|
-
exports.INVENTION_KEYWORDS = Object.freeze([
|
|
17
|
-
'architecture',
|
|
18
|
-
'data model',
|
|
19
|
-
'data-model',
|
|
20
|
-
'datamodel',
|
|
21
|
-
'api contract',
|
|
22
|
-
'api-contract',
|
|
23
|
-
'apicontract',
|
|
24
|
-
'migration',
|
|
25
|
-
'auth',
|
|
26
|
-
'queue',
|
|
27
|
-
'verifier-behavior',
|
|
28
|
-
'verifier behavior',
|
|
29
|
-
]);
|
|
30
|
-
exports.REQUIRED_TRD_HEADINGS = Object.freeze([
|
|
31
|
-
{ id: 'architecture', pattern: /^##\s+architecture\b/im },
|
|
32
|
-
{ id: 'data_model', pattern: /^##\s+data\s+model\b/im },
|
|
33
|
-
{ id: 'api_contracts', pattern: /^##\s+api\s+contracts?\b/im },
|
|
34
|
-
{ id: 'failure_modes', pattern: /^##\s+failure\s+modes?/im },
|
|
35
|
-
{ id: 'migration', pattern: /^##\s+migration\b/im },
|
|
36
|
-
{ id: 'open_questions', pattern: /^##\s+open\s+questions?\b/im },
|
|
37
|
-
]);
|
|
38
|
-
exports.PLACEHOLDER_REGEX = /\b(TBD|TODO|FIXME|fill in later|to be determined)\b/i;
|
|
39
|
-
exports.MIN_TRD_LENGTH = 1000;
|
|
40
|
-
exports.PILLAR_HEADING_REGEX = /^##\s+Pillar\s+\d+\s*:\s*(.+?)\s*$/gim;
|
|
41
|
-
exports.MIN_CONTEXT_CATEGORIES = Object.freeze([
|
|
42
|
-
'data_model',
|
|
43
|
-
'api_contracts',
|
|
44
|
-
'state_or_persistence',
|
|
45
|
-
'failure_modes',
|
|
46
|
-
'migration_or_rollout',
|
|
47
|
-
]);
|
|
48
|
-
exports.MIN_CONTEXT_EVIDENCE_CHARS = 80;
|
|
49
|
-
exports.MIN_P9_SCORE = 0.85;
|
|
50
|
-
function normalizeWhitespace(s) {
|
|
51
|
-
return (s || '').toString().replace(/\s+/g, ' ').trim();
|
|
52
|
-
}
|
|
53
|
-
function parsePrdPillarNames(prdContent) {
|
|
54
|
-
if (!prdContent || typeof prdContent !== 'string')
|
|
55
|
-
return [];
|
|
56
|
-
const names = [];
|
|
57
|
-
exports.PILLAR_HEADING_REGEX.lastIndex = 0;
|
|
58
|
-
let match;
|
|
59
|
-
while ((match = exports.PILLAR_HEADING_REGEX.exec(prdContent)) !== null) {
|
|
60
|
-
const name = match[1].trim();
|
|
61
|
-
if (name)
|
|
62
|
-
names.push(name);
|
|
63
|
-
}
|
|
64
|
-
return names;
|
|
65
|
-
}
|
|
66
|
-
function deterministicTrdGate(opts) {
|
|
67
|
-
const { trdContent, prdContent } = opts;
|
|
68
|
-
const issues = [];
|
|
69
|
-
const trd = (trdContent || '').toString();
|
|
70
|
-
const trdLen = trd.trim().length;
|
|
71
|
-
if (trdLen < exports.MIN_TRD_LENGTH) {
|
|
72
|
-
issues.push({
|
|
73
|
-
section: 'document',
|
|
74
|
-
issue: `TRD is too short (${trdLen} chars; minimum ${exports.MIN_TRD_LENGTH}).`,
|
|
75
|
-
required_fix: 'Expand the draft with concrete technical detail.',
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
for (const required of exports.REQUIRED_TRD_HEADINGS) {
|
|
79
|
-
if (!required.pattern.test(trd)) {
|
|
80
|
-
issues.push({
|
|
81
|
-
section: required.id,
|
|
82
|
-
issue: `Required H2 section is missing.`,
|
|
83
|
-
required_fix: `Add a "## ${required.id.replace(/_/g, ' ')}" section grounded in the PRD + discovery.`,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const placeholderMatch = trd.match(exports.PLACEHOLDER_REGEX);
|
|
88
|
-
if (placeholderMatch) {
|
|
89
|
-
issues.push({
|
|
90
|
-
section: 'placeholders',
|
|
91
|
-
issue: `Placeholder token "${placeholderMatch[0]}" present — TRDs must not ship with unresolved placeholders.`,
|
|
92
|
-
required_fix: 'Resolve or move the open item into the ## Open Questions section.',
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
const pillarNames = parsePrdPillarNames(prdContent);
|
|
96
|
-
if (pillarNames.length > 0) {
|
|
97
|
-
const missing = [];
|
|
98
|
-
const haystack = trd.toLowerCase();
|
|
99
|
-
for (const name of pillarNames) {
|
|
100
|
-
if (!haystack.includes(name.toLowerCase()))
|
|
101
|
-
missing.push(name);
|
|
102
|
-
}
|
|
103
|
-
if (missing.length > 0) {
|
|
104
|
-
issues.push({
|
|
105
|
-
section: 'pillar_coverage',
|
|
106
|
-
issue: `TRD does not mention PRD pillar(s): ${missing.join(', ')}.`,
|
|
107
|
-
required_fix: 'Add a per-pillar technical-design section, or reference each pillar by name in the relevant TRD section.',
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
passed: issues.length === 0,
|
|
113
|
-
blockingIssues: issues,
|
|
114
|
-
deterministic: true,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function minContextGate(opts) {
|
|
118
|
-
const summary = opts.discoverySummary || {};
|
|
119
|
-
const confirmed = summary.confirmed_context || {};
|
|
120
|
-
const likely = summary.likely_conventions || {};
|
|
121
|
-
const answers = opts.answeredCategories || {};
|
|
122
|
-
const missing = {};
|
|
123
|
-
for (const cat of exports.MIN_CONTEXT_CATEGORIES) {
|
|
124
|
-
const items = []
|
|
125
|
-
.concat(confirmed[cat] || [])
|
|
126
|
-
.concat(likely[cat] || [])
|
|
127
|
-
.concat(answers[cat] || []);
|
|
128
|
-
const combined = normalizeWhitespace(items.join(' '));
|
|
129
|
-
const reasons = [];
|
|
130
|
-
if (items.length === 0) {
|
|
131
|
-
reasons.push('no evidence in confirmed_context, likely_conventions, or QA answers');
|
|
132
|
-
}
|
|
133
|
-
else if (combined.length < exports.MIN_CONTEXT_EVIDENCE_CHARS) {
|
|
134
|
-
reasons.push(`evidence too thin (${combined.length} chars; need \u2265 ${exports.MIN_CONTEXT_EVIDENCE_CHARS})`);
|
|
135
|
-
}
|
|
136
|
-
if (reasons.length > 0)
|
|
137
|
-
missing[cat] = reasons;
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
ready: Object.keys(missing).length === 0,
|
|
141
|
-
missing,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function enforceP9Result(p9Output) {
|
|
145
|
-
const out = p9Output || {};
|
|
146
|
-
const score = typeof out.score === 'number' ? out.score : 0;
|
|
147
|
-
const suspected = Array.isArray(out.suspected_inventions) ? out.suspected_inventions : [];
|
|
148
|
-
if (score < exports.MIN_P9_SCORE) {
|
|
149
|
-
return {
|
|
150
|
-
passed: false,
|
|
151
|
-
reason: `P-9 score ${score.toFixed(2)} is below the minimum ${exports.MIN_P9_SCORE.toFixed(2)} — TRD is not approved.`,
|
|
152
|
-
score,
|
|
153
|
-
suspectedInventions: suspected,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
const flagged = [];
|
|
157
|
-
for (const inv of suspected) {
|
|
158
|
-
const claim = (inv && inv.claim ? inv.claim : '').toString().toLowerCase();
|
|
159
|
-
if (!claim)
|
|
160
|
-
continue;
|
|
161
|
-
const hit = exports.INVENTION_KEYWORDS.find((kw) => claim.includes(kw));
|
|
162
|
-
if (hit)
|
|
163
|
-
flagged.push({ claim: String(inv.claim), keyword: hit });
|
|
164
|
-
}
|
|
165
|
-
if (flagged.length > 0) {
|
|
166
|
-
const summary = flagged
|
|
167
|
-
.map((f) => `"${f.claim}" (keyword: ${f.keyword})`)
|
|
168
|
-
.join('; ');
|
|
169
|
-
return {
|
|
170
|
-
passed: false,
|
|
171
|
-
reason: `P-9 flagged invented technical claim(s): ${summary}. Move to Open Questions or ask the user.`,
|
|
172
|
-
score,
|
|
173
|
-
suspectedInventions: suspected,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
if (out.approved !== true) {
|
|
177
|
-
return {
|
|
178
|
-
passed: false,
|
|
179
|
-
reason: out.blocking_issues && out.blocking_issues.length > 0
|
|
180
|
-
? `P-9 reviewer rejected: ${String(out.blocking_issues[0].issue || 'blocking issue')}`
|
|
181
|
-
: 'P-9 reviewer did not approve the TRD.',
|
|
182
|
-
score,
|
|
183
|
-
suspectedInventions: suspected,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
return { passed: true, reason: null, score, suspectedInventions: suspected };
|
|
187
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* router.ts — dispatches hook invocations to the right handler.
|
|
3
|
-
*
|
|
4
|
-
* The companion-runner shim parses argv and stdin payloads into a
|
|
5
|
-
* RouterInvocation and calls dispatch(). Per-handler boundaries try/catch
|
|
6
|
-
* via the runner entry point: any exception inside this module is logged
|
|
7
|
-
* by the runner and converts to silent exit so a hook never breaks a
|
|
8
|
-
* user session.
|
|
9
|
-
*/
|
|
10
|
-
import type { PostToolUsePayload, PreToolUsePayload, RouterInvocation, StopPayload, UserPromptSubmitPayload, SessionStartPayload } from '../types';
|
|
11
|
-
export declare const QUALITY_GATE_REASON_PREFIX = "TRD quality gate (deterministic layer) blocked APPROVED transition: ";
|
|
12
|
-
export declare function dispatch(invocation: RouterInvocation): Promise<number>;
|
|
13
|
-
declare function handleUpdateTaskGate(payload: PreToolUsePayload): number;
|
|
14
|
-
declare function handlePostEdit(payload: PostToolUsePayload): Promise<number>;
|
|
15
|
-
declare function extractEditedPaths(toolInput: Record<string, unknown> | null | undefined): string[];
|
|
16
|
-
declare function handleSessionStart(_payload: SessionStartPayload): Promise<number>;
|
|
17
|
-
declare function handleUserPromptSubmit(payload: UserPromptSubmitPayload): Promise<number>;
|
|
18
|
-
declare function handleStop(payload: StopPayload): Promise<number>;
|
|
19
|
-
declare function transcriptCharsSinceLastStop(payload: StopPayload): number | null;
|
|
20
|
-
declare function readActiveFeatureId(repoRoot: string): string | null;
|
|
21
|
-
declare function handleWorkbookMutation(payload: PostToolUsePayload): number;
|
|
22
|
-
export declare const _extractEditedPaths: typeof extractEditedPaths;
|
|
23
|
-
export declare const _handlePostEdit: typeof handlePostEdit;
|
|
24
|
-
export declare const _handleUpdateTaskGate: typeof handleUpdateTaskGate;
|
|
25
|
-
export declare const _handleStop: typeof handleStop;
|
|
26
|
-
export declare const _handleUserPromptSubmit: typeof handleUserPromptSubmit;
|
|
27
|
-
export declare const _handleWorkbookMutation: typeof handleWorkbookMutation;
|
|
28
|
-
export declare const _handleSessionStart: typeof handleSessionStart;
|
|
29
|
-
export declare const _readActiveFeatureId: typeof readActiveFeatureId;
|
|
30
|
-
export declare const _transcriptCharsSinceLastStop: typeof transcriptCharsSinceLastStop;
|
|
31
|
-
export declare const TRIVIAL_TURN_CHAR_DEFAULT_EXPORT = 600;
|
|
32
|
-
export {};
|
|
@@ -1,34 +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
|
-
import type { CompanionState, CompanionMetrics, StatePatch } from '../types';
|
|
12
|
-
export declare const HASH_RING_BUFFER_CAP = 32;
|
|
13
|
-
export declare const CONTROLLER_EDITS_CAP = 64;
|
|
14
|
-
export declare const DEFAULT_COMPANION_METRICS: Readonly<CompanionMetrics>;
|
|
15
|
-
export declare const DEFAULT_COMPANION_STATE: Readonly<CompanionState>;
|
|
16
|
-
export declare function read(repoRoot: string): CompanionState;
|
|
17
|
-
declare function tryAcquireLock(repoRoot: string): boolean;
|
|
18
|
-
declare function releaseLock(repoRoot: string): void;
|
|
19
|
-
/**
|
|
20
|
-
* Atomic patch under O_EXCL lock. Special keys:
|
|
21
|
-
* - metrics: shallow-merged inside (caller can patch one counter).
|
|
22
|
-
* - pushDecisionHash / pushIssueHash / pushAssumptionHash: appended to
|
|
23
|
-
* the corresponding ring buffer (FIFO-capped at 32) instead of replacing.
|
|
24
|
-
* - pushControllerEdit: same idea for controllerEditsSinceLastPublish
|
|
25
|
-
* (FIFO-capped at 64), with replace-by-path semantics.
|
|
26
|
-
*
|
|
27
|
-
* Returns the new state, or null on lock-contention timeout.
|
|
28
|
-
*/
|
|
29
|
-
export declare function patch(repoRoot: string, _patch: StatePatch): CompanionState | null;
|
|
30
|
-
/** Bump a metric by 1 atomically. Returns null on lock contention. */
|
|
31
|
-
export declare function incrementMetric(repoRoot: string, metricKey: keyof CompanionMetrics, delta?: number): CompanionState | null;
|
|
32
|
-
export declare const _tryAcquireLock: typeof tryAcquireLock;
|
|
33
|
-
export declare const _releaseLock: typeof releaseLock;
|
|
34
|
-
export {};
|