@dzhechkov/harness-core 0.8.32 → 0.8.33
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/.dz-manifest.json +97 -37
- package/README.md +30 -0
- package/dist/apply-leg.d.ts +13 -1
- package/dist/apply-leg.d.ts.map +1 -1
- package/dist/apply-leg.js +123 -10
- package/dist/apply-leg.js.map +1 -1
- package/dist/embed-socket-path.d.ts +65 -0
- package/dist/embed-socket-path.d.ts.map +1 -0
- package/dist/embed-socket-path.js +100 -0
- package/dist/embed-socket-path.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +66 -3
- package/dist/operations.js.map +1 -1
- package/dist/packed-install-smoke.d.ts +108 -0
- package/dist/packed-install-smoke.d.ts.map +1 -0
- package/dist/packed-install-smoke.js +172 -0
- package/dist/packed-install-smoke.js.map +1 -0
- package/dist/publish-sibling-drift.d.ts +67 -0
- package/dist/publish-sibling-drift.d.ts.map +1 -0
- package/dist/publish-sibling-drift.js +262 -0
- package/dist/publish-sibling-drift.js.map +1 -0
- package/dist/publish.d.ts +44 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +243 -24
- package/dist/publish.js.map +1 -1
- package/dist/qe-bridge.d.ts +16 -0
- package/dist/qe-bridge.d.ts.map +1 -1
- package/dist/qe-bridge.js +1 -0
- package/dist/qe-bridge.js.map +1 -1
- package/dist/release.d.ts +19 -0
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +81 -2
- package/dist/release.js.map +1 -1
- package/dist/setup.d.ts +36 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +96 -2
- package/dist/setup.js.map +1 -1
- package/package.json +23 -23
- package/sbom.json +186 -36
- package/src/apply-leg.ts +123 -10
- package/src/embed-socket-path.ts +113 -0
- package/src/index.ts +35 -2
- package/src/operations.ts +67 -3
- package/src/packed-install-smoke.ts +273 -0
- package/src/publish-sibling-drift.ts +293 -0
- package/src/publish.ts +280 -25
- package/src/qe-bridge.ts +14 -0
- package/src/release.ts +103 -2
- package/src/setup.ts +108 -2
package/src/setup.ts
CHANGED
|
@@ -44,6 +44,77 @@ import {
|
|
|
44
44
|
/** Memory backend type. */
|
|
45
45
|
export type MemoryBackend = 'jsonl' | 'agentdb';
|
|
46
46
|
|
|
47
|
+
/** Where a resolved setup memory backend came from (feature `setup-backend-from-config`). */
|
|
48
|
+
export type MemoryBackendSource = 'flag' | 'config' | 'default' | 'default-unreadable' | 'disabled';
|
|
49
|
+
|
|
50
|
+
/** Result of {@link resolveSetupMemoryBackend}. */
|
|
51
|
+
export interface ResolvedSetupMemoryBackend {
|
|
52
|
+
readonly backend: MemoryBackend;
|
|
53
|
+
readonly source: MemoryBackendSource;
|
|
54
|
+
/** `true` only when an explicit `--memory jsonl` pulled an agentdb-configured project down to jsonl (FR-2). */
|
|
55
|
+
readonly downgraded: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* FR-1/FR-2/FR-3 (feature `setup-backend-from-config`). Before this function, `runSetup` decided
|
|
60
|
+
* the backend as `opts.memory ?? 'jsonl'` — a repeat `dz setup --target claude-code` (no `--memory`)
|
|
61
|
+
* on an agentdb project silently reset it to jsonl and dropped `.dz/agentdb-writer.mjs` from
|
|
62
|
+
* `SessionStart` (AC-1, red-first). This is the ONE place that decides the backend for a run, so
|
|
63
|
+
* the config write, the printed source line, and the doctor cross-check can never disagree.
|
|
64
|
+
*
|
|
65
|
+
* - An explicit `--memory <x>` always wins (`source: 'flag'`) — including the one case that
|
|
66
|
+
* DOWNGRADES an agentdb-configured project to jsonl (FR-2): `downgraded` is set so the caller can
|
|
67
|
+
* warn and force the config write back in sync even without `--force`.
|
|
68
|
+
* - No flag, and `.dz/config.json` has a recognised `memory.backend` → that value, `source: 'config'`.
|
|
69
|
+
* - No flag, and no config (absent, unreadable, or an unrecognised backend value) → `jsonl`,
|
|
70
|
+
* `source: 'default'` — the literal ticket command on an empty project (no change, named in
|
|
71
|
+
* 01_requirements.md "Что НЕ чинится").
|
|
72
|
+
*/
|
|
73
|
+
export function resolveSetupMemoryBackend(
|
|
74
|
+
projectRoot: string,
|
|
75
|
+
memoryOpt: MemoryBackend | undefined,
|
|
76
|
+
noMemory: boolean = false,
|
|
77
|
+
): ResolvedSetupMemoryBackend {
|
|
78
|
+
// Lead edit after Codex review (findings 5/6): a config that EXISTS but cannot be read, or names an
|
|
79
|
+
// unknown backend, is not "no config" — its source is labeled so, and a later step never overwrites
|
|
80
|
+
// it silently. `--no-memory` disables memory entirely: no downgrade, no config rewrite.
|
|
81
|
+
let configuredBackend: MemoryBackend | undefined;
|
|
82
|
+
let configUnreadable = false;
|
|
83
|
+
const configPath = join(projectRoot, '.dz', 'config.json');
|
|
84
|
+
if (existsSync(configPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8')) as { memory?: { backend?: string } };
|
|
87
|
+
if (cfg.memory?.backend === 'agentdb') configuredBackend = 'agentdb';
|
|
88
|
+
else if (cfg.memory?.backend === 'jsonl') configuredBackend = 'jsonl';
|
|
89
|
+
else configUnreadable = true;
|
|
90
|
+
} catch {
|
|
91
|
+
configUnreadable = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (noMemory) {
|
|
95
|
+
return { backend: memoryOpt ?? configuredBackend ?? 'jsonl', source: 'disabled', downgraded: false };
|
|
96
|
+
}
|
|
97
|
+
if (memoryOpt !== undefined) {
|
|
98
|
+
return { backend: memoryOpt, source: 'flag', downgraded: memoryOpt === 'jsonl' && configuredBackend === 'agentdb' };
|
|
99
|
+
}
|
|
100
|
+
if (configuredBackend !== undefined) {
|
|
101
|
+
return { backend: configuredBackend, source: 'config', downgraded: false };
|
|
102
|
+
}
|
|
103
|
+
return { backend: 'jsonl', source: configUnreadable ? 'default-unreadable' : 'default', downgraded: false };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* FR-3: the human-readable "source" suffix, shared between `runSetup`'s own warning step and the
|
|
108
|
+
* CLI's printed `memory backend: …` line so the two texts can never drift apart.
|
|
109
|
+
*/
|
|
110
|
+
export function memoryBackendSourceLabel(source: MemoryBackendSource): string {
|
|
111
|
+
if (source === 'flag') return 'from --memory';
|
|
112
|
+
if (source === 'config') return 'from .dz/config.json';
|
|
113
|
+
if (source === 'default-unreadable') return 'default — .dz/config.json unreadable or names no known backend';
|
|
114
|
+
if (source === 'disabled') return 'memory disabled (--no-memory)';
|
|
115
|
+
return 'default — no .dz/config.json';
|
|
116
|
+
}
|
|
117
|
+
|
|
47
118
|
/** Setup options. */
|
|
48
119
|
export interface SetupOptions {
|
|
49
120
|
readonly projectRoot: string;
|
|
@@ -72,6 +143,12 @@ export interface SetupResult {
|
|
|
72
143
|
readonly totalSteps: number;
|
|
73
144
|
readonly completed: number;
|
|
74
145
|
readonly skipped: number;
|
|
146
|
+
/** The memory backend this run actually used (feature `setup-backend-from-config`, FR-1). */
|
|
147
|
+
readonly memoryBackend: MemoryBackend;
|
|
148
|
+
/** Where {@link memoryBackend} came from — FR-3, also the `--json` field name. */
|
|
149
|
+
readonly memoryBackendSource: MemoryBackendSource;
|
|
150
|
+
/** `true` when an explicit `--memory jsonl` pulled an agentdb-configured project down (FR-2). */
|
|
151
|
+
readonly memoryBackendDowngraded: boolean;
|
|
75
152
|
}
|
|
76
153
|
|
|
77
154
|
/** A single setup step. */
|
|
@@ -809,7 +886,10 @@ function applyLegStepResult(opts: SetupOptions, backend: MemoryBackend): SetupSt
|
|
|
809
886
|
export function runSetup(opts: SetupOptions): SetupResult {
|
|
810
887
|
const steps: SetupStep[] = [];
|
|
811
888
|
const dzDir = join(opts.projectRoot, '.dz');
|
|
812
|
-
|
|
889
|
+
// FR-1/FR-2/FR-3 (feature `setup-backend-from-config`): read BEFORE this run writes anything, so
|
|
890
|
+
// the comparison is against the PRIOR config, never the one this same call is about to produce.
|
|
891
|
+
const resolvedMemory = resolveSetupMemoryBackend(opts.projectRoot, opts.memory, opts.noMemory === true);
|
|
892
|
+
const backend: MemoryBackend = resolvedMemory.backend;
|
|
813
893
|
|
|
814
894
|
// Step 0: Install agentdb + better-sqlite3 locally so the session-hook writer can import them
|
|
815
895
|
// and share a native store with the MCP server. Best-effort — the writer self-degrades to a
|
|
@@ -835,14 +915,37 @@ export function runSetup(opts: SetupOptions): SetupResult {
|
|
|
835
915
|
steps.push({ name: 'Create .dz directory', status: 'skipped', detail: 'already exists' });
|
|
836
916
|
}
|
|
837
917
|
|
|
838
|
-
// Step 2: Write .dz/config.json
|
|
918
|
+
// Step 2: Write .dz/config.json. FR-2: a DOWNGRADE (explicit --memory jsonl over an
|
|
919
|
+
// agentdb-configured project) forces the write even without --force — "two truths after any
|
|
920
|
+
// setup coincide" means the config may not keep claiming agentdb once the caller has explicitly
|
|
921
|
+
// asked for jsonl.
|
|
839
922
|
const configPath = join(dzDir, 'config.json');
|
|
840
923
|
if (!existsSync(configPath) || opts.force) {
|
|
841
924
|
writeFileSync(configPath, generateDzConfig(opts.target, opts.preset, backend));
|
|
842
925
|
steps.push({ name: 'Write .dz/config.json', status: 'done', detail: `${backend} backend` });
|
|
926
|
+
} else if (resolvedMemory.downgraded) {
|
|
927
|
+
// Lead edit after Codex review (finding 3): a downgrade changes ONLY memory.backend — every other
|
|
928
|
+
// field the owner keeps in .dz/config.json survives; an unparsable file falls back to regeneration.
|
|
929
|
+
let rewritten = false;
|
|
930
|
+
try {
|
|
931
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8')) as Record<string, unknown>;
|
|
932
|
+
const memory = (cfg['memory'] !== null && typeof cfg['memory'] === 'object') ? (cfg['memory'] as Record<string, unknown>) : {};
|
|
933
|
+
cfg['memory'] = { ...memory, backend };
|
|
934
|
+
writeFileSync(configPath, JSON.stringify(cfg, null, 2) + '\n');
|
|
935
|
+
rewritten = true;
|
|
936
|
+
} catch { /* fall through to regeneration */ }
|
|
937
|
+
if (!rewritten) writeFileSync(configPath, generateDzConfig(opts.target, opts.preset, backend));
|
|
938
|
+
steps.push({ name: 'Write .dz/config.json', status: 'done', detail: `memory.backend → ${backend} (other fields kept)` });
|
|
843
939
|
} else {
|
|
844
940
|
steps.push({ name: 'Write .dz/config.json', status: 'skipped', detail: 'already exists (use --force)' });
|
|
845
941
|
}
|
|
942
|
+
if (resolvedMemory.downgraded) {
|
|
943
|
+
steps.push({
|
|
944
|
+
name: 'Memory backend downgrade',
|
|
945
|
+
status: 'done',
|
|
946
|
+
detail: '⚠ memory backend downgraded agentdb → jsonl by --memory jsonl',
|
|
947
|
+
});
|
|
948
|
+
}
|
|
846
949
|
|
|
847
950
|
// Step 3: Initialize session log
|
|
848
951
|
const sessionsPath = join(dzDir, 'sessions.jsonl');
|
|
@@ -1219,5 +1322,8 @@ export function runSetup(opts: SetupOptions): SetupResult {
|
|
|
1219
1322
|
totalSteps: steps.length,
|
|
1220
1323
|
completed: steps.filter((s) => s.status === 'done').length,
|
|
1221
1324
|
skipped: steps.filter((s) => s.status === 'skipped').length,
|
|
1325
|
+
memoryBackend: resolvedMemory.backend,
|
|
1326
|
+
memoryBackendSource: resolvedMemory.source,
|
|
1327
|
+
memoryBackendDowngraded: resolvedMemory.downgraded,
|
|
1222
1328
|
};
|
|
1223
1329
|
}
|