mister-wolf 2.18.4 → 2.19.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 +1 -1
- package/README.ru.md +16 -14
- package/dist/adapters/cli/cli-entry.d.ts.map +1 -1
- package/dist/adapters/cli/cli-entry.js +10 -1
- package/dist/adapters/cli/cli-entry.js.map +1 -1
- package/dist/adapters/cli/commands/claim.d.ts.map +1 -1
- package/dist/adapters/cli/commands/claim.js +2 -1
- package/dist/adapters/cli/commands/claim.js.map +1 -1
- package/dist/adapters/cli/commands/memory-sync.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-sync.js +3 -0
- package/dist/adapters/cli/commands/memory-sync.js.map +1 -1
- package/dist/adapters/cli/commands/memory-upgrade.d.ts +133 -0
- package/dist/adapters/cli/commands/memory-upgrade.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-upgrade.js +507 -5
- package/dist/adapters/cli/commands/memory-upgrade.js.map +1 -1
- package/dist/adapters/cli/commands/upgrade-projects.d.ts +17 -0
- package/dist/adapters/cli/commands/upgrade-projects.d.ts.map +1 -0
- package/dist/adapters/cli/commands/upgrade-projects.js +75 -0
- package/dist/adapters/cli/commands/upgrade-projects.js.map +1 -0
- package/dist/adapters/cli/report-renderer.d.ts +43 -0
- package/dist/adapters/cli/report-renderer.d.ts.map +1 -0
- package/dist/adapters/cli/report-renderer.js +184 -0
- package/dist/adapters/cli/report-renderer.js.map +1 -0
- package/dist/adapters/fs/claim-registry.d.ts.map +1 -1
- package/dist/adapters/fs/claim-registry.js +15 -2
- package/dist/adapters/fs/claim-registry.js.map +1 -1
- package/dist/adapters/fs/projects-registry.d.ts +21 -0
- package/dist/adapters/fs/projects-registry.d.ts.map +1 -1
- package/dist/adapters/fs/projects-registry.js +54 -1
- package/dist/adapters/fs/projects-registry.js.map +1 -1
- package/dist/adapters/fs/update-map.d.ts +102 -0
- package/dist/adapters/fs/update-map.d.ts.map +1 -0
- package/dist/adapters/fs/update-map.js +95 -0
- package/dist/adapters/fs/update-map.js.map +1 -0
- package/dist/adapters/fs/upgrade-lock.d.ts +23 -0
- package/dist/adapters/fs/upgrade-lock.d.ts.map +1 -0
- package/dist/adapters/fs/upgrade-lock.js +59 -0
- package/dist/adapters/fs/upgrade-lock.js.map +1 -0
- package/dist/adapters/render/opencode/opencode-renderer.d.ts +13 -1
- package/dist/adapters/render/opencode/opencode-renderer.d.ts.map +1 -1
- package/dist/adapters/render/opencode/opencode-renderer.js +76 -8
- package/dist/adapters/render/opencode/opencode-renderer.js.map +1 -1
- package/dist/app/use-cases/claim-artifact.d.ts +4 -1
- package/dist/app/use-cases/claim-artifact.d.ts.map +1 -1
- package/dist/app/use-cases/claim-artifact.js +9 -2
- package/dist/app/use-cases/claim-artifact.js.map +1 -1
- package/dist/app/use-cases/project-step.d.ts +52 -0
- package/dist/app/use-cases/project-step.d.ts.map +1 -0
- package/dist/app/use-cases/project-step.js +77 -0
- package/dist/app/use-cases/project-step.js.map +1 -0
- package/dist/app/use-cases/scan-unregistered.d.ts +25 -0
- package/dist/app/use-cases/scan-unregistered.d.ts.map +1 -0
- package/dist/app/use-cases/scan-unregistered.js +74 -0
- package/dist/app/use-cases/scan-unregistered.js.map +1 -0
- package/dist/app/use-cases/seed-base-playbooks.d.ts +10 -0
- package/dist/app/use-cases/seed-base-playbooks.d.ts.map +1 -1
- package/dist/app/use-cases/seed-base-playbooks.js +54 -13
- package/dist/app/use-cases/seed-base-playbooks.js.map +1 -1
- package/dist/app/use-cases/upgrade-projects.d.ts +61 -0
- package/dist/app/use-cases/upgrade-projects.d.ts.map +1 -0
- package/dist/app/use-cases/upgrade-projects.js +379 -0
- package/dist/app/use-cases/upgrade-projects.js.map +1 -0
- package/dist/app/use-cases/verify-against-map.d.ts +48 -0
- package/dist/app/use-cases/verify-against-map.d.ts.map +1 -0
- package/dist/app/use-cases/verify-against-map.js +161 -0
- package/dist/app/use-cases/verify-against-map.js.map +1 -0
- package/dist/ports/base-set-renderer.port.d.ts +13 -0
- package/dist/ports/base-set-renderer.port.d.ts.map +1 -1
- package/package.json +3 -2
- package/templates/.wolf/router.log +1 -1
- package/templates/opencode/plugins/wolf-router.ts +158 -48
- package/update-map.json +204 -0
|
@@ -3,12 +3,25 @@ export interface RenderOutcome {
|
|
|
3
3
|
file: string;
|
|
4
4
|
action: RenderAction;
|
|
5
5
|
reason?: string;
|
|
6
|
+
/** 2.19.0 (design §«Сверка»): структурный флаг mutated-skip — сверка
|
|
7
|
+
* verifyAgainstMap различает skipped-identical / skipped-mutated полем,
|
|
8
|
+
* не парсингом reason-строки. */
|
|
9
|
+
mutated?: boolean;
|
|
6
10
|
}
|
|
7
11
|
/** Контекст подстановки моделей (onboarding v2, §4.5): {{model.primary}} / {{model.worker}}. */
|
|
8
12
|
export interface ModelContext {
|
|
9
13
|
primary: string;
|
|
10
14
|
worker: string;
|
|
11
15
|
}
|
|
16
|
+
/** Действие read-only инспекции цели (T10, REQ-08, design §«--check»): цель
|
|
17
|
+
* сверяется с текущим рендером без единой записи на диск. foreign — unstamped
|
|
18
|
+
* файл на месте цели (wx-политика: чужое, вне покрытия). */
|
|
19
|
+
export type InspectAction = 'identical' | 'differs' | 'missing' | 'mutated' | 'foreign' | 'unknown';
|
|
20
|
+
export interface InspectOutcome {
|
|
21
|
+
/** rel-путь от baseDir — тот же ключ, что RenderOutcome.file. */
|
|
22
|
+
file: string;
|
|
23
|
+
action: InspectAction;
|
|
24
|
+
}
|
|
12
25
|
export interface BakeResolver {
|
|
13
26
|
/** Вернуть тело playbook'а для вживления (bake-in) или null. Источник — память целевого проекта (§4). */
|
|
14
27
|
(baseName: string): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-set-renderer.port.d.ts","sourceRoot":"","sources":["../../src/ports/base-set-renderer.port.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"base-set-renderer.port.d.ts","sourceRoot":"","sources":["../../src/ports/base-set-renderer.port.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;sCAEkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;6DAE6D;AAC7D,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpG,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,yGAAyG;IACzG,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,0GAA0G;IAC1G,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC/B;+CAC2C;IAC3C,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,uGAAuG;IACvG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACtF;;;;OAIG;IACH,WAAW,CACT,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,GAC7B,OAAO,CAAC;QAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC/D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mister-wolf",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
4
4
|
"description": "Local-first project memory for AI coding agents: decisions, lessons, tools and processes that outlive the session",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
|
-
"templates"
|
|
27
|
+
"templates",
|
|
28
|
+
"update-map.json"
|
|
28
29
|
],
|
|
29
30
|
"scripts": {
|
|
30
31
|
"build": "tsc",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-10-
|
|
1
|
+
2026-10-24T17:36:23.551Z agent-id=v2-router-probe-xyz playbook=hit name=fallback variant=fallback source=default resolution=error face_id=- version=- hash=- session=opc-277ab5c4-acf5-40ed-bfb9-6037555e3f73 injected=yes ms=1 bytes=1274
|
|
@@ -6,21 +6,23 @@
|
|
|
6
6
|
* `agent-id: <id>` В ТЕЛЕ рамки агента (frontmatter в system-промпт не
|
|
7
7
|
* попадает — известная грабля) → 2.18.4: канонический face-resolver
|
|
8
8
|
* (`wolf face resolve`: type=face, status=active, owner_skill === agentId;
|
|
9
|
-
* ровно одно активное лицо, иначе отказ) →
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* ровно одно активное лицо, иначе отказ) → 2.18.5 (AC1) поведение разделено:
|
|
10
|
+
* unique → доставка лица; none → legacy-поиск note/howto/playbook с гвардами
|
|
11
|
+
* владельца, типа (лица — только резолвер) и статуса (active); multiple →
|
|
12
|
+
* конфликт зафиксирован, методика НЕ выбирается и НЕ внедряется; resolver
|
|
13
|
+
* error → диагностируемый сбой — оба случая без запасного поиска (ревью
|
|
14
|
+
* 2.18.4: текстовый fallback обходил конфликт через proposed-лицо).
|
|
14
15
|
* Вариант Б (CR-2026-10-13-02): инъекция мемоизируется по opencode-сессии
|
|
15
16
|
* (пересборка system в пределах сессии получает запечатанный текст той же
|
|
16
17
|
* версии — без переключения посередине задания), кэш версионируется ключом
|
|
17
18
|
* head-записи — новая сессия всегда получает актуальную версию.
|
|
18
19
|
*
|
|
19
|
-
* Fallback (T012, волна 1.1):
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* сами playbook-объекты через owner_skill, отдельного
|
|
20
|
+
* Fallback (T012, волна 1.1): методика недоступна (miss/conflict/error) →
|
|
21
|
+
* инъекция встроенного универсального FALLBACK_PLAYBOOK для любого agent-id.
|
|
22
|
+
* В router.log (2.18.5, AC3): source=face|legacy|default,
|
|
23
|
+
* resolution=unique|none|conflict|error, face_id/version/hash, session.
|
|
24
|
+
* Реестр доставок = сами playbook-объекты через owner_skill, отдельного
|
|
25
|
+
* конфига нет.
|
|
24
26
|
*
|
|
25
27
|
* Ноль зависимостей (Node stdlib; ai-sdk НЕ используется). Fail-safe: всё в
|
|
26
28
|
* try/catch — плагин не имеет права уронить сессию (лог: .wolf/router.log —
|
|
@@ -32,7 +34,6 @@ import path from 'path';
|
|
|
32
34
|
import fs from 'fs';
|
|
33
35
|
import { execFile } from 'child_process';
|
|
34
36
|
import { randomUUID } from 'crypto';
|
|
35
|
-
import { promisify } from 'util';
|
|
36
37
|
import { fileURLToPath } from 'url';
|
|
37
38
|
|
|
38
39
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -71,17 +72,29 @@ const CACHE_TTL_MS = 300_000;
|
|
|
71
72
|
// agent-id последней рамки, пропущенной через system.transform (для skill-метрики B3)
|
|
72
73
|
let lastAgentId: string | null = null;
|
|
73
74
|
|
|
74
|
-
const run = promisify(execFile);
|
|
75
75
|
// execFile: args array, no shell. Целевой проект — глобальный `wolf`;
|
|
76
76
|
// догфуд в репо Wolf — локальный dist. Ошибка обоих → исключение наверх (fail-safe).
|
|
77
77
|
// WOLF_SESSION (4.C): ключ ставится фабрикой ОДИН раз на процесс opencode —
|
|
78
78
|
// спавны и bash-вызовы волка наследуют его из process.env (execFile без
|
|
79
79
|
// env-поля наследует сам). Известный потолок: несколько чатов одного процесса
|
|
80
80
|
// opencode шарят ключ — консервативная недо-дедупликация, не ошибка.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
81
|
+
// 2.18.5: runWolf резолвит stdout и при ненулевом exit — контракт CLI печатает
|
|
82
|
+
// разборчивый JSON ({ok:false,error:{kind}}) на stdout с exit 1; promisify
|
|
83
|
+
// терял его (reject без stdout), превращая реальный miss в необъяснимый error.
|
|
84
|
+
const runWolf = (args: string[]): Promise<{ stdout: string }> =>
|
|
85
|
+
new Promise((resolve, reject) => {
|
|
86
|
+
const attempt = (file: string, a: string[]): void => {
|
|
87
|
+
execFile(file, a, { cwd: PROJECT_ROOT, timeout: 5000 }, (err, stdout) => {
|
|
88
|
+
const out = typeof stdout === 'string' ? stdout : '';
|
|
89
|
+
// resolve при exit 0 (пустой stdout — валидный miss search) и при
|
|
90
|
+
// exit≠0 с разборчивым выводом (контракт CLI miss/conflict с exit 1)
|
|
91
|
+
if (!err || out) return resolve({ stdout: out });
|
|
92
|
+
if (file === 'wolf') return attempt('node', [LOCAL_CLI, ...args]);
|
|
93
|
+
reject(err ?? new Error('wolf CLI produced no output'));
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
attempt('wolf', args);
|
|
97
|
+
});
|
|
85
98
|
|
|
86
99
|
function logRoute(line: string): void {
|
|
87
100
|
try {
|
|
@@ -97,44 +110,96 @@ function logRoute(line: string): void {
|
|
|
97
110
|
// версионируется ключом head — кэш экономит только get-спавн и отдаётся лишь
|
|
98
111
|
// при совпадении id с актуальной записью живого search; устаревшая версия
|
|
99
112
|
// лица не отдаётся никогда (новая сессия в пределах TTL получает head).
|
|
100
|
-
const cache = new Map<string, { value:
|
|
113
|
+
const cache = new Map<string, { value: RouteResult; at: number }>();
|
|
101
114
|
|
|
102
115
|
// Вариант Б (а): мемоизация инъекции по opencode-сессии. Ключ сессии —
|
|
103
116
|
// WOLF_SESSION (ставится на процесс opencode; несколько чатов одного
|
|
104
117
|
// процесса — задокументированный потолок, см. ensureSession). Сессия
|
|
105
118
|
// пригвождена к версии первого задания: пересборка system не запускает
|
|
106
119
|
// ре-резолв — переключение версии посередине задания исключено (REQ-05).
|
|
107
|
-
|
|
120
|
+
interface InjectedPlaybook {
|
|
121
|
+
text: string;
|
|
122
|
+
name: string;
|
|
123
|
+
variant: string;
|
|
124
|
+
bytes: number;
|
|
125
|
+
source: string;
|
|
126
|
+
resolution: string;
|
|
127
|
+
face_id: string;
|
|
128
|
+
version: string;
|
|
129
|
+
hash: string;
|
|
130
|
+
}
|
|
131
|
+
const sessionInject = new Map<string, InjectedPlaybook>();
|
|
132
|
+
|
|
133
|
+
/** Исход доставки (2.18.5, AC1/AC3): unique — каноническое лицо; none — лица
|
|
134
|
+
* нет, legacy-поиск разрешён; conflict/error — методика НЕ выбирается и НЕ
|
|
135
|
+
* внедряется (только универсальный fallback + диагностика в router.log). */
|
|
136
|
+
type RouteResolution = 'unique' | 'none' | 'conflict' | 'error';
|
|
137
|
+
|
|
138
|
+
interface RouteResult {
|
|
139
|
+
id: string | null;
|
|
140
|
+
body: string | null;
|
|
141
|
+
source: 'face' | 'legacy' | 'default';
|
|
142
|
+
resolution: RouteResolution;
|
|
143
|
+
version: string | null;
|
|
144
|
+
hash: string | null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const routeFailure = (resolution: 'conflict' | 'error'): RouteResult => ({
|
|
148
|
+
id: null,
|
|
149
|
+
body: null,
|
|
150
|
+
source: 'default',
|
|
151
|
+
resolution,
|
|
152
|
+
version: null,
|
|
153
|
+
hash: null,
|
|
154
|
+
});
|
|
108
155
|
|
|
109
156
|
// 2.18.4: канонический резолвер лица — строгий запрос type=face/status=active/
|
|
110
157
|
// owner_skill (`wolf face resolve`) вместо вероятностного текстового поиска.
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
158
|
+
// 2.18.5 (AC1): результат различается — unique доставляется; none → legacy-путь
|
|
159
|
+
// ниже; conflict/error → НЕ fallback к текстовому поиску (ревью 2.18.4:
|
|
160
|
+
// запасной поиск обходил конфликт, выбирая proposed-лицо по owner_skill).
|
|
161
|
+
async function resolveFaceCanonical(agentId: string): Promise<RouteResult | null> {
|
|
162
|
+
let stdout: string;
|
|
163
|
+
try {
|
|
164
|
+
({ stdout } = await runWolf(['face', 'resolve', agentId]));
|
|
165
|
+
} catch {
|
|
166
|
+
return routeFailure('error'); // обе формы CLI упали без вывода — диагностируемый сбой
|
|
167
|
+
}
|
|
114
168
|
try {
|
|
115
|
-
const
|
|
116
|
-
|
|
169
|
+
const parsed = JSON.parse(stdout) as {
|
|
170
|
+
ok?: boolean;
|
|
171
|
+
face?: { id?: unknown; body?: unknown; version?: unknown; hash?: unknown };
|
|
172
|
+
error?: { kind?: unknown };
|
|
173
|
+
};
|
|
117
174
|
if (parsed?.ok && typeof parsed.face?.body === 'string' && parsed.face.body.length > 0) {
|
|
118
|
-
return {
|
|
175
|
+
return {
|
|
176
|
+
id: String(parsed.face.id ?? ''),
|
|
177
|
+
body: parsed.face.body,
|
|
178
|
+
source: 'face',
|
|
179
|
+
resolution: 'unique',
|
|
180
|
+
version: typeof parsed.face.version === 'string' ? parsed.face.version : null,
|
|
181
|
+
hash: typeof parsed.face.hash === 'string' ? parsed.face.hash : null,
|
|
182
|
+
};
|
|
119
183
|
}
|
|
184
|
+
if (parsed?.error?.kind === 'multiple') return routeFailure('conflict');
|
|
185
|
+
if (parsed?.error?.kind === 'none') return null; // miss → legacy-путь
|
|
186
|
+
return routeFailure('error'); // ok:false без kind / неразборчивый ответ
|
|
120
187
|
} catch {
|
|
121
|
-
|
|
188
|
+
return routeFailure('error');
|
|
122
189
|
}
|
|
123
|
-
return null;
|
|
124
190
|
}
|
|
125
191
|
|
|
126
|
-
async function resolvePlaybook(agentId: string): Promise<
|
|
192
|
+
async function resolvePlaybook(agentId: string): Promise<RouteResult> {
|
|
127
193
|
const face = await resolveFaceCanonical(agentId);
|
|
128
194
|
if (face) {
|
|
129
|
-
cache.set(agentId, { value: face, at: Date.now() });
|
|
130
|
-
return face;
|
|
195
|
+
if (face.resolution === 'unique') cache.set(agentId, { value: face, at: Date.now() });
|
|
196
|
+
return face; // unique | conflict | error — стоп, запасной поиск не гасит исход
|
|
131
197
|
}
|
|
132
|
-
let found:
|
|
198
|
+
let found: RouteResult | null = null;
|
|
133
199
|
try {
|
|
134
200
|
// 2.13: плейбуки живут как note+facet howto (type 'playbook' — legacy),
|
|
135
201
|
// поэтому без --type; слово «playbook» (title/tags канона) сужает выборку.
|
|
136
|
-
// Формат строки search: `<id> [<type>] [<facet>] <title
|
|
137
|
-
// фильтруем — каноничность решает гвард owner_skill ниже.
|
|
202
|
+
// Формат строки search: `<id> [<type>] [<facet>] <title>`.
|
|
138
203
|
const { stdout } = await runWolf(['search', agentId, 'playbook', '--hide-superseded']);
|
|
139
204
|
const ids = [...stdout.matchAll(/^([\w-]+) \[\w+\]/gm)].map((m) => m[1]);
|
|
140
205
|
// Вариант Б (б): search живой на каждой новой сессии (мемоизация в
|
|
@@ -147,20 +212,46 @@ async function resolvePlaybook(agentId: string): Promise<{ id: string; body: str
|
|
|
147
212
|
}
|
|
148
213
|
// Ранний стоп (спека A2-б): релевантность поиска уже отсортировала,
|
|
149
214
|
// --hide-superseded отсекает старые версии — первый кандидат, прошедший
|
|
150
|
-
//
|
|
215
|
+
// гварды, и есть результат (один get при miss вместо K подряд).
|
|
216
|
+
// 2.18.5 (AC1): гварды — owner_skill И тип (note|howto|playbook; лица
|
|
217
|
+
// только через канонический резолвер) И статус (active или не задан;
|
|
218
|
+
// proposed/superseded не доставляются).
|
|
151
219
|
for (const id of ids) {
|
|
152
220
|
const { stdout: json } = await runWolf(['get', id]);
|
|
153
|
-
const obj = JSON.parse(json)
|
|
221
|
+
const obj = JSON.parse(json) as {
|
|
222
|
+
id?: unknown;
|
|
223
|
+
body?: unknown;
|
|
224
|
+
owner_skill?: unknown;
|
|
225
|
+
extra?: { owner_skill?: unknown };
|
|
226
|
+
type?: unknown;
|
|
227
|
+
status?: unknown;
|
|
228
|
+
version?: unknown;
|
|
229
|
+
hash?: unknown;
|
|
230
|
+
};
|
|
154
231
|
const owner = obj.owner_skill ?? obj.extra?.owner_skill;
|
|
155
232
|
if (owner !== agentId && owner !== `skill:${agentId}`) continue; // гвард владельца
|
|
156
|
-
if (obj.
|
|
233
|
+
if (obj.type !== 'note' && obj.type !== 'howto' && obj.type !== 'playbook') continue; // лица — только резолвер
|
|
234
|
+
if (obj.status !== undefined && obj.status !== 'active') continue; // гвард статуса
|
|
235
|
+
if (obj.body) {
|
|
236
|
+
found = {
|
|
237
|
+
id: String(obj.id ?? id),
|
|
238
|
+
body: obj.body,
|
|
239
|
+
source: 'legacy',
|
|
240
|
+
resolution: 'none',
|
|
241
|
+
version: typeof obj.version === 'string' ? obj.version : null,
|
|
242
|
+
hash: typeof obj.hash === 'string' ? obj.hash : null,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
157
245
|
break;
|
|
158
246
|
}
|
|
159
247
|
} catch {
|
|
160
|
-
|
|
248
|
+
// 2.18.5: сбой legacy-поиска — диагностируемый error, не молчаливый miss
|
|
249
|
+
cache.set(agentId, { value: routeFailure('error'), at: Date.now() });
|
|
250
|
+
return routeFailure('error');
|
|
161
251
|
}
|
|
162
|
-
|
|
163
|
-
|
|
252
|
+
const result = found ?? { ...routeFailure('none'), source: 'default' as const };
|
|
253
|
+
cache.set(agentId, { value: result, at: Date.now() });
|
|
254
|
+
return result;
|
|
164
255
|
}
|
|
165
256
|
|
|
166
257
|
// B3: метрика вызовов скиллов. Форма входа v1: input.tool — имя тула,
|
|
@@ -187,7 +278,9 @@ function recordSkillMetric(tool: unknown, args: unknown): void {
|
|
|
187
278
|
// Общая доставка playbook (v1 system.transform / v2 context): joined system-текст
|
|
188
279
|
// → маркер agent-id → гвард идемпотентности INJECT_HEADER → мемоизация сессии
|
|
189
280
|
// (вариант Б: запечатанный текст без ре-резолва) → resolvePlaybook → push(текст).
|
|
190
|
-
// Fail-safe: не роняем сессию ни на одном шаге.
|
|
281
|
+
// Fail-safe: не роняем сессию ни на одном шаге. 2.18.5 (AC3): каждая строка
|
|
282
|
+
// журнала несёт source/resolution/face_id/version/hash/session — видно, как
|
|
283
|
+
// именно доставлена методика (canonical-метка legacy-результатом не ставится).
|
|
191
284
|
async function deliverPlaybook(joined: string, push: (text: string) => void): Promise<void> {
|
|
192
285
|
try {
|
|
193
286
|
const m = joined.match(AGENT_ID_RE);
|
|
@@ -195,6 +288,7 @@ async function deliverPlaybook(joined: string, push: (text: string) => void): Pr
|
|
|
195
288
|
if (joined.includes(INJECT_HEADER)) return; // идемпотентность: не вставляем дважды
|
|
196
289
|
const agentId = m[1];
|
|
197
290
|
lastAgentId = agentId; // агент известен хуку skill-метрики (B3)
|
|
291
|
+
const sessionId = process.env.WOLF_SESSION ?? '-';
|
|
198
292
|
// Вариант Б (а): сессия уже получила инъекцию → отдаём запечатанный текст
|
|
199
293
|
// (то же содержание, тот же вариант), без CLI-спавнов и ре-резолва —
|
|
200
294
|
// независимо от того, персистит ли рантайм system-текст между сообщениями.
|
|
@@ -203,7 +297,9 @@ async function deliverPlaybook(joined: string, push: (text: string) => void): Pr
|
|
|
203
297
|
if (memoized) {
|
|
204
298
|
push(memoized.text);
|
|
205
299
|
logRoute(
|
|
206
|
-
`agent-id=${agentId} playbook=hit name=${memoized.name} variant=${memoized.variant}
|
|
300
|
+
`agent-id=${agentId} playbook=hit name=${memoized.name} variant=${memoized.variant}` +
|
|
301
|
+
` source=${memoized.source} resolution=${memoized.resolution} face_id=${memoized.face_id}` +
|
|
302
|
+
` version=${memoized.version} hash=${memoized.hash} session=${sessionId} injected=yes` +
|
|
207
303
|
` ms=0 bytes=${memoized.bytes}`
|
|
208
304
|
);
|
|
209
305
|
return;
|
|
@@ -211,32 +307,46 @@ async function deliverPlaybook(joined: string, push: (text: string) => void): Pr
|
|
|
211
307
|
const startedAt = Date.now();
|
|
212
308
|
const resolved = await resolvePlaybook(agentId);
|
|
213
309
|
const ms = Date.now() - startedAt;
|
|
214
|
-
|
|
310
|
+
const fields =
|
|
311
|
+
` source=${resolved.source} resolution=${resolved.resolution} face_id=${resolved.source === 'face' ? (resolved.id ?? '-') : '-'}` +
|
|
312
|
+
` version=${resolved.version ?? '-'} hash=${resolved.hash ?? '-'}`;
|
|
313
|
+
if (resolved.body) {
|
|
215
314
|
const text = `\n\n${INJECT_HEADER}\n\n${resolved.body}`;
|
|
216
315
|
sessionInject.set(memoKey, {
|
|
217
316
|
text,
|
|
218
|
-
name: resolved.id,
|
|
219
|
-
variant: 'canonical',
|
|
317
|
+
name: resolved.id ?? '',
|
|
318
|
+
variant: resolved.source === 'face' ? 'canonical' : 'legacy',
|
|
220
319
|
bytes: Buffer.byteLength(resolved.body),
|
|
320
|
+
source: resolved.source,
|
|
321
|
+
resolution: resolved.resolution,
|
|
322
|
+
face_id: resolved.source === 'face' ? (resolved.id ?? '-') : '-',
|
|
323
|
+
version: resolved.version ?? '-',
|
|
324
|
+
hash: resolved.hash ?? '-',
|
|
221
325
|
});
|
|
222
326
|
push(text);
|
|
223
327
|
logRoute(
|
|
224
|
-
`agent-id=${agentId} playbook=hit name=${resolved.id} variant
|
|
225
|
-
|
|
328
|
+
`agent-id=${agentId} playbook=hit name=${resolved.id} variant=${resolved.source === 'face' ? 'canonical' : 'legacy'}` +
|
|
329
|
+
`${fields} session=${sessionId} injected=yes ms=${ms} bytes=${Buffer.byteLength(resolved.body)}`
|
|
226
330
|
);
|
|
227
331
|
} else {
|
|
228
|
-
// T012: miss
|
|
332
|
+
// T012: методика недоступна (miss/conflict/error) → универсальный fallback;
|
|
333
|
+
// инъекция для любого agent-id; конфликт/сбой зафиксированы в resolution.
|
|
229
334
|
const text = `\n\n${INJECT_HEADER}\n\n${FALLBACK_PLAYBOOK}`;
|
|
230
335
|
sessionInject.set(memoKey, {
|
|
231
336
|
text,
|
|
232
337
|
name: 'fallback',
|
|
233
338
|
variant: 'fallback',
|
|
234
339
|
bytes: Buffer.byteLength(FALLBACK_PLAYBOOK),
|
|
340
|
+
source: 'default',
|
|
341
|
+
resolution: resolved.resolution,
|
|
342
|
+
face_id: '-',
|
|
343
|
+
version: '-',
|
|
344
|
+
hash: '-',
|
|
235
345
|
});
|
|
236
346
|
push(text);
|
|
237
347
|
logRoute(
|
|
238
|
-
`agent-id=${agentId} playbook=hit name=fallback variant=fallback
|
|
239
|
-
|
|
348
|
+
`agent-id=${agentId} playbook=hit name=fallback variant=fallback` +
|
|
349
|
+
`${fields} session=${sessionId} injected=yes ms=${ms} bytes=${Buffer.byteLength(FALLBACK_PLAYBOOK)}`
|
|
240
350
|
);
|
|
241
351
|
}
|
|
242
352
|
} catch {
|
package/update-map.json
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.19.0",
|
|
3
|
+
"prev": "2.18.5",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "base/agents/executor-lead.md",
|
|
7
|
+
"kind": "agent",
|
|
8
|
+
"category": "unchanged"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "base/agents/mr-wolf.md",
|
|
12
|
+
"kind": "agent",
|
|
13
|
+
"category": "unchanged"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"path": "base/agents/steward.md",
|
|
17
|
+
"kind": "agent",
|
|
18
|
+
"category": "unchanged"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "base/agents/worker-implementer.md",
|
|
22
|
+
"kind": "agent",
|
|
23
|
+
"category": "unchanged"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "base/agents/worker-researcher.md",
|
|
27
|
+
"kind": "agent",
|
|
28
|
+
"category": "unchanged"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "base/agents/worker-reviewer.md",
|
|
32
|
+
"kind": "agent",
|
|
33
|
+
"category": "unchanged"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "base/commands/analyze-doc.md",
|
|
37
|
+
"kind": "command",
|
|
38
|
+
"category": "unchanged"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"path": "base/commands/complain.md",
|
|
42
|
+
"kind": "command",
|
|
43
|
+
"category": "unchanged"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"path": "base/commands/doc-review.md",
|
|
47
|
+
"kind": "command",
|
|
48
|
+
"category": "unchanged"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "base/skills/finishing-a-development-branch/SKILL.md",
|
|
52
|
+
"kind": "skill",
|
|
53
|
+
"category": "unchanged"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"path": "base/skills/receiving-code-review/SKILL.md",
|
|
57
|
+
"kind": "skill",
|
|
58
|
+
"category": "unchanged"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"path": "base/skills/requesting-code-review/SKILL.md",
|
|
62
|
+
"kind": "skill",
|
|
63
|
+
"category": "unchanged"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "base/skills/test-driven-development/SKILL.md",
|
|
67
|
+
"kind": "skill",
|
|
68
|
+
"category": "unchanged"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"path": "base/skills/using-git-worktrees/SKILL.md",
|
|
72
|
+
"kind": "skill",
|
|
73
|
+
"category": "unchanged"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"path": "base/skills/using-skills/SKILL.md",
|
|
77
|
+
"kind": "skill",
|
|
78
|
+
"category": "unchanged"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"path": "base/skills/verification-before-completion/SKILL.md",
|
|
82
|
+
"kind": "skill",
|
|
83
|
+
"category": "unchanged"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"path": "base/skills/wolf-brainstorm/SKILL.md",
|
|
87
|
+
"kind": "skill",
|
|
88
|
+
"category": "unchanged"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"path": "base/skills/wolf-debug/SKILL.md",
|
|
92
|
+
"kind": "skill",
|
|
93
|
+
"category": "unchanged"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": "base/skills/wolf-design/SKILL.md",
|
|
97
|
+
"kind": "skill",
|
|
98
|
+
"category": "unchanged"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"path": "base/skills/wolf-execute/SKILL.md",
|
|
102
|
+
"kind": "skill",
|
|
103
|
+
"category": "unchanged"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"path": "base/skills/wolf-explain/SKILL.md",
|
|
107
|
+
"kind": "skill",
|
|
108
|
+
"category": "unchanged"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "base/skills/wolf-handoff/SKILL.md",
|
|
112
|
+
"kind": "skill",
|
|
113
|
+
"category": "unchanged"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"path": "base/skills/wolf-plan/SKILL.md",
|
|
117
|
+
"kind": "skill",
|
|
118
|
+
"category": "unchanged"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"path": "base/skills/wolf-review/SKILL.md",
|
|
122
|
+
"kind": "skill",
|
|
123
|
+
"category": "unchanged"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"path": "base/skills/wolf-sdd/SKILL.md",
|
|
127
|
+
"kind": "skill",
|
|
128
|
+
"category": "unchanged"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"path": "base/skills/wolf-skill-intake/SKILL.md",
|
|
132
|
+
"kind": "skill",
|
|
133
|
+
"category": "unchanged"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"path": "base/skills/wolf-testplan/SKILL.md",
|
|
137
|
+
"kind": "skill",
|
|
138
|
+
"category": "unchanged"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"path": "base/skills/writing-skills/SKILL.md",
|
|
142
|
+
"kind": "skill",
|
|
143
|
+
"category": "unchanged"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"path": "opencode/plugins/wolf-router.ts",
|
|
147
|
+
"kind": "plugin",
|
|
148
|
+
"category": "unchanged"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"path": "opencode/plugins/wolf-session-start.js",
|
|
152
|
+
"kind": "plugin",
|
|
153
|
+
"category": "unchanged"
|
|
154
|
+
}
|
|
155
|
+
],
|
|
156
|
+
"faces": [
|
|
157
|
+
{
|
|
158
|
+
"template": "base/playbooks/complaint-protocol.md",
|
|
159
|
+
"owner_skill": "mr-wolf",
|
|
160
|
+
"category": "unchanged",
|
|
161
|
+
"seed": true
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"template": "base/playbooks/executor-lead-playbook.md",
|
|
165
|
+
"owner_skill": "executor-lead",
|
|
166
|
+
"category": "unchanged",
|
|
167
|
+
"seed": true
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"template": "base/playbooks/steward-nastavnik.md",
|
|
171
|
+
"owner_skill": "steward",
|
|
172
|
+
"category": "unchanged",
|
|
173
|
+
"seed": true
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"template": "base/playbooks/worker-implementer-playbook.md",
|
|
177
|
+
"owner_skill": "worker-implementer",
|
|
178
|
+
"category": "unchanged",
|
|
179
|
+
"seed": true
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"template": "base/playbooks/worker-researcher-playbook.md",
|
|
183
|
+
"owner_skill": "worker-researcher",
|
|
184
|
+
"category": "unchanged",
|
|
185
|
+
"seed": true
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"template": "base/playbooks/worker-reviewer-playbook.md",
|
|
189
|
+
"owner_skill": "worker-reviewer",
|
|
190
|
+
"category": "unchanged",
|
|
191
|
+
"seed": true
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
"agents_md": {
|
|
195
|
+
"category": "unchanged",
|
|
196
|
+
"mode": "append-block"
|
|
197
|
+
},
|
|
198
|
+
"schema_migrations": [],
|
|
199
|
+
"outside_v1": [
|
|
200
|
+
"taxonomy (config.yaml memory_types — manual wolf taxonomy)",
|
|
201
|
+
"tool-skills (generated by wolf tool — not a base-set path)",
|
|
202
|
+
"local/foreign artifacts (untracked .opencode/* and .wolf/* files)"
|
|
203
|
+
]
|
|
204
|
+
}
|