greprag 5.65.2 → 5.65.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codex-chip-hooks.js +2 -2
- package/dist/codex-chip-hooks.js.map +1 -1
- package/dist/commands/agent-doctrine-file.d.ts +27 -9
- package/dist/commands/agent-doctrine-file.js +74 -47
- package/dist/commands/agent-doctrine-file.js.map +1 -1
- package/dist/commands/agents.d.ts +2 -2
- package/dist/commands/agents.js +167 -48
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/codex-chip/command.js +4 -2
- package/dist/commands/codex-chip/command.js.map +1 -1
- package/dist/commands/codex-chip/goals.d.ts +3 -3
- package/dist/commands/codex-chip/goals.js +3 -3
- package/dist/commands/codex-chip/goals.js.map +1 -1
- package/dist/commands/codex-chip/help.d.ts +1 -1
- package/dist/commands/codex-chip/help.js +4 -3
- package/dist/commands/codex-chip/help.js.map +1 -1
- package/dist/commands/codex-chip/model.d.ts +6 -2
- package/dist/commands/codex-chip/model.js +12 -2
- package/dist/commands/codex-chip/model.js.map +1 -1
- package/dist/commands/codex-chip/native.js +2 -2
- package/dist/commands/codex-chip/native.js.map +1 -1
- package/dist/commands/codex-chip/prompt.js +8 -4
- package/dist/commands/codex-chip/prompt.js.map +1 -1
- package/dist/commands/codex-chip/selection.d.ts +5 -4
- package/dist/commands/codex-chip/selection.js +28 -9
- package/dist/commands/codex-chip/selection.js.map +1 -1
- package/dist/commands/codex-model-policy.d.ts +1 -1
- package/dist/commands/codex-model-policy.js +17 -6
- package/dist/commands/codex-model-policy.js.map +1 -1
- package/dist/commands/codex.js +1 -1
- package/dist/commands/init.js +19 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/load-primer-reminder.js +1 -1
- package/dist/commands/load-primer-reminder.js.map +1 -1
- package/dist/commands/mechanic-spawn.js +1 -1
- package/dist/commands/mechanic-spawn.js.map +1 -1
- package/dist/commands/opencode-chip-mission.d.ts +4 -4
- package/dist/commands/opencode-chip-mission.js.map +1 -1
- package/dist/commands/opencode-chip-store.d.ts +2 -2
- package/dist/commands/opencode-chip.js +3 -2
- package/dist/commands/opencode-chip.js.map +1 -1
- package/dist/commands/parity.js +1 -1
- package/dist/commands/skill-mirror-reminder.d.ts +3 -4
- package/dist/commands/skill-mirror-reminder.js +13 -8
- package/dist/commands/skill-mirror-reminder.js.map +1 -1
- package/dist/commands/skill.js +28 -0
- package/dist/commands/skill.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/native-skill-mirror.d.ts +30 -0
- package/dist/native-skill-mirror.js +230 -0
- package/dist/native-skill-mirror.js.map +1 -0
- package/dist/opencode-plugin.bundle.js +9 -4
- package/dist/skill-mirror-client.d.ts +2 -5
- package/dist/skill-mirror-client.js +18 -6
- package/dist/skill-mirror-client.js.map +1 -1
- package/dist/skill-mirror-files.d.ts +6 -0
- package/dist/skill-mirror-files.js +51 -0
- package/dist/skill-mirror-files.js.map +1 -0
- package/package.json +1 -1
- package/skill/greprag/docs/codex-chip.md +4 -3
- package/skill/templates/chip-leader.md +37 -15
- package/skill/templates/codex-chip-spawn.md +40 -25
package/dist/codex-chip-hooks.js
CHANGED
|
@@ -66,8 +66,8 @@ function context(input) {
|
|
|
66
66
|
// adr: adr/codex-landing-doctrine.md — default parent-owned landing + the one FIX exception.
|
|
67
67
|
'Landing: the parent owns merge, archive, and cleanup — do not merge, push, deploy, clean up, or edit the parent checkout. ONE exception: a mission whose first line begins `FIX:` (emitted by `greprag fix spawn`) carries its own Phase 3 landing contract — after peer conferral it merges its branch to main itself; cleanup stays native (`Clearance: safe to archive`), and push/release stays operator-gated.',
|
|
68
68
|
];
|
|
69
|
-
if (chip
|
|
70
|
-
lines.push('Harness: Codex.
|
|
69
|
+
if ((0, model_1.chipMissionKind)(chip) === 'fix') {
|
|
70
|
+
lines.push('Harness: Codex. Mission: visible native FIX chip with ordinary writable authority, not an internal subagent.', 'Scope: repair GrepRAG-owned harness surfaces in this checkout: load entries, skill templates, docs, hook context, CLI messages, and tests. Codex owns native task creation, worktrees, permissions, Git, and task lifecycle.', 'Own diagnosis, implementation, tests, commit, and parent report. Inspect Codex behavior only far enough to correct GrepRAG guidance or report a precise external blocker.', 'FIX peer handoff: if a peer offers to coordinate, integrate, rework, or take over a harness repair, hand off branch/commit, dirty files, checks, blockers, and caveats. Do not defend patch ownership; peers may take ownership within their assigned GrepRAG harness scope.', 'Visible delegation route: load `codex-chip-spawn` and create the child with `codex_app__create_thread` using the current project worktree target; load `chip-leader` for multi-chip seams. Never use `multi_agent_v1__spawn_agent` for a visible chip.');
|
|
71
71
|
}
|
|
72
72
|
return output(input.hook_event_name || 'SessionStart', lines.join('\n'));
|
|
73
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-chip-hooks.js","sourceRoot":"","sources":["../src/codex-chip-hooks.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,sDAMC;AAzFD,2CAA6B;AAE7B,uDAAoE;AACpE,
|
|
1
|
+
{"version":3,"file":"codex-chip-hooks.js","sourceRoot":"","sources":["../src/codex-chip-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,30 +1,48 @@
|
|
|
1
|
-
/** Pure
|
|
1
|
+
/** Pure full-file follower helpers for canonical agent doctrine.
|
|
2
|
+
*
|
|
3
|
+
* Follower files must stay byte-faithful instruction files. Ownership state
|
|
4
|
+
* lives outside the markdown in the GrepRAG parity manifest.
|
|
5
|
+
*/
|
|
2
6
|
export interface DoctrineFollowerRender {
|
|
3
7
|
scopeKey: string;
|
|
4
8
|
harness: 'claude-code' | 'codex' | 'opencode';
|
|
5
9
|
revision: number;
|
|
6
10
|
body: string;
|
|
7
11
|
}
|
|
12
|
+
export interface DoctrineFollowerBaseline {
|
|
13
|
+
syncedRevision?: number | null;
|
|
14
|
+
syncedHash?: string | null;
|
|
15
|
+
syncedAt?: string | null;
|
|
16
|
+
dirtyAt?: string | null;
|
|
17
|
+
}
|
|
8
18
|
export type DoctrineFollowerOutcome = {
|
|
9
19
|
action: 'current';
|
|
10
20
|
content: string;
|
|
11
21
|
renderHash: string;
|
|
22
|
+
shouldReportSync: boolean;
|
|
12
23
|
} | {
|
|
13
|
-
action: 'seed' | 'update' | '
|
|
24
|
+
action: 'seed' | 'update' | 'force';
|
|
14
25
|
content: string;
|
|
15
26
|
renderHash: string;
|
|
27
|
+
shouldReportSync: true;
|
|
16
28
|
} | {
|
|
17
|
-
action: '
|
|
29
|
+
action: 'local-change' | 'conflict' | 'unmanaged';
|
|
18
30
|
content: string;
|
|
19
31
|
reason: string;
|
|
20
32
|
renderHash: string;
|
|
33
|
+
shouldReportSync: false;
|
|
21
34
|
};
|
|
22
35
|
export declare function doctrineRenderHash(value: string): string;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
/** Return only the canonical body from an old marker-managed follower. */
|
|
37
|
+
export declare function extractDoctrineFollowerBody(source: string): string | null;
|
|
38
|
+
export declare function renderDoctrineFollower(render: DoctrineFollowerRender): string;
|
|
39
|
+
/** Plan a full-file follower write.
|
|
40
|
+
*
|
|
41
|
+
* No marker comments are generated. A write is automatic only when the file is
|
|
42
|
+
* empty/missing, already exactly current, or still equals its last verified
|
|
43
|
+
* baseline. If both canon and disk changed since that baseline, the caller gets
|
|
44
|
+
* `conflict` and must not write.
|
|
45
|
+
*/
|
|
46
|
+
export declare function planDoctrineFollowerWrite(source: string, render: DoctrineFollowerRender, baseline: DoctrineFollowerBaseline | null | undefined, options?: {
|
|
28
47
|
force?: boolean;
|
|
29
|
-
adoptWholeFile?: boolean;
|
|
30
48
|
}): DoctrineFollowerOutcome;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/** Pure
|
|
2
|
+
/** Pure full-file follower helpers for canonical agent doctrine.
|
|
3
|
+
*
|
|
4
|
+
* Follower files must stay byte-faithful instruction files. Ownership state
|
|
5
|
+
* lives outside the markdown in the GrepRAG parity manifest.
|
|
6
|
+
*/
|
|
3
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
8
|
if (k2 === undefined) k2 = k;
|
|
5
9
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -35,70 +39,93 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
39
|
})();
|
|
36
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
41
|
exports.doctrineRenderHash = doctrineRenderHash;
|
|
38
|
-
exports.
|
|
39
|
-
exports.
|
|
42
|
+
exports.extractDoctrineFollowerBody = extractDoctrineFollowerBody;
|
|
43
|
+
exports.renderDoctrineFollower = renderDoctrineFollower;
|
|
44
|
+
exports.planDoctrineFollowerWrite = planDoctrineFollowerWrite;
|
|
40
45
|
const crypto = __importStar(require("node:crypto"));
|
|
41
|
-
function normalizedBody(value) {
|
|
42
|
-
return value.replace(/\r\n/g, '\n').trim();
|
|
43
|
-
}
|
|
44
46
|
function doctrineRenderHash(value) {
|
|
45
|
-
return crypto.createHash('sha256').update(
|
|
47
|
+
return crypto.createHash('sha256').update(value).digest('hex');
|
|
48
|
+
}
|
|
49
|
+
const LEGACY_BLOCK_RE = /<!--\s*greprag:agents:start\s+scope=\S+\s+harness=\S+\s+revision=(\d+)\s+hash=([a-f0-9]{64})(?:\s+chars=(\d+))?\s*-->\r?\n([\s\S]*?)<!--\s*greprag:agents:end\s*-->/i;
|
|
50
|
+
/** Return only the canonical body from an old marker-managed follower. */
|
|
51
|
+
function extractDoctrineFollowerBody(source) {
|
|
52
|
+
const match = source.match(LEGACY_BLOCK_RE);
|
|
53
|
+
if (!match)
|
|
54
|
+
return null;
|
|
55
|
+
const chars = match[3] === undefined ? null : Number(match[3]);
|
|
56
|
+
const captured = match[4];
|
|
57
|
+
return chars === null ? captured.replace(/\r?\n$/, '') : captured.slice(0, chars);
|
|
58
|
+
}
|
|
59
|
+
function renderDoctrineFollower(render) {
|
|
60
|
+
return render.body;
|
|
46
61
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
const hash = doctrineRenderHash(body);
|
|
50
|
-
return `<!-- greprag:agents:start scope=${render.scopeKey} harness=${render.harness} revision=${render.revision} hash=${hash} -->\n`
|
|
51
|
-
+ `${body}\n<!-- greprag:agents:end -->`;
|
|
62
|
+
function hasSyncedBaseline(baseline) {
|
|
63
|
+
return !!baseline?.syncedHash && /^[a-f0-9]{64}$/i.test(baseline.syncedHash);
|
|
52
64
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return
|
|
57
|
-
whole: match[0],
|
|
58
|
-
revision: Number(match[1]),
|
|
59
|
-
declaredHash: match[2].toLowerCase(),
|
|
60
|
-
inner: match[3],
|
|
61
|
-
} : null;
|
|
65
|
+
function canonChangedSinceBaseline(baseline, render, renderHash) {
|
|
66
|
+
if (!hasSyncedBaseline(baseline))
|
|
67
|
+
return false;
|
|
68
|
+
return baseline.syncedRevision !== render.revision || baseline.syncedHash !== renderHash;
|
|
62
69
|
}
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
/** Plan a full-file follower write.
|
|
71
|
+
*
|
|
72
|
+
* No marker comments are generated. A write is automatic only when the file is
|
|
73
|
+
* empty/missing, already exactly current, or still equals its last verified
|
|
74
|
+
* baseline. If both canon and disk changed since that baseline, the caller gets
|
|
75
|
+
* `conflict` and must not write.
|
|
76
|
+
*/
|
|
77
|
+
function planDoctrineFollowerWrite(source, render, baseline, options = {}) {
|
|
78
|
+
const body = renderDoctrineFollower(render);
|
|
79
|
+
const renderHash = doctrineRenderHash(body);
|
|
80
|
+
const sourceHash = doctrineRenderHash(source);
|
|
81
|
+
const baselineHash = baseline?.syncedHash?.toLowerCase() || null;
|
|
82
|
+
const synced = hasSyncedBaseline(baseline);
|
|
83
|
+
if (sourceHash === renderHash) {
|
|
77
84
|
return {
|
|
78
|
-
action: '
|
|
85
|
+
action: 'current',
|
|
79
86
|
content: source,
|
|
80
87
|
renderHash,
|
|
81
|
-
|
|
88
|
+
shouldReportSync: baseline?.syncedRevision !== render.revision || baselineHash !== renderHash,
|
|
82
89
|
};
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
if (options.force) {
|
|
92
|
+
return { action: 'force', content: body, renderHash, shouldReportSync: true };
|
|
93
|
+
}
|
|
94
|
+
if (!source.trim()) {
|
|
95
|
+
return { action: 'seed', content: body, renderHash, shouldReportSync: true };
|
|
96
|
+
}
|
|
97
|
+
if (!synced) {
|
|
86
98
|
return {
|
|
87
|
-
action: '
|
|
99
|
+
action: 'unmanaged',
|
|
88
100
|
content: source,
|
|
89
101
|
renderHash,
|
|
90
|
-
|
|
102
|
+
shouldReportSync: false,
|
|
103
|
+
reason: 'file has no external sync baseline; enroll only when bytes already match canon or use --force',
|
|
91
104
|
};
|
|
92
105
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
const diskChanged = sourceHash !== baselineHash;
|
|
107
|
+
const canonChanged = canonChangedSinceBaseline(baseline, render, renderHash);
|
|
108
|
+
const dirty = !!baseline?.dirtyAt && (!baseline.syncedAt || baseline.dirtyAt > baseline.syncedAt);
|
|
109
|
+
if (!diskChanged && canonChanged) {
|
|
110
|
+
return { action: 'update', content: body, renderHash, shouldReportSync: true };
|
|
111
|
+
}
|
|
112
|
+
if (diskChanged && canonChanged) {
|
|
113
|
+
return {
|
|
114
|
+
action: 'conflict',
|
|
115
|
+
content: source,
|
|
116
|
+
renderHash,
|
|
117
|
+
shouldReportSync: false,
|
|
118
|
+
reason: 'both canon and follower changed since the last verified sync; pull or reconcile explicitly',
|
|
119
|
+
};
|
|
97
120
|
}
|
|
98
121
|
return {
|
|
99
|
-
action: '
|
|
100
|
-
content: source
|
|
122
|
+
action: 'local-change',
|
|
123
|
+
content: source,
|
|
101
124
|
renderHash,
|
|
125
|
+
shouldReportSync: false,
|
|
126
|
+
reason: dirty
|
|
127
|
+
? 'follower has a worthy direct edit after sync; pull it to canon or revert it before push'
|
|
128
|
+
: 'follower changed since the last verified sync; pull it to canon or revert it before push',
|
|
102
129
|
};
|
|
103
130
|
}
|
|
104
131
|
//# sourceMappingURL=agent-doctrine-file.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-doctrine-file.js","sourceRoot":"","sources":["../../src/commands/agent-doctrine-file.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"agent-doctrine-file.js","sourceRoot":"","sources":["../../src/commands/agent-doctrine-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,8 +8,8 @@ export interface AgentDoctrineBootstrapResult {
|
|
|
8
8
|
blockedFollowers: number;
|
|
9
9
|
}
|
|
10
10
|
/** Init-time seed for the active harness. No canon is a clean no-op; only a
|
|
11
|
-
* missing/empty follower is written. Every existing file
|
|
12
|
-
*
|
|
11
|
+
* missing/empty follower is written. Every existing nonmatching file requires
|
|
12
|
+
* an explicit `agents push` or `agents pull`. */
|
|
13
13
|
export declare function bootstrapAgentDoctrine(apiKey: string, harness: Harness): Promise<AgentDoctrineBootstrapResult>;
|
|
14
14
|
export declare function runAgents(args: string[]): Promise<void>;
|
|
15
15
|
export {};
|
package/dist/commands/agents.js
CHANGED
|
@@ -46,16 +46,21 @@ const agent_doctrine_file_1 = require("./agent-doctrine-file");
|
|
|
46
46
|
const HELP = `greprag agents — canonical CLAUDE.md / AGENTS.md doctrine
|
|
47
47
|
|
|
48
48
|
USAGE
|
|
49
|
-
greprag agents
|
|
50
|
-
greprag agents
|
|
49
|
+
greprag agents pull <file> [--scope global|repo] [--harness <name>] [--push]
|
|
50
|
+
greprag agents push [--scope global|repo|all] [--check] [--force]
|
|
51
|
+
greprag agents adopt <file> [--scope global|repo] [--harness <name>] [--no-sync]
|
|
52
|
+
greprag agents revise <file> [--scope global|repo] [--harness <name>] [--no-sync]
|
|
53
|
+
greprag agents overlay set <harness> <file> [--scope global|repo] [--no-sync]
|
|
54
|
+
greprag agents overlay derive <harness> <shared-file> <rendered-file> [--scope global|repo] [--no-sync]
|
|
55
|
+
greprag agents overlay clear <harness> [--scope global|repo] [--no-sync]
|
|
51
56
|
greprag agents sync [--scope global|repo|all] [--check] [--force]
|
|
52
57
|
greprag agents status [--scope global|repo|all]
|
|
53
58
|
|
|
54
59
|
MODEL
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
Adopt and revise copy source bytes exactly; no model rewrites doctrine.
|
|
61
|
+
Harness translations are raw additive suffixes. Pull writes disk to canon.
|
|
62
|
+
Push writes canon to disk only when the external sync baseline is clean.
|
|
63
|
+
Status/check never writes.`;
|
|
59
64
|
function config(apiKeyOverride) {
|
|
60
65
|
return {
|
|
61
66
|
apiUrl: process.env.GREPRAG_API_URL || 'https://api.greprag.com',
|
|
@@ -133,19 +138,24 @@ function parityUnitName(scope, projectId, directory) {
|
|
|
133
138
|
: crypto.createHash('sha256').update(directory).digest('hex').slice(0, 8);
|
|
134
139
|
return `agent-doctrine-${projectId.slice(0, 8)}-${suffix}`;
|
|
135
140
|
}
|
|
136
|
-
function
|
|
137
|
-
|
|
141
|
+
function uniqueNonempty(values) {
|
|
142
|
+
const seen = new Set();
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const value of values) {
|
|
145
|
+
if (!value)
|
|
146
|
+
continue;
|
|
147
|
+
if (seen.has(value))
|
|
148
|
+
continue;
|
|
149
|
+
seen.add(value);
|
|
150
|
+
out.push(value);
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
138
153
|
}
|
|
139
154
|
function renderForTarget(doc, target) {
|
|
140
|
-
const parts = [doc.shared.trim()];
|
|
141
155
|
if (target.combinedAgents) {
|
|
142
|
-
|
|
143
|
-
parts.push(renderSection('OpenCode Overlay', doc.overlays.opencode));
|
|
156
|
+
return doc.shared + uniqueNonempty([doc.overlays.codex, doc.overlays.opencode]).join('');
|
|
144
157
|
}
|
|
145
|
-
|
|
146
|
-
parts.push(renderSection(`${target.harness} Overlay`, doc.overlays[target.harness]));
|
|
147
|
-
}
|
|
148
|
-
return parts.filter(Boolean).join('\n\n').trim() + '\n';
|
|
158
|
+
return doc.shared + (doc.overlays[target.harness] || '');
|
|
149
159
|
}
|
|
150
160
|
async function apiJson(pathname, init, apiKeyOverride) {
|
|
151
161
|
const cfg = config(apiKeyOverride);
|
|
@@ -192,6 +202,27 @@ async function fetchDocument(scope, projectId, directory, apiKey) {
|
|
|
192
202
|
throw error;
|
|
193
203
|
}
|
|
194
204
|
}
|
|
205
|
+
async function fetchFollowerBaselines(unitName, apiKey) {
|
|
206
|
+
try {
|
|
207
|
+
const body = await apiJson('/v1/parity/list', undefined, apiKey);
|
|
208
|
+
const unit = body.units.find((candidate) => candidate.name === unitName);
|
|
209
|
+
const baselines = new Map();
|
|
210
|
+
for (const follower of unit?.followers || []) {
|
|
211
|
+
if (!follower.path)
|
|
212
|
+
continue;
|
|
213
|
+
baselines.set(`${follower.harness}\0${follower.path}`, {
|
|
214
|
+
syncedRevision: follower.syncedRevision,
|
|
215
|
+
syncedHash: follower.syncedHash,
|
|
216
|
+
syncedAt: follower.syncedAt,
|
|
217
|
+
dirtyAt: follower.dirtyAt,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return baselines;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return new Map();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
195
226
|
function inferHarness(file, explicit) {
|
|
196
227
|
if (explicit === 'claude-code' || explicit === 'codex' || explicit === 'opencode')
|
|
197
228
|
return explicit;
|
|
@@ -230,22 +261,22 @@ async function syncOne(params) {
|
|
|
230
261
|
if (!doc) {
|
|
231
262
|
if (!params.quiet)
|
|
232
263
|
console.log(`${params.scope}: no canonical doctrine`);
|
|
233
|
-
return { canonical: false, current: 0, changed: 0, blocked: 0, drift: 0 };
|
|
264
|
+
return { canonical: false, current: 0, changed: 0, enrolled: 0, blocked: 0, drift: 0 };
|
|
234
265
|
}
|
|
235
266
|
const unitName = parityUnitName(params.scope, ctx.projectId, ctx.directory);
|
|
236
|
-
const
|
|
267
|
+
const baselines = await fetchFollowerBaselines(unitName, params.apiKey);
|
|
268
|
+
const stats = { canonical: true, current: 0, changed: 0, enrolled: 0, blocked: 0, drift: 0 };
|
|
237
269
|
for (const target of ctx.targets.filter(t => targetMatchesHarness(t, params.harness))) {
|
|
238
270
|
const source = fs.existsSync(target.actualPath)
|
|
239
271
|
? fs.readFileSync(target.actualPath, 'utf8')
|
|
240
272
|
: '';
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
const outcome = (0, agent_doctrine_file_1.patchDoctrineFollower)(source, {
|
|
273
|
+
const rendered = renderForTarget(doc, target);
|
|
274
|
+
const outcome = (0, agent_doctrine_file_1.planDoctrineFollowerWrite)(source, {
|
|
244
275
|
scopeKey: doc.scopeKey,
|
|
245
276
|
harness: target.harness,
|
|
246
277
|
revision: doc.revision,
|
|
247
|
-
body:
|
|
248
|
-
}, { force: params.force
|
|
278
|
+
body: rendered,
|
|
279
|
+
}, baselines.get(`${target.harness}\0${target.manifestPath}`), { force: params.force });
|
|
249
280
|
const current = outcome.action === 'current';
|
|
250
281
|
if (current)
|
|
251
282
|
stats.current++;
|
|
@@ -256,12 +287,20 @@ async function syncOne(params) {
|
|
|
256
287
|
console.log(` ${current ? 'fresh' : outcome.action.padEnd(9)} ${target.actualPath}${detail}`);
|
|
257
288
|
}
|
|
258
289
|
const seedOnlyBlocked = params.seedOnly && !current && outcome.action !== 'seed';
|
|
259
|
-
if (outcome.action === '
|
|
290
|
+
if (outcome.action === 'conflict' || outcome.action === 'local-change'
|
|
291
|
+
|| outcome.action === 'unmanaged' || seedOnlyBlocked) {
|
|
260
292
|
stats.blocked++;
|
|
261
293
|
continue;
|
|
262
294
|
}
|
|
263
|
-
if (params.check
|
|
295
|
+
if (params.check)
|
|
264
296
|
continue;
|
|
297
|
+
if (current) {
|
|
298
|
+
if (outcome.shouldReportSync) {
|
|
299
|
+
await reportSync(unitName, target, doc.revision, outcome.renderHash, params.apiKey);
|
|
300
|
+
stats.enrolled++;
|
|
301
|
+
}
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
265
304
|
fs.mkdirSync(path.dirname(target.actualPath), { recursive: true });
|
|
266
305
|
fs.writeFileSync(target.actualPath, outcome.content, 'utf8');
|
|
267
306
|
await reportSync(unitName, target, doc.revision, outcome.renderHash, params.apiKey);
|
|
@@ -269,31 +308,32 @@ async function syncOne(params) {
|
|
|
269
308
|
}
|
|
270
309
|
return stats;
|
|
271
310
|
}
|
|
272
|
-
async function
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (sourcePath && !fs.existsSync(sourcePath))
|
|
311
|
+
async function exactSourceCommand(args, mode) {
|
|
312
|
+
const from = args[0] && !args[0].startsWith('-') ? args[0] : undefined;
|
|
313
|
+
if (!from)
|
|
314
|
+
throw new Error(`${mode} requires a source file`);
|
|
315
|
+
const sourcePath = path.resolve(from);
|
|
316
|
+
if (!fs.existsSync(sourcePath))
|
|
279
317
|
throw new Error(`source file not found: ${sourcePath}`);
|
|
280
318
|
const scope = inferScope(sourcePath, flag(args, '--scope'));
|
|
281
|
-
|
|
319
|
+
const harness = inferHarness(sourcePath, flag(args, '--harness'));
|
|
282
320
|
const ctx = context(scope, args);
|
|
283
|
-
const current = adopt ? null : await fetchDocument(scope, ctx.projectId, ctx.directory);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
321
|
+
const current = mode === 'adopt' ? null : await fetchDocument(scope, ctx.projectId, ctx.directory);
|
|
322
|
+
const endpointMode = mode === 'pull'
|
|
323
|
+
? current ? 'revise' : 'adopt'
|
|
324
|
+
: mode;
|
|
325
|
+
const fileContent = fs.readFileSync(sourcePath, 'utf8');
|
|
326
|
+
const content = (0, agent_doctrine_file_1.extractDoctrineFollowerBody)(fileContent) ?? fileContent;
|
|
327
|
+
const body = await apiJson(`/v1/agents/${endpointMode}`, {
|
|
287
328
|
method: 'POST',
|
|
288
329
|
body: JSON.stringify({
|
|
289
330
|
scope,
|
|
290
331
|
projectId: ctx.projectId,
|
|
291
332
|
directory: ctx.directory,
|
|
292
333
|
sourceHarness: harness,
|
|
293
|
-
sourcePath
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
expectedRevision: current?.revision ?? null,
|
|
334
|
+
sourcePath,
|
|
335
|
+
content,
|
|
336
|
+
expectedRevision: endpointMode === 'revise' ? current?.revision ?? null : null,
|
|
297
337
|
followers: ctx.targets.map((target) => ({
|
|
298
338
|
harness: target.harness,
|
|
299
339
|
path: target.manifestPath,
|
|
@@ -301,17 +341,87 @@ async function writeCommand(args, adopt) {
|
|
|
301
341
|
})),
|
|
302
342
|
}),
|
|
303
343
|
});
|
|
304
|
-
|
|
305
|
-
|
|
344
|
+
const verb = mode === 'pull' ? 'Pulled' : mode === 'adopt' ? 'Adopted' : 'Revised';
|
|
345
|
+
console.log(`${verb} ${body.document.scopeKey} revision ${body.document.revision}.`);
|
|
346
|
+
const shouldPush = mode === 'pull'
|
|
347
|
+
? args.includes('--push')
|
|
348
|
+
: !args.includes('--no-sync');
|
|
349
|
+
if (shouldPush) {
|
|
306
350
|
await syncOne({
|
|
307
351
|
scope,
|
|
308
352
|
args,
|
|
309
353
|
check: false,
|
|
310
354
|
force: args.includes('--force'),
|
|
311
|
-
adoptSourcePath: adopt ? sourcePath : undefined,
|
|
312
355
|
});
|
|
313
356
|
}
|
|
314
357
|
}
|
|
358
|
+
async function overlayCommand(args) {
|
|
359
|
+
const action = args[0];
|
|
360
|
+
const harnessRaw = args[1];
|
|
361
|
+
if (action !== 'set' && action !== 'clear' && action !== 'derive') {
|
|
362
|
+
throw new Error('overlay requires set, derive, or clear');
|
|
363
|
+
}
|
|
364
|
+
const harness = inferHarness(undefined, harnessRaw);
|
|
365
|
+
if (harnessRaw !== harness)
|
|
366
|
+
throw new Error('overlay harness must be claude-code, codex, or opencode');
|
|
367
|
+
const file = action === 'set' ? args[2] : undefined;
|
|
368
|
+
if (action === 'set' && !file)
|
|
369
|
+
throw new Error('overlay set requires a source file');
|
|
370
|
+
const sharedFile = action === 'derive' ? args[2] : undefined;
|
|
371
|
+
const renderedFile = action === 'derive' ? args[3] : undefined;
|
|
372
|
+
if (action === 'derive' && (!sharedFile || !renderedFile)) {
|
|
373
|
+
throw new Error('overlay derive requires <shared-file> <rendered-file>');
|
|
374
|
+
}
|
|
375
|
+
const sourcePath = file ? path.resolve(file) : null;
|
|
376
|
+
if (sourcePath && !fs.existsSync(sourcePath))
|
|
377
|
+
throw new Error(`source file not found: ${sourcePath}`);
|
|
378
|
+
const sharedPath = sharedFile ? path.resolve(sharedFile) : null;
|
|
379
|
+
const renderedPath = renderedFile ? path.resolve(renderedFile) : null;
|
|
380
|
+
if (sharedPath && !fs.existsSync(sharedPath))
|
|
381
|
+
throw new Error(`shared file not found: ${sharedPath}`);
|
|
382
|
+
if (renderedPath && !fs.existsSync(renderedPath))
|
|
383
|
+
throw new Error(`rendered file not found: ${renderedPath}`);
|
|
384
|
+
const scope = inferScope(undefined, flag(args, '--scope'));
|
|
385
|
+
const ctx = context(scope, args);
|
|
386
|
+
const current = await fetchDocument(scope, ctx.projectId, ctx.directory);
|
|
387
|
+
if (!current)
|
|
388
|
+
throw new Error('canonical doctrine does not exist; adopt it first');
|
|
389
|
+
let content = '';
|
|
390
|
+
if (sourcePath) {
|
|
391
|
+
content = fs.readFileSync(sourcePath, 'utf8');
|
|
392
|
+
}
|
|
393
|
+
else if (sharedPath && renderedPath) {
|
|
394
|
+
const shared = fs.readFileSync(sharedPath, 'utf8');
|
|
395
|
+
const rendered = fs.readFileSync(renderedPath, 'utf8');
|
|
396
|
+
if (!rendered.startsWith(shared)) {
|
|
397
|
+
throw new Error('rendered file does not start with shared file bytes; cannot derive exact suffix');
|
|
398
|
+
}
|
|
399
|
+
content = rendered.slice(shared.length);
|
|
400
|
+
}
|
|
401
|
+
const body = await apiJson('/v1/agents/overlay', {
|
|
402
|
+
method: 'POST',
|
|
403
|
+
body: JSON.stringify({
|
|
404
|
+
scope,
|
|
405
|
+
projectId: ctx.projectId,
|
|
406
|
+
directory: ctx.directory,
|
|
407
|
+
sourceHarness: harness,
|
|
408
|
+
sourcePath: renderedPath || sourcePath,
|
|
409
|
+
content,
|
|
410
|
+
overlayHarness: harness,
|
|
411
|
+
expectedRevision: current.revision,
|
|
412
|
+
followers: ctx.targets.map((target) => ({
|
|
413
|
+
harness: target.harness,
|
|
414
|
+
path: target.manifestPath,
|
|
415
|
+
note: target.note,
|
|
416
|
+
})),
|
|
417
|
+
}),
|
|
418
|
+
});
|
|
419
|
+
const verb = action === 'set' ? 'Set' : action === 'derive' ? 'Derived' : 'Cleared';
|
|
420
|
+
console.log(`${verb} ${harness} overlay at revision ${body.document.revision}.`);
|
|
421
|
+
if (!args.includes('--no-sync')) {
|
|
422
|
+
await syncOne({ scope, args, check: false, force: args.includes('--force') });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
315
425
|
async function syncCommand(args, checkOverride = false) {
|
|
316
426
|
const requested = flag(args, '--scope') || 'all';
|
|
317
427
|
if (!['global', 'repo', 'all'].includes(requested)) {
|
|
@@ -334,8 +444,8 @@ async function syncCommand(args, checkOverride = false) {
|
|
|
334
444
|
}
|
|
335
445
|
}
|
|
336
446
|
/** Init-time seed for the active harness. No canon is a clean no-op; only a
|
|
337
|
-
* missing/empty follower is written. Every existing file
|
|
338
|
-
*
|
|
447
|
+
* missing/empty follower is written. Every existing nonmatching file requires
|
|
448
|
+
* an explicit `agents push` or `agents pull`. */
|
|
339
449
|
async function bootstrapAgentDoctrine(apiKey, harness) {
|
|
340
450
|
const result = {
|
|
341
451
|
canonicalScopes: [], currentFollowers: 0, changedFollowers: 0, blockedFollowers: 0,
|
|
@@ -358,10 +468,19 @@ async function runAgents(args) {
|
|
|
358
468
|
console.log(HELP);
|
|
359
469
|
return;
|
|
360
470
|
}
|
|
471
|
+
if (sub === 'pull')
|
|
472
|
+
return exactSourceCommand(args.slice(1), 'pull');
|
|
473
|
+
if (sub === 'push')
|
|
474
|
+
return syncCommand(args.slice(1));
|
|
361
475
|
if (sub === 'adopt')
|
|
362
|
-
return
|
|
363
|
-
if (sub === '
|
|
364
|
-
return
|
|
476
|
+
return exactSourceCommand(args.slice(1), 'adopt');
|
|
477
|
+
if (sub === 'revise')
|
|
478
|
+
return exactSourceCommand(args.slice(1), 'revise');
|
|
479
|
+
if (sub === 'overlay')
|
|
480
|
+
return overlayCommand(args.slice(1));
|
|
481
|
+
if (sub === 'optimize') {
|
|
482
|
+
throw new Error('agents optimize was removed: use lossless agents pull or explicit agents overlay');
|
|
483
|
+
}
|
|
365
484
|
if (sub === 'sync')
|
|
366
485
|
return syncCommand(args.slice(1));
|
|
367
486
|
if (sub === 'status')
|