@deftai/directive-core 0.84.0 → 0.86.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/dist/cache/fetch.d.ts +17 -0
- package/dist/cache/fetch.js +50 -0
- package/dist/doctor/checks.js +16 -1
- package/dist/doctor/constants.d.ts +4 -2
- package/dist/doctor/constants.js +10 -6
- package/dist/doctor/index.d.ts +1 -0
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/main.d.ts +2 -1
- package/dist/doctor/main.js +83 -22
- package/dist/doctor/npm-registry.d.ts +23 -0
- package/dist/doctor/npm-registry.js +128 -0
- package/dist/doctor/npm-view.d.ts +10 -0
- package/dist/doctor/npm-view.js +31 -0
- package/dist/doctor/payload-staleness.js +2 -9
- package/dist/doctor/signpost-checks.d.ts +2 -1
- package/dist/doctor/signpost-checks.js +2 -0
- package/dist/doctor/types.d.ts +12 -0
- package/dist/eval-health-relocation/evaluate.js +15 -1
- package/dist/fs/projection-containment.js +1 -1
- package/dist/hooks/cursor-hooks.d.ts +6 -20
- package/dist/hooks/cursor-hooks.js +7 -92
- package/dist/init-deposit/agent-hooks.d.ts +2 -2
- package/dist/init-deposit/agent-hooks.js +24 -38
- package/dist/init-deposit/gitignore.js +5 -0
- package/dist/init-deposit/hygiene.d.ts +22 -0
- package/dist/init-deposit/hygiene.js +136 -4
- package/dist/init-deposit/legacy-detect.d.ts +25 -1
- package/dist/init-deposit/legacy-detect.js +143 -11
- package/dist/init-deposit/refresh.d.ts +2 -0
- package/dist/init-deposit/refresh.js +18 -5
- package/dist/policy/index.d.ts +2 -0
- package/dist/policy/index.js +2 -0
- package/dist/policy/org-force-on-migration.d.ts +44 -0
- package/dist/policy/org-force-on-migration.js +242 -0
- package/dist/policy/product-signal.d.ts +3 -1
- package/dist/policy/product-signal.js +15 -4
- package/dist/policy/value-feedback.d.ts +18 -1
- package/dist/policy/value-feedback.js +78 -5
- package/dist/preflight-cache/evaluate.js +12 -1
- package/dist/product-signal/consent-prompt.d.ts +13 -0
- package/dist/product-signal/consent-prompt.js +30 -0
- package/dist/product-signal/submit.js +22 -1
- package/dist/render/framework-commands.d.ts +1 -1
- package/dist/render/framework-commands.js +6 -6
- package/dist/render/index.d.ts +1 -0
- package/dist/render/index.js +1 -0
- package/dist/render/roadmap-render.d.ts +5 -1
- package/dist/render/roadmap-render.js +20 -2
- package/dist/render/rule-map-template.d.ts +2 -0
- package/dist/render/rule-map-template.js +407 -0
- package/dist/render/rule-map.d.ts +2 -0
- package/dist/render/rule-map.js +708 -0
- package/dist/review-monitor/constants.d.ts +7 -1
- package/dist/review-monitor/constants.js +40 -14
- package/dist/review-monitor/github-lease.d.ts +45 -0
- package/dist/review-monitor/github-lease.js +106 -0
- package/dist/review-monitor/index.d.ts +2 -0
- package/dist/review-monitor/index.js +2 -0
- package/dist/review-monitor/lease-comment.d.ts +36 -0
- package/dist/review-monitor/lease-comment.js +152 -0
- package/dist/review-monitor/record.d.ts +61 -13
- package/dist/review-monitor/record.js +379 -132
- package/dist/review-monitor/verify.d.ts +2 -0
- package/dist/review-monitor/verify.js +32 -13
- package/dist/scm/gh-rest.d.ts +7 -1
- package/dist/scm/gh-rest.js +35 -0
- package/dist/session/session-start.js +5 -0
- package/dist/task-surface/index.js +53 -13
- package/dist/verify-env/agent-hooks-live-probe.d.ts +32 -0
- package/dist/verify-env/agent-hooks-live-probe.js +216 -0
- package/dist/verify-env/index.d.ts +1 -0
- package/dist/verify-env/index.js +1 -0
- package/dist/xbrief-migrate/constants.d.ts +6 -0
- package/dist/xbrief-migrate/constants.js +6 -0
- package/dist/xbrief-migrate/index.d.ts +2 -2
- package/dist/xbrief-migrate/index.js +2 -2
- package/dist/xbrief-migrate/migrate-project.d.ts +7 -0
- package/dist/xbrief-migrate/migrate-project.js +44 -18
- package/package.json +3 -3
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
/** Deterministic review-monitor gate (#2655). Three-state exit contract. */
|
|
1
|
+
/** Deterministic review-monitor gate (#2655 / #2814). Three-state exit contract. */
|
|
2
2
|
export declare const EXIT_READY = 0;
|
|
3
3
|
export declare const EXIT_NOT_READY = 1;
|
|
4
4
|
export declare const EXIT_CONFIG_ERROR = 2;
|
|
5
|
+
export declare const EXIT_CONFLICT = 1;
|
|
5
6
|
export declare const SCHEMA_VERSION = 1;
|
|
7
|
+
/** @deprecated Obsolete local ledger (#2814); retained for migration references only. */
|
|
6
8
|
export declare const REVIEW_MONITOR_FILENAME = "review-monitor.json";
|
|
9
|
+
/** @deprecated Obsolete local ledger (#2814). */
|
|
7
10
|
export declare const REVIEW_MONITOR_RELPATH: readonly [".deft", "review-monitor.json"];
|
|
11
|
+
export declare const REVIEW_OWNER_MARKER_START = "<!-- deft:review-owner -->";
|
|
12
|
+
export declare const REVIEW_OWNER_MARKER_END = "<!-- /deft:review-owner -->";
|
|
8
13
|
export declare const MONITORING_TIER_1 = 1;
|
|
9
14
|
export declare const MONITORING_TIER_2 = 2;
|
|
10
15
|
export declare const MONITORING_TIER_3 = 3;
|
|
11
16
|
export declare const DEFAULT_STALE_MINUTES = 30;
|
|
12
17
|
export declare const REVIEW_MONITOR_HELP: string;
|
|
13
18
|
export declare const REGISTER_HELP: string;
|
|
19
|
+
export declare const RELEASE_HELP: string;
|
|
14
20
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
/** Deterministic review-monitor gate (#2655). Three-state exit contract. */
|
|
1
|
+
/** Deterministic review-monitor gate (#2655 / #2814). Three-state exit contract. */
|
|
2
2
|
export const EXIT_READY = 0;
|
|
3
3
|
export const EXIT_NOT_READY = 1;
|
|
4
4
|
export const EXIT_CONFIG_ERROR = 2;
|
|
5
|
+
export const EXIT_CONFLICT = 1;
|
|
5
6
|
export const SCHEMA_VERSION = 1;
|
|
7
|
+
/** @deprecated Obsolete local ledger (#2814); retained for migration references only. */
|
|
6
8
|
export const REVIEW_MONITOR_FILENAME = "review-monitor.json";
|
|
9
|
+
/** @deprecated Obsolete local ledger (#2814). */
|
|
7
10
|
export const REVIEW_MONITOR_RELPATH = [".deft", REVIEW_MONITOR_FILENAME];
|
|
11
|
+
export const REVIEW_OWNER_MARKER_START = "<!-- deft:review-owner -->";
|
|
12
|
+
export const REVIEW_OWNER_MARKER_END = "<!-- /deft:review-owner -->";
|
|
8
13
|
export const MONITORING_TIER_1 = 1;
|
|
9
14
|
export const MONITORING_TIER_2 = 2;
|
|
10
15
|
export const MONITORING_TIER_3 = 3;
|
|
11
16
|
export const DEFAULT_STALE_MINUTES = 30;
|
|
12
17
|
export const REVIEW_MONITOR_HELP = "usage: task verify:review-monitor -- --pr <N> [options]\n" +
|
|
13
18
|
"\n" +
|
|
14
|
-
"Fail-closed gate: when Tier 1 (sub-agent primitive available), require
|
|
15
|
-
"
|
|
16
|
-
"sleep-poll, or claim
|
|
19
|
+
"Fail-closed gate: when Tier 1 (sub-agent primitive available), require an\n" +
|
|
20
|
+
"unexpired GitHub review-owner lease (`<!-- deft:review-owner -->` sticky\n" +
|
|
21
|
+
"PR comment) before the parent may yield, Approach-3 sleep-poll, or claim\n" +
|
|
22
|
+
"review ownership (#2655 / #2814). Legacy `.deft/review-monitor.json` is\n" +
|
|
23
|
+
"ignored and must not satisfy this gate.\n" +
|
|
17
24
|
"\n" +
|
|
18
25
|
"options:\n" +
|
|
19
26
|
" -h, --help Show this help and exit 0\n" +
|
|
20
27
|
" --pr N Pull request number (required unless --help)\n" +
|
|
21
|
-
" --repo OWNER/REPO Repository (optional
|
|
28
|
+
" --repo OWNER/REPO Repository (optional; inferred from origin)\n" +
|
|
22
29
|
" --head-sha SHA Expected HEAD SHA (optional freshness check)\n" +
|
|
23
30
|
" --project-root PATH Project root (default: cwd)\n" +
|
|
24
31
|
" --call-site SITE solo | swarm-phase5-6 | swarm-phase6-cascade\n" +
|
|
@@ -27,18 +34,22 @@ export const REVIEW_MONITOR_HELP = "usage: task verify:review-monitor -- --pr <N
|
|
|
27
34
|
" --json Emit structured JSON on stdout\n" +
|
|
28
35
|
"\n" +
|
|
29
36
|
"exit codes:\n" +
|
|
30
|
-
" 0 READY Tier 1
|
|
31
|
-
" 1 NOT READY Tier 1 without
|
|
32
|
-
" 2 CONFIG Usage / path /
|
|
37
|
+
" 0 READY Tier 1 GitHub lease active, or Tier 3 Approach 3 with warning ack\n" +
|
|
38
|
+
" 1 NOT READY Tier 1 without GitHub lease, or Approach 3 blocked on Tier 1\n" +
|
|
39
|
+
" 2 CONFIG Usage / path / GitHub fetch error\n" +
|
|
33
40
|
"\n" +
|
|
34
|
-
"
|
|
41
|
+
"Claim a lease after spawning Approach 1:\n" +
|
|
35
42
|
" task review-monitor:register -- --pr <N> --monitor-agent-id <id> \\\n" +
|
|
36
43
|
" --platform-primitive cursor-task|spawn_subagent|start_agent \\\n" +
|
|
37
|
-
" [--head-sha SHA] [--repo OWNER/REPO]\n"
|
|
44
|
+
" [--head-sha SHA] [--repo OWNER/REPO] [--force]\n" +
|
|
45
|
+
"\n" +
|
|
46
|
+
"Release when done:\n" +
|
|
47
|
+
" task review-monitor:release -- --pr <N> [--monitor-agent-id <id>]\n";
|
|
38
48
|
export const REGISTER_HELP = "usage: task review-monitor:register -- --pr <N> --monitor-agent-id <id> \\\n" +
|
|
39
49
|
" --platform-primitive <primitive> [options]\n" +
|
|
40
50
|
"\n" +
|
|
41
|
-
"
|
|
51
|
+
"Claim the PR-anchored review-owner lease via a sticky GitHub PR comment\n" +
|
|
52
|
+
"(`<!-- deft:review-owner -->`). Does not write `.deft/review-monitor.json` (#2814).\n" +
|
|
42
53
|
"\n" +
|
|
43
54
|
"required:\n" +
|
|
44
55
|
" --pr N Pull request number\n" +
|
|
@@ -46,10 +57,25 @@ export const REGISTER_HELP = "usage: task review-monitor:register -- --pr <N> --
|
|
|
46
57
|
" --platform-primitive P start_agent | spawn_subagent | cursor-task\n" +
|
|
47
58
|
"\n" +
|
|
48
59
|
"options:\n" +
|
|
49
|
-
" --repo OWNER/REPO Repository\n" +
|
|
60
|
+
" --repo OWNER/REPO Repository (default: origin / DEFT_TRIAGE_REPO)\n" +
|
|
61
|
+
" --owner LOGIN GitHub login for claim (default: gh api user)\n" +
|
|
50
62
|
" --head-sha SHA HEAD SHA at monitor start\n" +
|
|
51
63
|
" --project-root PATH Project root (default: cwd)\n" +
|
|
52
|
-
" --parent-session-id ID Optional parent ritual / session id\n" +
|
|
64
|
+
" --parent-session-id ID Optional parent ritual / session id (audit only)\n" +
|
|
65
|
+
" --force Take over a non-expired foreign lease (loud)\n" +
|
|
66
|
+
"\n" +
|
|
67
|
+
"exit codes: 0 claimed / 1 conflict / 2 config error\n";
|
|
68
|
+
export const RELEASE_HELP = "usage: task review-monitor:release -- --pr <N> [options]\n" +
|
|
69
|
+
"\n" +
|
|
70
|
+
"End the PR-anchored review-owner lease by editing the sticky GitHub comment\n" +
|
|
71
|
+
"in place (#2814).\n" +
|
|
72
|
+
"\n" +
|
|
73
|
+
"options:\n" +
|
|
74
|
+
" --pr N Pull request number (required)\n" +
|
|
75
|
+
" --repo OWNER/REPO Repository (default: origin / DEFT_TRIAGE_REPO)\n" +
|
|
76
|
+
" --monitor-agent-id ID Release only when this monitor holds the lease\n" +
|
|
77
|
+
" --owner LOGIN Release only when this GitHub login holds the lease\n" +
|
|
78
|
+
" --project-root PATH Project root (default: cwd)\n" +
|
|
53
79
|
"\n" +
|
|
54
|
-
"exit codes: 0
|
|
80
|
+
"exit codes: 0 released / 1 held-by-other / 2 config error\n";
|
|
55
81
|
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type GhRestSeams } from "../scm/gh-rest.js";
|
|
2
|
+
import { type IssueComment } from "../umbrella-current-shape/index.js";
|
|
3
|
+
import { type ReviewOwnerComment } from "./lease-comment.js";
|
|
4
|
+
export type { IssueComment };
|
|
5
|
+
export interface ReviewOwnerGithubSeams extends GhRestSeams {
|
|
6
|
+
readonly fetchComments?: (repo: string, pr: number) => IssueComment[] | {
|
|
7
|
+
error: string;
|
|
8
|
+
};
|
|
9
|
+
readonly createComment?: (repo: string, pr: number, body: string) => {
|
|
10
|
+
id: number;
|
|
11
|
+
} | {
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
readonly updateComment?: (repo: string, commentId: number, body: string) => {
|
|
15
|
+
ok: true;
|
|
16
|
+
} | {
|
|
17
|
+
error: string;
|
|
18
|
+
};
|
|
19
|
+
readonly deleteComment?: (repo: string, commentId: number) => {
|
|
20
|
+
ok: true;
|
|
21
|
+
} | {
|
|
22
|
+
error: string;
|
|
23
|
+
};
|
|
24
|
+
readonly getGitHubLogin?: () => string | null;
|
|
25
|
+
}
|
|
26
|
+
export declare function listReviewOwnerComments(repo: string, pr: number, seams?: ReviewOwnerGithubSeams): ReviewOwnerComment[] | {
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function createReviewOwnerComment(repo: string, pr: number, body: string, seams?: ReviewOwnerGithubSeams): {
|
|
30
|
+
id: number;
|
|
31
|
+
} | {
|
|
32
|
+
error: string;
|
|
33
|
+
};
|
|
34
|
+
export declare function updateReviewOwnerComment(repo: string, commentId: number, body: string, seams?: ReviewOwnerGithubSeams): {
|
|
35
|
+
ok: true;
|
|
36
|
+
} | {
|
|
37
|
+
error: string;
|
|
38
|
+
};
|
|
39
|
+
export declare function deleteReviewOwnerComment(repo: string, commentId: number, seams?: ReviewOwnerGithubSeams): {
|
|
40
|
+
ok: true;
|
|
41
|
+
} | {
|
|
42
|
+
error: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function resolveGitHubLogin(seams?: ReviewOwnerGithubSeams): string | null;
|
|
45
|
+
//# sourceMappingURL=github-lease.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { resolveBinary } from "../scm/binary.js";
|
|
3
|
+
import { DEFAULT_TIMEOUT_S, restDeleteComment, restGetUser, restPostComment, restUpdateComment, } from "../scm/gh-rest.js";
|
|
4
|
+
import { SUBPROCESS_MAX_BUFFER } from "../subprocess/max-buffer.js";
|
|
5
|
+
import { isMaintainerAuthored, parseCommentsFromGhStdout, } from "../umbrella-current-shape/index.js";
|
|
6
|
+
import { mapCommentEntry } from "./lease-comment.js";
|
|
7
|
+
function defaultFetchComments(repo, pr, seams) {
|
|
8
|
+
const binary = resolveBinary(seams.whichFn);
|
|
9
|
+
const path = `repos/${repo}/issues/${pr}/comments?per_page=100`;
|
|
10
|
+
const proc = spawnSync(binary, ["api", "--paginate", path], {
|
|
11
|
+
encoding: "utf8",
|
|
12
|
+
maxBuffer: SUBPROCESS_MAX_BUFFER,
|
|
13
|
+
timeout: DEFAULT_TIMEOUT_S * 1000,
|
|
14
|
+
});
|
|
15
|
+
if (proc.error !== undefined) {
|
|
16
|
+
return { error: `fetch PR #${pr} comments (${repo}) failed: ${proc.error.message}` };
|
|
17
|
+
}
|
|
18
|
+
if (proc.status !== 0) {
|
|
19
|
+
return {
|
|
20
|
+
error: `fetch PR #${pr} comments (${repo}) failed: ${(proc.stderr || proc.stdout || "").trim()}`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return parseCommentsFromGhStdout(String(proc.stdout ?? ""));
|
|
25
|
+
}
|
|
26
|
+
catch (exc) {
|
|
27
|
+
return {
|
|
28
|
+
error: `fetch PR #${pr} comments (${repo}) returned non-JSON: ${String(exc)}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function listReviewOwnerComments(repo, pr, seams = {}) {
|
|
33
|
+
const fetcher = seams.fetchComments ?? ((r, n) => defaultFetchComments(r, n, seams));
|
|
34
|
+
const fetched = fetcher(repo, pr);
|
|
35
|
+
if (!Array.isArray(fetched)) {
|
|
36
|
+
return fetched;
|
|
37
|
+
}
|
|
38
|
+
const comments = [];
|
|
39
|
+
for (const entry of fetched) {
|
|
40
|
+
if (!isMaintainerAuthored(entry.authorAssociation)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const mapped = mapCommentEntry({
|
|
44
|
+
id: entry.id,
|
|
45
|
+
body: entry.body,
|
|
46
|
+
created_at: entry.updatedAt,
|
|
47
|
+
});
|
|
48
|
+
if (mapped !== null) {
|
|
49
|
+
comments.push(mapped);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return comments;
|
|
53
|
+
}
|
|
54
|
+
export function createReviewOwnerComment(repo, pr, body, seams = {}) {
|
|
55
|
+
if (seams.createComment !== undefined) {
|
|
56
|
+
return seams.createComment(repo, pr, body);
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const created = restPostComment(repo, pr, body, seams);
|
|
60
|
+
const id = created.id;
|
|
61
|
+
if (typeof id !== "number") {
|
|
62
|
+
return { error: "create comment: response missing id" };
|
|
63
|
+
}
|
|
64
|
+
return { id };
|
|
65
|
+
}
|
|
66
|
+
catch (exc) {
|
|
67
|
+
return { error: String(exc.message ?? exc) };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function updateReviewOwnerComment(repo, commentId, body, seams = {}) {
|
|
71
|
+
if (seams.updateComment !== undefined) {
|
|
72
|
+
return seams.updateComment(repo, commentId, body);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
restUpdateComment(repo, commentId, body, seams);
|
|
76
|
+
return { ok: true };
|
|
77
|
+
}
|
|
78
|
+
catch (exc) {
|
|
79
|
+
return { error: String(exc.message ?? exc) };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function deleteReviewOwnerComment(repo, commentId, seams = {}) {
|
|
83
|
+
if (seams.deleteComment !== undefined) {
|
|
84
|
+
return seams.deleteComment(repo, commentId);
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
restDeleteComment(repo, commentId, seams);
|
|
88
|
+
return { ok: true };
|
|
89
|
+
}
|
|
90
|
+
catch (exc) {
|
|
91
|
+
return { error: String(exc.message ?? exc) };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function resolveGitHubLogin(seams = {}) {
|
|
95
|
+
if (seams.getGitHubLogin !== undefined) {
|
|
96
|
+
return seams.getGitHubLogin();
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const user = restGetUser(seams);
|
|
100
|
+
return typeof user.login === "string" && user.login.length > 0 ? user.login : null;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=github-lease.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PlatformPrimitive } from "./tier-detection.js";
|
|
2
|
+
export declare function parseIso8601Utc(value: string): Date | null;
|
|
3
|
+
export interface ReviewOwnerLease {
|
|
4
|
+
readonly owner: string;
|
|
5
|
+
readonly monitor_agent_id: string;
|
|
6
|
+
readonly head_sha: string | null;
|
|
7
|
+
readonly started_at: string;
|
|
8
|
+
readonly expires_at: string;
|
|
9
|
+
readonly platform_primitive: PlatformPrimitive;
|
|
10
|
+
readonly ended_at: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface ReviewOwnerComment {
|
|
13
|
+
readonly id: number;
|
|
14
|
+
readonly body: string;
|
|
15
|
+
readonly createdAt: string;
|
|
16
|
+
readonly lease: ReviewOwnerLease | null;
|
|
17
|
+
}
|
|
18
|
+
/** True when the comment body contains the review-owner marker block. */
|
|
19
|
+
export declare function hasReviewOwnerMarker(body: string): boolean;
|
|
20
|
+
export declare function parseReviewOwnerLease(body: string): ReviewOwnerLease | null;
|
|
21
|
+
export declare function renderReviewOwnerComment(lease: ReviewOwnerLease): string;
|
|
22
|
+
export declare function renderReleasedReviewOwnerComment(endedAt: string): string;
|
|
23
|
+
export declare function computeExpiresAt(startedAt: Date, staleMinutes?: number): string;
|
|
24
|
+
export declare function isLeaseActive(lease: ReviewOwnerLease, options?: {
|
|
25
|
+
now?: Date;
|
|
26
|
+
headSha?: string | null;
|
|
27
|
+
}): boolean;
|
|
28
|
+
export declare function isLeaseExpired(lease: ReviewOwnerLease, now?: Date): boolean;
|
|
29
|
+
export declare function mapCommentEntry(entry: unknown): ReviewOwnerComment | null;
|
|
30
|
+
/** Oldest comment id wins create-race resolution (#2814). */
|
|
31
|
+
export declare function selectWinningReviewOwnerComment(comments: readonly ReviewOwnerComment[]): ReviewOwnerComment | null;
|
|
32
|
+
export declare function findActiveLeaseComment(comments: readonly ReviewOwnerComment[], options?: {
|
|
33
|
+
now?: Date;
|
|
34
|
+
headSha?: string | null;
|
|
35
|
+
}): ReviewOwnerComment | null;
|
|
36
|
+
//# sourceMappingURL=lease-comment.d.ts.map
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { DEFAULT_STALE_MINUTES, REVIEW_OWNER_MARKER_END, REVIEW_OWNER_MARKER_START, } from "./constants.js";
|
|
2
|
+
export function parseIso8601Utc(value) {
|
|
3
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
let candidate = trimmed;
|
|
8
|
+
if (trimmed.endsWith("Z")) {
|
|
9
|
+
candidate = `${trimmed.slice(0, -1)}+00:00`;
|
|
10
|
+
}
|
|
11
|
+
if (!candidate.endsWith("+00:00")) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const parsed = new Date(candidate);
|
|
15
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return parsed;
|
|
19
|
+
}
|
|
20
|
+
const FIELD_RE = /^(owner|monitor_agent_id|head_sha|started_at|expires_at|platform_primitive|ended_at):\s*(.*)$/;
|
|
21
|
+
/** True when the comment body contains the review-owner marker block. */
|
|
22
|
+
export function hasReviewOwnerMarker(body) {
|
|
23
|
+
return body.includes(REVIEW_OWNER_MARKER_START);
|
|
24
|
+
}
|
|
25
|
+
function parseFieldBlock(body) {
|
|
26
|
+
const start = body.indexOf(REVIEW_OWNER_MARKER_START);
|
|
27
|
+
const end = body.indexOf(REVIEW_OWNER_MARKER_END);
|
|
28
|
+
if (start < 0 || end < 0 || end <= start) {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
const block = body.slice(start + REVIEW_OWNER_MARKER_START.length, end);
|
|
32
|
+
const fields = {};
|
|
33
|
+
for (const line of block.split("\n")) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (trimmed.length === 0) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const match = FIELD_RE.exec(trimmed);
|
|
39
|
+
if (match?.[1] !== undefined) {
|
|
40
|
+
fields[match[1]] = (match[2] ?? "").trim();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return fields;
|
|
44
|
+
}
|
|
45
|
+
export function parseReviewOwnerLease(body) {
|
|
46
|
+
const fields = parseFieldBlock(body);
|
|
47
|
+
const owner = fields.owner ?? "";
|
|
48
|
+
const monitorAgentId = fields.monitor_agent_id ?? "";
|
|
49
|
+
const startedAt = fields.started_at ?? "";
|
|
50
|
+
const expiresAt = fields.expires_at ?? "";
|
|
51
|
+
const platformPrimitive = fields.platform_primitive ?? "";
|
|
52
|
+
if (owner.length === 0 ||
|
|
53
|
+
monitorAgentId.length === 0 ||
|
|
54
|
+
startedAt.length === 0 ||
|
|
55
|
+
expiresAt.length === 0 ||
|
|
56
|
+
platformPrimitive.length === 0) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const headShaRaw = fields.head_sha ?? "";
|
|
60
|
+
const endedAtRaw = fields.ended_at ?? "";
|
|
61
|
+
return {
|
|
62
|
+
owner,
|
|
63
|
+
monitor_agent_id: monitorAgentId,
|
|
64
|
+
head_sha: headShaRaw.length > 0 ? headShaRaw : null,
|
|
65
|
+
started_at: startedAt,
|
|
66
|
+
expires_at: expiresAt,
|
|
67
|
+
platform_primitive: platformPrimitive,
|
|
68
|
+
ended_at: endedAtRaw.length > 0 ? endedAtRaw : null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function renderReviewOwnerComment(lease) {
|
|
72
|
+
const headShaLine = lease.head_sha !== null && lease.head_sha.length > 0
|
|
73
|
+
? `head_sha: ${lease.head_sha}\n`
|
|
74
|
+
: "head_sha:\n";
|
|
75
|
+
const endedLine = lease.ended_at !== null && lease.ended_at.length > 0 ? `ended_at: ${lease.ended_at}\n` : "";
|
|
76
|
+
return (`${REVIEW_OWNER_MARKER_START}\n` +
|
|
77
|
+
`owner: ${lease.owner}\n` +
|
|
78
|
+
`monitor_agent_id: ${lease.monitor_agent_id}\n` +
|
|
79
|
+
headShaLine +
|
|
80
|
+
`started_at: ${lease.started_at}\n` +
|
|
81
|
+
`expires_at: ${lease.expires_at}\n` +
|
|
82
|
+
`platform_primitive: ${lease.platform_primitive}\n` +
|
|
83
|
+
endedLine +
|
|
84
|
+
`${REVIEW_OWNER_MARKER_END}`);
|
|
85
|
+
}
|
|
86
|
+
export function renderReleasedReviewOwnerComment(endedAt) {
|
|
87
|
+
return `${REVIEW_OWNER_MARKER_START}\n` + `ended_at: ${endedAt}\n` + `${REVIEW_OWNER_MARKER_END}`;
|
|
88
|
+
}
|
|
89
|
+
export function computeExpiresAt(startedAt, staleMinutes = DEFAULT_STALE_MINUTES) {
|
|
90
|
+
return new Date(startedAt.getTime() + staleMinutes * 60 * 1000).toISOString();
|
|
91
|
+
}
|
|
92
|
+
export function isLeaseActive(lease, options = {}) {
|
|
93
|
+
if (lease.ended_at !== null) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const started = parseIso8601Utc(lease.started_at);
|
|
97
|
+
const expires = parseIso8601Utc(lease.expires_at);
|
|
98
|
+
const now = options.now ?? new Date();
|
|
99
|
+
if (started === null || expires === null) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
if (now.getTime() > expires.getTime()) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (options.headSha !== undefined && options.headSha !== null && lease.head_sha !== null) {
|
|
106
|
+
return lease.head_sha === options.headSha;
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
export function isLeaseExpired(lease, now = new Date()) {
|
|
111
|
+
if (lease.ended_at !== null) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
const expires = parseIso8601Utc(lease.expires_at);
|
|
115
|
+
if (expires === null) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return now.getTime() > expires.getTime();
|
|
119
|
+
}
|
|
120
|
+
export function mapCommentEntry(entry) {
|
|
121
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const rec = entry;
|
|
125
|
+
if (typeof rec.id !== "number" || typeof rec.body !== "string") {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
if (!hasReviewOwnerMarker(rec.body)) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
id: rec.id,
|
|
133
|
+
body: rec.body,
|
|
134
|
+
createdAt: typeof rec.created_at === "string" ? rec.created_at : "",
|
|
135
|
+
lease: parseReviewOwnerLease(rec.body),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** Oldest comment id wins create-race resolution (#2814). */
|
|
139
|
+
export function selectWinningReviewOwnerComment(comments) {
|
|
140
|
+
if (comments.length === 0) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return [...comments].sort((a, b) => a.id - b.id)[0] ?? null;
|
|
144
|
+
}
|
|
145
|
+
export function findActiveLeaseComment(comments, options = {}) {
|
|
146
|
+
const active = comments.filter((comment) => comment.lease !== null && isLeaseActive(comment.lease, options));
|
|
147
|
+
if (active.length === 0) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
return selectWinningReviewOwnerComment(active);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=lease-comment.js.map
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
+
import { EXIT_CONFIG_ERROR, EXIT_CONFLICT, EXIT_READY } from "./constants.js";
|
|
2
|
+
import { type ReviewOwnerGithubSeams } from "./github-lease.js";
|
|
3
|
+
import { parseIso8601Utc } from "./lease-comment.js";
|
|
1
4
|
import type { PlatformPrimitive } from "./tier-detection.js";
|
|
5
|
+
export { parseIso8601Utc };
|
|
6
|
+
/** Legacy shape retained for verify JSON compatibility (#2655 / #2814). */
|
|
2
7
|
export interface ReviewMonitorRecord {
|
|
3
8
|
readonly pr: number;
|
|
4
9
|
readonly repo: string | null;
|
|
5
10
|
readonly head_sha: string | null;
|
|
6
11
|
readonly platform_primitive: PlatformPrimitive;
|
|
7
12
|
readonly monitor_agent_id: string;
|
|
13
|
+
readonly owner: string;
|
|
8
14
|
readonly started_at: string;
|
|
9
|
-
readonly
|
|
15
|
+
readonly expires_at: string;
|
|
16
|
+
readonly worktree_path: string | null;
|
|
10
17
|
readonly parent_session_id: string | null;
|
|
11
18
|
readonly ended_at: string | null;
|
|
19
|
+
readonly comment_id: number | null;
|
|
12
20
|
}
|
|
13
21
|
export interface ReviewMonitorFile {
|
|
14
22
|
readonly schema_version: number;
|
|
15
23
|
readonly records: ReviewMonitorRecord[];
|
|
16
24
|
}
|
|
17
|
-
export declare function reviewMonitorPath(projectRoot: string): string;
|
|
18
|
-
export declare function emptyReviewMonitorFile(): ReviewMonitorFile;
|
|
19
|
-
export declare function readReviewMonitorFile(path: string): {
|
|
20
|
-
data: ReviewMonitorFile | null;
|
|
21
|
-
error: string | null;
|
|
22
|
-
};
|
|
23
|
-
export declare function writeReviewMonitorFile(path: string, data: ReviewMonitorFile): void;
|
|
24
25
|
export interface RegisterReviewMonitorInput {
|
|
25
26
|
readonly pr: number;
|
|
26
27
|
readonly repo?: string | null;
|
|
@@ -29,13 +30,43 @@ export interface RegisterReviewMonitorInput {
|
|
|
29
30
|
readonly monitorAgentId: string;
|
|
30
31
|
readonly projectRoot: string;
|
|
31
32
|
readonly parentSessionId?: string | null;
|
|
33
|
+
readonly owner?: string | null;
|
|
32
34
|
readonly startedAt?: Date;
|
|
35
|
+
readonly staleMinutes?: number;
|
|
36
|
+
readonly force?: boolean;
|
|
37
|
+
readonly seams?: ReviewOwnerGithubSeams;
|
|
33
38
|
}
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
export interface RegisterReviewMonitorResult {
|
|
40
|
+
readonly exitCode: typeof EXIT_READY | typeof EXIT_CONFLICT | typeof EXIT_CONFIG_ERROR;
|
|
41
|
+
readonly message: string;
|
|
42
|
+
readonly record: ReviewMonitorRecord | null;
|
|
43
|
+
readonly commentId: number | null;
|
|
44
|
+
readonly priorOwner: string | null;
|
|
45
|
+
}
|
|
46
|
+
export interface ReleaseReviewMonitorInput {
|
|
47
|
+
readonly pr: number;
|
|
48
|
+
readonly repo?: string | null;
|
|
49
|
+
readonly monitorAgentId?: string | null;
|
|
50
|
+
readonly owner?: string | null;
|
|
51
|
+
readonly projectRoot: string;
|
|
52
|
+
readonly endedAt?: Date;
|
|
53
|
+
readonly seams?: ReviewOwnerGithubSeams;
|
|
54
|
+
}
|
|
55
|
+
export interface ReleaseReviewMonitorResult {
|
|
56
|
+
readonly exitCode: typeof EXIT_READY | typeof EXIT_CONFLICT | typeof EXIT_CONFIG_ERROR;
|
|
57
|
+
readonly message: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function registerReviewMonitor(input: RegisterReviewMonitorInput): RegisterReviewMonitorResult;
|
|
60
|
+
export declare function releaseReviewMonitor(input: ReleaseReviewMonitorInput): ReleaseReviewMonitorResult;
|
|
61
|
+
export declare function findActiveMonitorForPrFromComments(comments: readonly {
|
|
62
|
+
id: number;
|
|
63
|
+
body: string;
|
|
64
|
+
}[], pr: number, options: {
|
|
65
|
+
now?: Date;
|
|
66
|
+
staleMinutes?: number;
|
|
67
|
+
headSha?: string | null;
|
|
68
|
+
repo?: string | null;
|
|
69
|
+
}): ReviewMonitorRecord | null;
|
|
39
70
|
export declare function isRecordActive(record: ReviewMonitorRecord, options: {
|
|
40
71
|
now?: Date;
|
|
41
72
|
staleMinutes?: number;
|
|
@@ -46,5 +77,22 @@ export declare function findActiveMonitorForPr(file: ReviewMonitorFile, pr: numb
|
|
|
46
77
|
staleMinutes?: number;
|
|
47
78
|
headSha?: string | null;
|
|
48
79
|
}): ReviewMonitorRecord | null;
|
|
80
|
+
export declare function emptyReviewMonitorFile(): ReviewMonitorFile;
|
|
81
|
+
/** @deprecated Local `.deft/review-monitor.json` is obsolete (#2814); always empty. */
|
|
82
|
+
export declare function readReviewMonitorFile(_path: string): {
|
|
83
|
+
data: ReviewMonitorFile | null;
|
|
84
|
+
error: string | null;
|
|
85
|
+
};
|
|
86
|
+
/** @deprecated Local `.deft/review-monitor.json` is obsolete (#2814); no-op. */
|
|
87
|
+
export declare function writeReviewMonitorFile(_path: string, _data: ReviewMonitorFile): void;
|
|
88
|
+
/** @deprecated Local `.deft/review-monitor.json` is obsolete (#2814). */
|
|
89
|
+
export declare function reviewMonitorPath(projectRoot: string): string;
|
|
49
90
|
export declare function defaultSubagentStatusDir(projectRoot: string): string;
|
|
91
|
+
export declare function fetchActiveMonitorFromGithub(repo: string, pr: number, options?: {
|
|
92
|
+
now?: Date;
|
|
93
|
+
headSha?: string | null;
|
|
94
|
+
seams?: ReviewOwnerGithubSeams;
|
|
95
|
+
}): ReviewMonitorRecord | null | {
|
|
96
|
+
error: string;
|
|
97
|
+
};
|
|
50
98
|
//# sourceMappingURL=record.d.ts.map
|