wendkeep 0.58.3 → 0.60.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/CHANGELOG.md +93 -0
- package/README.en.md +45 -3
- package/README.md +45 -3
- package/bin/wendkeep.mjs +54 -6
- package/docs/en/commands/changes-and-verification.md +9 -3
- package/docs/en/commands/getting-started.md +7 -3
- package/docs/en/commands/memory.md +20 -2
- package/docs/en/commands/operating-profiles.md +173 -0
- package/docs/en/commands/sessions-and-import.md +8 -4
- package/docs/en/commands/verify.md +12 -6
- package/docs/pt-BR/commands/changes-and-verification.md +9 -4
- package/docs/pt-BR/commands/getting-started.md +7 -3
- package/docs/pt-BR/commands/memory.md +18 -2
- package/docs/pt-BR/commands/operating-profiles.md +171 -0
- package/docs/pt-BR/commands/sessions-and-import.md +7 -3
- package/docs/pt-BR/commands/verify.md +11 -5
- package/hooks/brain-core.mjs +159 -159
- package/hooks/brain-inject.mjs +83 -26
- package/hooks/brain-recall.mjs +32 -32
- package/hooks/brain-reindex.mjs +13 -13
- package/hooks/change-context.mjs +24 -10
- package/hooks/change-core.mjs +174 -37
- package/hooks/change-guard.mjs +115 -16
- package/hooks/change-nag.mjs +20 -5
- package/hooks/change-warn.mjs +27 -9
- package/hooks/decision-capture.mjs +1 -1
- package/hooks/derived-sections.mjs +1 -1
- package/hooks/flow-core.mjs +891 -0
- package/hooks/flow-protected-policy.mjs +218 -0
- package/hooks/frontmatter-repair.mjs +3 -1
- package/hooks/git-snapshot.mjs +722 -0
- package/hooks/import-sessions.mjs +10 -5
- package/hooks/memory-mode.mjs +63 -13
- package/hooks/memory-store.mjs +309 -69
- package/hooks/obsidian-common.mjs +39 -55
- package/hooks/operating-profile-runtime.mjs +157 -0
- package/hooks/plan-capture.mjs +14 -3
- package/hooks/sensors-core.mjs +15 -3
- package/hooks/session-backfill.mjs +7 -2
- package/hooks/session-ensure.mjs +6 -4
- package/hooks/session-iteration.mjs +65 -0
- package/hooks/session-memory-lifecycle.mjs +10 -5
- package/hooks/session-note-io.mjs +130 -15
- package/hooks/session-observability.mjs +4 -2
- package/hooks/session-stop.mjs +65 -19
- package/hooks/spec-core.mjs +91 -12
- package/hooks/subagent-stop.mjs +4 -1
- package/hooks/subagent-usage.mjs +2 -2
- package/hooks/task-log.mjs +3 -1
- package/hooks/token-usage.mjs +1 -1
- package/hooks/vault-health.mjs +183 -37
- package/hooks/vault-path-safety.mjs +2 -0
- package/hooks/vault-runtime-store.mjs +558 -0
- package/package.json +10 -3
- package/packages/cli/package.json +5 -0
- package/packages/harness/package.json +5 -0
- package/packages/integrations/package.json +5 -0
- package/packages/mcp/package.json +5 -0
- package/packages/pi/package.json +5 -0
- package/packages/vault/package.json +6 -0
- package/packages/vault/src/index.mjs +2 -0
- package/packages/vault/src/project-vault.mjs +327 -0
- package/packages/vault/src/vault-path-safety.mjs +558 -0
- package/src/change.mjs +2 -1
- package/src/flow.mjs +232 -0
- package/src/init.mjs +26 -3
- package/src/memory.mjs +785 -35
- package/src/operating-profile.mjs +133 -0
- package/src/profile.mjs +224 -0
- package/src/project-vault.mjs +2 -221
- package/src/rebuild-costs.mjs +11 -4
- package/src/skills-seed.mjs +38 -16
- package/src/sync-defs.mjs +16 -7
- package/src/sync.mjs +9 -1
- package/src/taxonomy.mjs +8 -0
- package/src/validate-memory.mjs +21 -8
- package/src/verify.mjs +12 -2
package/src/skills-seed.mjs
CHANGED
|
@@ -11,18 +11,29 @@ function skill(name, description, body, files = []) {
|
|
|
11
11
|
return { name, description, body: `---\nname: ${name}\ndescription: ${description}\n---\n${body}`, files };
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const WORKFLOW = `#
|
|
14
|
+
const WORKFLOW = `# Perfis de Operação — roteador de trabalho do wendkeep
|
|
15
15
|
|
|
16
|
-
Use ao começar
|
|
17
|
-
|
|
16
|
+
Use ao começar implementação, correção ou refatoração. **Keep Core permanece sempre ativo**
|
|
17
|
+
em todos os perfis: Vault, sessão, identidade, memória, lessons e persistência. Na ausência de
|
|
18
|
+
configuração válida, **GOVERN é o padrão** compatível.
|
|
18
19
|
|
|
19
20
|
<HARD-GATE>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
Antes de editar, leia o **perfil efetivo** injetado pelo WendKeep e siga somente sua rota:
|
|
22
|
+
- \`OFF\`: não imponha processo Wend; a governança pertence ao **harness nativo da LLM**.
|
|
23
|
+
- \`FLOW\`: inicie o microcontrato com \`wendkeep flow start\` antes de editar os paths permitidos.
|
|
24
|
+
- \`GUIDE\`, \`GOVERN\` ou \`ASSURE\`: não edite código antes de Propose / \`wendkeep change new\`.
|
|
25
|
+
Este gate nunca transforma \`OFF\` ou \`FLOW\` silenciosamente em \`GOVERN\`.
|
|
23
26
|
</HARD-GATE>
|
|
24
27
|
|
|
25
|
-
##
|
|
28
|
+
## Rotas por perfil
|
|
29
|
+
|
|
30
|
+
- **OFF — LLM nativa:** Wend Runtime desligado; esta skill devolve a execução ao harness nativo.
|
|
31
|
+
- **FLOW — E → V:** \`flow start\` → implementar com wk-tdd → \`flow finish\`; sem change/ADR/verdict.
|
|
32
|
+
- **GUIDE — P → E → V:** change compacta, sem revisão formal obrigatória.
|
|
33
|
+
- **GOVERN — P → R → E → V:** loop a2 atual, com design/revisão; é o padrão conservador.
|
|
34
|
+
- **ASSURE — P → R → E → V → C:** GOVERN acrescido de confirmação e handoff explícitos.
|
|
35
|
+
|
|
36
|
+
## Passos para GUIDE, GOVERN e ASSURE
|
|
26
37
|
|
|
27
38
|
1. **Explore** — entenda o problema antes de propor. Leia o código/contexto relevante.
|
|
28
39
|
2. **Propose** — \`wendkeep change new <slug>\`. Isso cria \`08-Mudanças/<slug>/\` com:
|
|
@@ -251,18 +262,29 @@ nunca tivesse visto a implementação. Contexto fresco, read-only.
|
|
|
251
262
|
- \`verdict-template.json\` — o formato exato do \`verdict.json\` a gravar.
|
|
252
263
|
`;
|
|
253
264
|
|
|
254
|
-
const WORKFLOW_EN = `#
|
|
265
|
+
const WORKFLOW_EN = `# Operating Profiles — wendkeep work router
|
|
255
266
|
|
|
256
|
-
Use
|
|
257
|
-
|
|
267
|
+
Use this when starting an implementation, fix, or refactor. **Keep Core is always active**
|
|
268
|
+
in every profile: Vault, session, identity, memory, lessons, and persistence. With no valid
|
|
269
|
+
configuration, **GOVERN is the default** for compatibility.
|
|
258
270
|
|
|
259
271
|
<HARD-GATE>
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
272
|
+
Before editing, read the injected **effective profile** and follow only its route:
|
|
273
|
+
- \`OFF\`: impose no Wend process; governance belongs to the **native LLM harness**.
|
|
274
|
+
- \`FLOW\`: start the microcontract with \`wendkeep flow start\` before editing allowed paths.
|
|
275
|
+
- \`GUIDE\`, \`GOVERN\`, or \`ASSURE\`: do not edit code before Propose / \`wendkeep change new\`.
|
|
276
|
+
This gate never silently turns \`OFF\` or \`FLOW\` into \`GOVERN\`.
|
|
263
277
|
</HARD-GATE>
|
|
264
278
|
|
|
265
|
-
##
|
|
279
|
+
## Profile routes
|
|
280
|
+
|
|
281
|
+
- **OFF — native LLM:** Wend Runtime is disabled; this skill returns execution to the native harness.
|
|
282
|
+
- **FLOW — E → V:** \`flow start\` → implement with wk-tdd → \`flow finish\`; no change/ADR/verdict.
|
|
283
|
+
- **GUIDE — P → E → V:** a compact change with no mandatory formal review.
|
|
284
|
+
- **GOVERN — P → R → E → V:** the current a2 loop with design/review; the conservative default.
|
|
285
|
+
- **ASSURE — P → R → E → V → C:** GOVERN plus explicit confirmation and handoff.
|
|
286
|
+
|
|
287
|
+
## Steps for GUIDE, GOVERN, and ASSURE
|
|
266
288
|
|
|
267
289
|
1. **Explore** — understand the problem before proposing.
|
|
268
290
|
2. **Propose** — \`wendkeep change new <slug>\` scaffolds \`08-Changes/<slug>/\`
|
|
@@ -597,7 +619,7 @@ size of the problem>
|
|
|
597
619
|
// usuário ("implementa X", "corrige Y"), não com abstrações ("mudança não-trivial"). Gatilhos
|
|
598
620
|
// concretos + instrução imperativa = a skill dispara sozinha (paridade Superpowers).
|
|
599
621
|
const WK_SKILLS_PT = [
|
|
600
|
-
skill('wk-workflow', 'Use
|
|
622
|
+
skill('wk-workflow', 'Use quando o usuário pedir para implementar, criar, corrigir, refatorar, adicionar ou alterar código: leia o perfil efetivo e roteie OFF/FLOW/GUIDE/GOVERN/ASSURE ANTES de editar. Keep Core permanece ativo; GOVERN é o padrão compatível.', WORKFLOW),
|
|
601
623
|
skill('wk-tdd', 'Use ao implementar qualquer comportamento — Red/Green/Refactor com testes que discriminam (derivados do spec, litmus não-raso, adequação).', TDD),
|
|
602
624
|
skill('wk-debugging', 'Use quando algo falha, quebra, dá erro ou regride — depuração sistemática por hipótese antes de corrigir.', DEBUGGING),
|
|
603
625
|
skill('wk-brainstorming', 'Use quando a ideia ainda é vaga ou o usuário quer discutir/planejar uma feature (inclusive em plan mode) — vira design aprovado, com closure gate e tabela out-of-scope, antes de código.', BRAINSTORMING, [{ name: 'design-template.md', content: DESIGN_TEMPLATE_PT }]),
|
|
@@ -606,7 +628,7 @@ const WK_SKILLS_PT = [
|
|
|
606
628
|
];
|
|
607
629
|
|
|
608
630
|
const WK_SKILLS_EN = [
|
|
609
|
-
skill('wk-workflow', 'Use
|
|
631
|
+
skill('wk-workflow', 'Use when the user asks to implement, create, fix, refactor, add, or change code: read the effective profile and route OFF/FLOW/GUIDE/GOVERN/ASSURE BEFORE editing. Keep Core stays active; GOVERN is the compatible default.', WORKFLOW_EN),
|
|
610
632
|
skill('wk-tdd', 'Use when implementing any behaviour — Red/Green/Refactor with tests that discriminate (spec-derived, non-shallow litmus, adequacy).', TDD_EN),
|
|
611
633
|
skill('wk-debugging', 'Use when something fails, breaks, errors or regresses — systematic hypothesis-driven debugging before fixing.', DEBUGGING_EN),
|
|
612
634
|
skill('wk-brainstorming', 'Use when the idea is still vague or the user wants to discuss/plan a feature (plan mode included) — turns it into an approved design, with a closure gate and out-of-scope table, before code.', BRAINSTORMING_EN, [{ name: 'design-template.md', content: DESIGN_TEMPLATE_EN }]),
|
package/src/sync-defs.mjs
CHANGED
|
@@ -58,14 +58,23 @@ function renderAgentsSection(skills, sourceHash = '') {
|
|
|
58
58
|
const list = skills.map((s) => `- **${s.name}** — ${s.description}`).join('\n');
|
|
59
59
|
return `${AG_START}
|
|
60
60
|
<!-- wendkeep-version: ${WENDKEEP_VERSION}; skills-sha256: ${sourceHash} -->
|
|
61
|
-
## wendkeep —
|
|
61
|
+
## wendkeep — Keep Core & operating profiles
|
|
62
62
|
|
|
63
|
-
This project uses the [wendkeep](https://github.com/rogersialves/wendkeep) harness.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
This project uses the [wendkeep](https://github.com/rogersialves/wendkeep) harness. **Keep Core is always active**
|
|
64
|
+
in every profile: Vault, session, identity, memory, lessons, and persistence integrations.
|
|
65
|
+
The effective profile is selected explicitly; missing or invalid configuration uses **GOVERN as the default**.
|
|
66
|
+
|
|
67
|
+
Route work by the effective profile:
|
|
68
|
+
- **OFF** — Wend Runtime is disabled and governance belongs to the native LLM harness; Keep Core stays active.
|
|
69
|
+
- **FLOW** — Execute → Validate through \`wendkeep flow start/finish\`, without creating a change.
|
|
70
|
+
- **GUIDE** — Plan → Execute → Validate through a compact change.
|
|
71
|
+
- **GOVERN** — the default a2 loop: \`wendkeep change new <slug>\` → review → implement tasks test-first
|
|
72
|
+
(tag proof \`[sensor:id]\` and requirement \`[req:ID]\`) → \`wendkeep verify\` →
|
|
73
|
+
\`wendkeep verify --deep\` + independent read-only verdict → \`wendkeep change archive\`.
|
|
74
|
+
- **ASSURE** — GOVERN plus explicit confirmation and handoff.
|
|
75
|
+
|
|
76
|
+
Inspect with \`wendkeep profile status\` / \`wendkeep change status\` /
|
|
77
|
+
\`spec effective --change <slug>\` / \`sensors list\`. Author specs only in
|
|
69
78
|
\`08-Mudanças/<slug>/specs/\`; \`07-Specs\` is generated and must not be edited directly.
|
|
70
79
|
|
|
71
80
|
Process skills (full text in \`.claude/skills/\`, \`.agents/skills/\`, and the vault's \`.brain/skills/\`):
|
package/src/sync.mjs
CHANGED
|
@@ -22,6 +22,9 @@ const step = (n, label) => process.stdout.write(`\n[${n}/3] ${label}\n`);
|
|
|
22
22
|
export async function runSync(argv) {
|
|
23
23
|
const projectRaw = opt(argv, '--project');
|
|
24
24
|
const vaultRaw = opt(argv, '--vault');
|
|
25
|
+
const hasProfile = argv.includes('--profile') || argv.some((a) => a.startsWith('--profile='));
|
|
26
|
+
const profileRaw = opt(argv, '--profile');
|
|
27
|
+
const profileArgs = hasProfile ? ['--profile', profileRaw] : [];
|
|
25
28
|
const projectPath = resolve(projectRaw && !projectRaw.startsWith('--') ? projectRaw : process.cwd());
|
|
26
29
|
const passthrough = argv.filter((a) => a === '--yes' || a === '-y' || a === '--force');
|
|
27
30
|
|
|
@@ -29,7 +32,12 @@ export async function runSync(argv) {
|
|
|
29
32
|
step(1, 'init');
|
|
30
33
|
const { runInit } = await import('./init.mjs');
|
|
31
34
|
try {
|
|
32
|
-
await runInit([
|
|
35
|
+
await runInit([
|
|
36
|
+
'--project', projectPath,
|
|
37
|
+
...(vaultRaw ? ['--vault', vaultRaw] : []),
|
|
38
|
+
...profileArgs,
|
|
39
|
+
...passthrough,
|
|
40
|
+
]);
|
|
33
41
|
} catch (error) {
|
|
34
42
|
process.stderr.write(`wendkeep sync: init falhou — ${error.message}\n`);
|
|
35
43
|
return 1;
|
package/src/taxonomy.mjs
CHANGED
|
@@ -38,6 +38,14 @@ export const HOOK_FILES = [
|
|
|
38
38
|
'memory-store.mjs',
|
|
39
39
|
'memory-handoff.mjs',
|
|
40
40
|
'session-memory-lifecycle.mjs',
|
|
41
|
+
'session-note-io.mjs',
|
|
42
|
+
'operating-profile-runtime.mjs',
|
|
43
|
+
'git-snapshot.mjs',
|
|
44
|
+
'flow-protected-policy.mjs',
|
|
45
|
+
'session-iteration.mjs',
|
|
46
|
+
'vault-path-safety.mjs',
|
|
47
|
+
'vault-runtime-store.mjs',
|
|
48
|
+
'flow-core.mjs',
|
|
41
49
|
'change-core.mjs',
|
|
42
50
|
'spec-core.mjs',
|
|
43
51
|
'sensors-core.mjs',
|
package/src/validate-memory.mjs
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { validateMemoryEvent, validateSharedMemory } from '../hooks/memory-schema.mjs';
|
|
4
|
+
import { assertVaultPathSafe } from '../hooks/vault-path-safety.mjs';
|
|
4
5
|
import { validateCore } from './validate-core.mjs';
|
|
5
6
|
|
|
6
7
|
function failedComponent(errors, extra = {}) {
|
|
7
8
|
return { ok: false, errors: Array.isArray(errors) ? errors : [errors], warnings: [], ...extra };
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
function readRequired(path, label) {
|
|
11
|
-
|
|
11
|
+
function readRequired(vaultBase, path, label) {
|
|
12
|
+
let checked;
|
|
12
13
|
try {
|
|
13
|
-
|
|
14
|
+
checked = assertVaultPathSafe(vaultBase, path, {
|
|
15
|
+
expectedType: 'file', label: `artefato ${label}`,
|
|
16
|
+
});
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return { ok: false, error: `${label} inseguro: ${error?.message || error}` };
|
|
19
|
+
}
|
|
20
|
+
if (!checked.exists) return { ok: false, error: `${label} ausente: ${path}` };
|
|
21
|
+
try {
|
|
22
|
+
// Deliberately adjacent to the open performed by readFileSync.
|
|
23
|
+
checked = assertVaultPathSafe(vaultBase, checked.target, {
|
|
24
|
+
allowMissing: false, expectedType: 'file', label: `artefato ${label}`,
|
|
25
|
+
});
|
|
26
|
+
return { ok: true, content: readFileSync(checked.target, 'utf8') };
|
|
14
27
|
} catch (error) {
|
|
15
28
|
return { ok: false, error: `${label} ilegível: ${error?.message || error}` };
|
|
16
29
|
}
|
|
@@ -18,7 +31,7 @@ function readRequired(path, label) {
|
|
|
18
31
|
|
|
19
32
|
export function readProjectForValidation(vaultBase) {
|
|
20
33
|
const path = join(vaultBase, '.brain', 'PROJECT.json');
|
|
21
|
-
const read = readRequired(path, 'PROJECT.json');
|
|
34
|
+
const read = readRequired(vaultBase, path, 'PROJECT.json');
|
|
22
35
|
if (!read.ok) return failedComponent(read.error, { projectId: '', path });
|
|
23
36
|
try {
|
|
24
37
|
const marker = JSON.parse(read.content);
|
|
@@ -34,7 +47,7 @@ export function readProjectForValidation(vaultBase) {
|
|
|
34
47
|
/** Read and validate the append-only JSONL authority without repairing or mutating it. */
|
|
35
48
|
export function readLedgerForValidation(vaultBase, { projectId } = {}) {
|
|
36
49
|
const path = join(vaultBase, '.brain', 'MEMORY_EVENTS.jsonl');
|
|
37
|
-
const read = readRequired(path, 'MEMORY_EVENTS.jsonl');
|
|
50
|
+
const read = readRequired(vaultBase, path, 'MEMORY_EVENTS.jsonl');
|
|
38
51
|
if (!read.ok) return failedComponent(read.error, { events: [], eventIds: new Set(), path });
|
|
39
52
|
|
|
40
53
|
const errors = [];
|
|
@@ -79,14 +92,14 @@ export function readLedgerForValidation(vaultBase, { projectId } = {}) {
|
|
|
79
92
|
|
|
80
93
|
function validateCoreArtifact(vaultBase) {
|
|
81
94
|
const path = join(vaultBase, '.brain', 'CORE.md');
|
|
82
|
-
const read = readRequired(path, 'CORE.md');
|
|
95
|
+
const read = readRequired(vaultBase, path, 'CORE.md');
|
|
83
96
|
if (!read.ok) return failedComponent(read.error, { lineCount: 0, path });
|
|
84
97
|
return { ...validateCore(read.content), path, content: read.content };
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
function validateSharedArtifact(vaultBase, eventIds) {
|
|
88
101
|
const path = join(vaultBase, '.brain', 'SHARED_MEMORY.md');
|
|
89
|
-
const read = readRequired(path, 'SHARED_MEMORY.md');
|
|
102
|
+
const read = readRequired(vaultBase, path, 'SHARED_MEMORY.md');
|
|
90
103
|
if (!read.ok) return failedComponent(read.error, { path });
|
|
91
104
|
return { ...validateSharedMemory(read.content, { eventIds }), path, content: read.content };
|
|
92
105
|
}
|
package/src/verify.mjs
CHANGED
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
import { readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
6
6
|
import { parseTasks, activeChange, appendFixTasks, healSpecBacklinks } from '../hooks/change-core.mjs';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
loadSensorsDetailed,
|
|
9
|
+
findProjectRoot,
|
|
10
|
+
requiredSensors,
|
|
11
|
+
runSensors,
|
|
12
|
+
evaluateGate,
|
|
13
|
+
sensorProcessEnv,
|
|
14
|
+
} from '../hooks/sensors-core.mjs';
|
|
8
15
|
import {
|
|
9
16
|
buildEffectiveRequirementPackage,
|
|
10
17
|
captureSpecBaseline,
|
|
@@ -54,7 +61,10 @@ export function runVerify(argv) {
|
|
|
54
61
|
process.stderr.write(`wendkeep verify: wendkeep.sensors.json não encontrado em ${loaded.path} — rode da raiz do projeto ou use --project <raiz>\n`);
|
|
55
62
|
}
|
|
56
63
|
const sensors = loaded.sensors;
|
|
57
|
-
const evidence = runSensors(sensors, ids, {
|
|
64
|
+
const evidence = runSensors(sensors, ids, {
|
|
65
|
+
cwd: projectRoot,
|
|
66
|
+
env: sensorProcessEnv(vaultBase),
|
|
67
|
+
});
|
|
58
68
|
writeFileSync(join(changeDir, 'evidencia.json'), `${JSON.stringify(evidence, null, 2)}\n`, 'utf8');
|
|
59
69
|
// Freshness seal: bind this evidence to the tarefas.md it was produced against, so the archive
|
|
60
70
|
// gate can reject evidence gone stale (a sensor task added after this verify run).
|