zelari-code 0.2.2 → 0.6.2
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 +97 -2
- package/dist/agents/councilApi.js +7 -7
- package/dist/agents/councilApi.js.map +1 -1
- package/dist/agents/councilDirectives.js +3 -3
- package/dist/agents/promoteMember.js +2 -2
- package/dist/agents/roles.js +32 -32
- package/dist/agents/roles.js.map +1 -1
- package/dist/agents/skills/builtin/debugging.js +4 -4
- package/dist/agents/skills/builtin/debugging.js.map +1 -1
- package/dist/agents/skills/builtin/docs.js +13 -23
- package/dist/agents/skills/builtin/docs.js.map +1 -1
- package/dist/agents/skills/builtin/git-ops.js +3 -3
- package/dist/agents/skills/builtin/git-ops.js.map +1 -1
- package/dist/agents/skills/builtin/planning.js +4 -4
- package/dist/agents/skills/builtin/planning.js.map +1 -1
- package/dist/agents/skills/builtin/refactoring.js +3 -3
- package/dist/agents/skills/builtin/refactoring.js.map +1 -1
- package/dist/agents/skills/builtin/review.js +9 -9
- package/dist/agents/skills/builtin/review.js.map +1 -1
- package/dist/agents/skills/builtin/testing.js +3 -3
- package/dist/agents/skills/builtin/testing.js.map +1 -1
- package/dist/agents/tools.js +9 -2
- package/dist/agents/tools.js.map +1 -1
- package/dist/cli/app.js +94 -1861
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/compaction.js.map +1 -1
- package/dist/cli/components/ChatStream.js +81 -14
- package/dist/cli/components/ChatStream.js.map +1 -1
- package/dist/cli/components/CollapsibleToolOutput.js +26 -3
- package/dist/cli/components/CollapsibleToolOutput.js.map +1 -1
- package/dist/cli/components/Header.js +20 -1
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/InputBar.js +34 -2
- package/dist/cli/components/InputBar.js.map +1 -1
- package/dist/cli/components/Sidebar.js +30 -10
- package/dist/cli/components/Sidebar.js.map +1 -1
- package/dist/cli/councilDispatcher.js +10 -2
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/headless.js +137 -0
- package/dist/cli/headless.js.map +1 -0
- package/dist/cli/hooks/chatStats.js +28 -0
- package/dist/cli/hooks/chatStats.js.map +1 -0
- package/dist/cli/hooks/eventsToMessages.js +111 -0
- package/dist/cli/hooks/eventsToMessages.js.map +1 -0
- package/dist/cli/hooks/messageHelpers.js +125 -0
- package/dist/cli/hooks/messageHelpers.js.map +1 -0
- package/dist/cli/hooks/skillCompare.js +69 -0
- package/dist/cli/hooks/skillCompare.js.map +1 -0
- package/dist/cli/hooks/steer.js +28 -0
- package/dist/cli/hooks/steer.js.map +1 -0
- package/dist/cli/hooks/useBatchedMessages.js +67 -0
- package/dist/cli/hooks/useBatchedMessages.js.map +1 -0
- package/dist/cli/hooks/useChatTurn.js +363 -0
- package/dist/cli/hooks/useChatTurn.js.map +1 -0
- package/dist/cli/hooks/useSession.js +116 -0
- package/dist/cli/hooks/useSession.js.map +1 -0
- package/dist/cli/hooks/useSlashDispatch.js +303 -0
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -0
- package/dist/cli/hooks/useTerminalSize.js +60 -0
- package/dist/cli/hooks/useTerminalSize.js.map +1 -0
- package/dist/cli/main.bundled.js +25212 -21722
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +86 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +9 -2
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/runHeadless.js +160 -0
- package/dist/cli/runHeadless.js.map +1 -0
- package/dist/cli/sessionManager.js +47 -1
- package/dist/cli/sessionManager.js.map +1 -1
- package/dist/cli/skillSuggest.js +1 -1
- package/dist/cli/slashCommands.js +72 -3
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/branch.js +57 -0
- package/dist/cli/slashHandlers/branch.js.map +1 -0
- package/dist/cli/slashHandlers/git.js +40 -0
- package/dist/cli/slashHandlers/git.js.map +1 -0
- package/dist/cli/slashHandlers/promoteMember.js +25 -0
- package/dist/cli/slashHandlers/promoteMember.js.map +1 -0
- package/dist/cli/slashHandlers/provider.js +199 -0
- package/dist/cli/slashHandlers/provider.js.map +1 -0
- package/dist/cli/slashHandlers/skills.js +82 -0
- package/dist/cli/slashHandlers/skills.js.map +1 -0
- package/dist/cli/slashHandlers/transcript.js +13 -0
- package/dist/cli/slashHandlers/transcript.js.map +1 -0
- package/dist/cli/slashHandlers/updater.js +40 -0
- package/dist/cli/slashHandlers/updater.js.map +1 -0
- package/dist/cli/slashHandlers/workspace.js +118 -0
- package/dist/cli/slashHandlers/workspace.js.map +1 -0
- package/dist/cli/toolRegistry.js +17 -8
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/utils/duration.js +34 -0
- package/dist/cli/utils/duration.js.map +1 -0
- package/dist/cli/wizard/firstRun.js +63 -0
- package/dist/cli/wizard/firstRun.js.map +1 -0
- package/dist/cli/wizard/index.js +150 -0
- package/dist/cli/wizard/index.js.map +1 -0
- package/dist/cli/wizard/runWizard.js +137 -0
- package/dist/cli/wizard/runWizard.js.map +1 -0
- package/dist/cli/wizard/useWizardState.js +151 -0
- package/dist/cli/wizard/useWizardState.js.map +1 -0
- package/dist/cli/workspace/agentsMd.js +314 -0
- package/dist/cli/workspace/agentsMd.js.map +1 -0
- package/dist/cli/workspace/index.js +24 -0
- package/dist/cli/workspace/index.js.map +1 -0
- package/dist/cli/workspace/paths.js +88 -0
- package/dist/cli/workspace/paths.js.map +1 -0
- package/dist/cli/workspace/postCouncilHook.js +38 -0
- package/dist/cli/workspace/postCouncilHook.js.map +1 -0
- package/dist/cli/workspace/storage.js +392 -0
- package/dist/cli/workspace/storage.js.map +1 -0
- package/dist/cli/workspace/stubs.js +528 -0
- package/dist/cli/workspace/stubs.js.map +1 -0
- package/dist/cli/workspace/toolRegistry.js +61 -0
- package/dist/cli/workspace/toolRegistry.js.map +1 -0
- package/dist/cli/workspace/types.js +10 -0
- package/dist/cli/workspace/types.js.map +1 -0
- package/dist/main/core/tools/builtin/_walk.js +129 -0
- package/dist/main/core/tools/builtin/_walk.js.map +1 -0
- package/dist/main/core/tools/builtin/diff.js +477 -0
- package/dist/main/core/tools/builtin/diff.js.map +1 -0
- package/dist/main/core/tools/builtin/listFiles.js +5 -43
- package/dist/main/core/tools/builtin/listFiles.js.map +1 -1
- package/dist/main/core/tools/builtin/search.js +120 -28
- package/dist/main/core/tools/builtin/search.js.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { setActiveProviderId, setModelForProvider, } from '../providerConfig.js';
|
|
2
|
+
import { setApiKey as setKeyStoreApiKey } from '../keyStore.js';
|
|
3
|
+
const ORDER = ['welcome', 'provider', 'model', 'apikey', 'confirm'];
|
|
4
|
+
function next(s) {
|
|
5
|
+
const idx = ORDER.indexOf(s);
|
|
6
|
+
if (idx === -1 || idx === ORDER.length - 1)
|
|
7
|
+
return null;
|
|
8
|
+
return ORDER[idx + 1];
|
|
9
|
+
}
|
|
10
|
+
function prev(s) {
|
|
11
|
+
const idx = ORDER.indexOf(s);
|
|
12
|
+
if (idx <= 0)
|
|
13
|
+
return null;
|
|
14
|
+
return ORDER[idx - 1];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Pure-function factory for the wizard state machine. Returned API is
|
|
18
|
+
* stateless from the caller's perspective — pass the same instance to
|
|
19
|
+
* React via `useMemo`.
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export function createWizardState(opts) {
|
|
24
|
+
const persistActive = opts.persistActiveProvider ?? ((id) => setActiveProviderId(id));
|
|
25
|
+
const persistModel = opts.persistModel ?? ((id, m) => setModelForProvider(id, m));
|
|
26
|
+
const persistKey = opts.persistApiKey ?? ((id, k) => setKeyStoreApiKey(id, k));
|
|
27
|
+
let s = {
|
|
28
|
+
step: 'welcome',
|
|
29
|
+
providerCursor: 0,
|
|
30
|
+
apiKeyCursor: 0,
|
|
31
|
+
committed: false,
|
|
32
|
+
};
|
|
33
|
+
const listeners = new Set();
|
|
34
|
+
function notify() {
|
|
35
|
+
for (const l of listeners)
|
|
36
|
+
l();
|
|
37
|
+
}
|
|
38
|
+
const api = {
|
|
39
|
+
get state() {
|
|
40
|
+
return s;
|
|
41
|
+
},
|
|
42
|
+
moveProvider(up) {
|
|
43
|
+
const n = opts.providers.length;
|
|
44
|
+
const c = s.providerCursor;
|
|
45
|
+
s = {
|
|
46
|
+
...s,
|
|
47
|
+
providerCursor: up ? (c - 1 + n) % n : (c + 1) % n,
|
|
48
|
+
};
|
|
49
|
+
notify();
|
|
50
|
+
},
|
|
51
|
+
selectProvider() {
|
|
52
|
+
const provider = opts.providers[s.providerCursor];
|
|
53
|
+
if (!provider)
|
|
54
|
+
return; // shouldn't happen
|
|
55
|
+
s = {
|
|
56
|
+
...s,
|
|
57
|
+
step: 'model',
|
|
58
|
+
providerId: provider.id,
|
|
59
|
+
model: opts.defaultModelFor(provider.id),
|
|
60
|
+
};
|
|
61
|
+
notify();
|
|
62
|
+
},
|
|
63
|
+
setModel(name) {
|
|
64
|
+
const trimmed = name.trim();
|
|
65
|
+
if (!trimmed || !s.providerId)
|
|
66
|
+
return;
|
|
67
|
+
s = { ...s, model: trimmed };
|
|
68
|
+
notify();
|
|
69
|
+
},
|
|
70
|
+
moveApiKey(up) {
|
|
71
|
+
const c = s.apiKeyCursor;
|
|
72
|
+
// 3 options: 0=env, 1=keystore, 2=skip
|
|
73
|
+
s = { ...s, apiKeyCursor: up ? (c - 1 + 3) % 3 : (c + 1) % 3 };
|
|
74
|
+
notify();
|
|
75
|
+
},
|
|
76
|
+
selectApiKey(choice, value) {
|
|
77
|
+
// 'keystore' stores the (trimmed) value; 'env' and 'skip' clear it.
|
|
78
|
+
// Distinguish `value === undefined` (no value provided) from
|
|
79
|
+
// `value === ''` or whitespace-only (empty after trim) — both
|
|
80
|
+
// are guarded at commit time, but the type signature is clearer
|
|
81
|
+
// if we keep `undefined` for "not provided".
|
|
82
|
+
let apiKeyValue;
|
|
83
|
+
if (choice === 'keystore') {
|
|
84
|
+
apiKeyValue = value === undefined ? undefined : value.trim();
|
|
85
|
+
}
|
|
86
|
+
s = {
|
|
87
|
+
...s,
|
|
88
|
+
apiKeyChoice: choice,
|
|
89
|
+
apiKeyValue,
|
|
90
|
+
step: 'confirm',
|
|
91
|
+
};
|
|
92
|
+
notify();
|
|
93
|
+
},
|
|
94
|
+
back() {
|
|
95
|
+
const p = prev(s.step);
|
|
96
|
+
if (!p)
|
|
97
|
+
return;
|
|
98
|
+
s = { ...s, step: p };
|
|
99
|
+
notify();
|
|
100
|
+
},
|
|
101
|
+
commit() {
|
|
102
|
+
if (s.committed || !s.providerId || !s.model)
|
|
103
|
+
return;
|
|
104
|
+
persistActive(s.providerId);
|
|
105
|
+
persistModel(s.providerId, s.model);
|
|
106
|
+
// Persist API key only if user chose 'keystore' AND provided a
|
|
107
|
+
// non-empty value. 'env' means "use env var, don't save" and
|
|
108
|
+
// 'skip' means "no key yet, user will set it later via /login".
|
|
109
|
+
if (s.apiKeyChoice === 'keystore' && s.apiKeyValue && s.apiKeyValue.length > 0) {
|
|
110
|
+
try {
|
|
111
|
+
persistKey(s.providerId, s.apiKeyValue);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
// Key persistence failure shouldn't block config commit —
|
|
115
|
+
// the user can re-add the key later via /login. Log to
|
|
116
|
+
// stderr for debuggability, then proceed.
|
|
117
|
+
// eslint-disable-next-line no-console
|
|
118
|
+
console.error(`[zelari-code wizard] failed to persist API key for ${s.providerId}: ` +
|
|
119
|
+
(err instanceof Error ? err.message : String(err)));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
s = { ...s, committed: true };
|
|
123
|
+
notify();
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
// Internal: allow React UI to re-render. We expose `subscribe` so the
|
|
127
|
+
// Ink component can useSyncExternalStore (or call manually in tests).
|
|
128
|
+
api.subscribe = (l) => {
|
|
129
|
+
listeners.add(l);
|
|
130
|
+
return () => listeners.delete(l);
|
|
131
|
+
};
|
|
132
|
+
// Advance to first non-welcome step programmatically — used by tests
|
|
133
|
+
// and by the "skip intro" flag (future).
|
|
134
|
+
api.jumpToProvider = () => {
|
|
135
|
+
s = { ...s, step: 'provider' };
|
|
136
|
+
notify();
|
|
137
|
+
};
|
|
138
|
+
// Advance from model to apikey step (used by runWizard when user
|
|
139
|
+
// confirms the model on step 3).
|
|
140
|
+
api.advanceToApikey = () => {
|
|
141
|
+
if (s.step === 'model') {
|
|
142
|
+
s = { ...s, step: 'apikey' };
|
|
143
|
+
notify();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
return api;
|
|
147
|
+
}
|
|
148
|
+
/** Convenience constants for tests + UI. */
|
|
149
|
+
export const API_KEY_OPTIONS = ['env', 'keystore', 'skip'];
|
|
150
|
+
export const WIZARD_STEPS = ORDER;
|
|
151
|
+
//# sourceMappingURL=useWizardState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWizardState.js","sourceRoot":"","sources":["../../../src/cli/wizard/useWizardState.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace/agentsMd.ts — AGENTS.MD auto-maintenance.
|
|
3
|
+
*
|
|
4
|
+
* Reads `.zelari/` artifacts and updates the project-root `AGENTS.MD`
|
|
5
|
+
* file in place using marker-delimited sections. Sections outside
|
|
6
|
+
* markers (e.g. "Overview") are NEVER touched. Sections inside
|
|
7
|
+
* markers are auto-curated from workspace artifacts.
|
|
8
|
+
*
|
|
9
|
+
* Idempotency: if the generated section content matches what's already
|
|
10
|
+
* in the file, no write happens → no spurious git diff.
|
|
11
|
+
*
|
|
12
|
+
* Fail-safe: if AGENTS.MD has been manually edited and the markers are
|
|
13
|
+
* missing, the entire file is treated as manual and no auto-update
|
|
14
|
+
* is performed. The user can re-enable by re-adding the markers.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/plans/2026-07-01-council-workspace-cli-stubs.md
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
19
|
+
import { createHash } from 'node:crypto';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { readFile } from 'node:fs/promises';
|
|
22
|
+
import { projectName as deriveProjectName } from './paths.js';
|
|
23
|
+
/** All auto-managed section ids in canonical order. */
|
|
24
|
+
export const AUTO_SECTIONS = [
|
|
25
|
+
'tech-stack',
|
|
26
|
+
'decisions',
|
|
27
|
+
'conventions',
|
|
28
|
+
'build',
|
|
29
|
+
'open-questions',
|
|
30
|
+
];
|
|
31
|
+
// ── Markers ───────────────────────────────────────────────────────────
|
|
32
|
+
const MARKER_OPEN = (id) => `<!-- zelari:auto:start section="${id}" -->`;
|
|
33
|
+
const MARKER_CLOSE = (id) => `<!-- zelari:auto:end section="${id}" -->`;
|
|
34
|
+
/** Read package.json from the project root. */
|
|
35
|
+
async function readPackageJson(projectRoot) {
|
|
36
|
+
const path = join(projectRoot, 'package.json');
|
|
37
|
+
if (!existsSync(path))
|
|
38
|
+
return null;
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Generate the tech-stack section from package.json. */
|
|
47
|
+
async function genTechStack(ctx) {
|
|
48
|
+
const pkg = await readPackageJson(ctx.projectRoot);
|
|
49
|
+
if (!pkg)
|
|
50
|
+
return '_No package.json found._';
|
|
51
|
+
const runtime = Object.entries(pkg.dependencies ?? {})
|
|
52
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
53
|
+
.map(([k, v]) => `- ${k} \`${v}\``)
|
|
54
|
+
.join('\n');
|
|
55
|
+
const dev = Object.entries(pkg.devDependencies ?? {})
|
|
56
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
57
|
+
.map(([k, v]) => `- ${k} \`${v}\``)
|
|
58
|
+
.join('\n');
|
|
59
|
+
return [
|
|
60
|
+
'<!-- Auto-derived from package.json -->',
|
|
61
|
+
'',
|
|
62
|
+
'**Runtime:**',
|
|
63
|
+
runtime || '_none_',
|
|
64
|
+
'',
|
|
65
|
+
'**Dev:**',
|
|
66
|
+
dev || '_none_',
|
|
67
|
+
'',
|
|
68
|
+
].join('\n');
|
|
69
|
+
}
|
|
70
|
+
/** Generate the decisions section from `.zelari/decisions/`. */
|
|
71
|
+
async function genDecisions(ctx) {
|
|
72
|
+
const decisionsDir = join(ctx.rootDir, 'decisions');
|
|
73
|
+
if (!existsSync(decisionsDir))
|
|
74
|
+
return '_No ADRs yet._';
|
|
75
|
+
const files = ctx.storage.listMarkdown(decisionsDir).sort();
|
|
76
|
+
const accepted = [];
|
|
77
|
+
const proposed = [];
|
|
78
|
+
for (const file of files) {
|
|
79
|
+
const doc = ctx.storage.readIfExists(file);
|
|
80
|
+
if (!doc?.meta)
|
|
81
|
+
continue;
|
|
82
|
+
const line = `- **${doc.meta.id}** _(${doc.meta.status ?? 'proposed'})_`;
|
|
83
|
+
if (doc.meta.status === 'accepted')
|
|
84
|
+
accepted.push(line);
|
|
85
|
+
else
|
|
86
|
+
proposed.push(line);
|
|
87
|
+
}
|
|
88
|
+
if (accepted.length === 0 && proposed.length === 0)
|
|
89
|
+
return '_No ADRs yet._';
|
|
90
|
+
return [
|
|
91
|
+
'See `.zelari/decisions/` for full ADRs (context/decision/consequences).',
|
|
92
|
+
'',
|
|
93
|
+
'**Accepted:**',
|
|
94
|
+
...(accepted.length ? accepted : ['_none yet_']),
|
|
95
|
+
'',
|
|
96
|
+
'**Proposed:**',
|
|
97
|
+
...(proposed.length ? proposed : ['_none_']),
|
|
98
|
+
'',
|
|
99
|
+
].join('\n');
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Generate the conventions section.
|
|
103
|
+
* v1: extract from existing CLAUDE.MD / README.md if present; otherwise generic.
|
|
104
|
+
* Future: infer from code patterns via Caronte + Nettuno observations.
|
|
105
|
+
*/
|
|
106
|
+
async function genConventions(ctx) {
|
|
107
|
+
const lines = [];
|
|
108
|
+
// Try to detect from CLAUDE.md
|
|
109
|
+
const claudeMd = join(ctx.projectRoot, 'CLAUDE.MD');
|
|
110
|
+
if (existsSync(claudeMd)) {
|
|
111
|
+
const content = readFileSync(claudeMd, 'utf8');
|
|
112
|
+
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
113
|
+
if (match) {
|
|
114
|
+
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(match[0].trim());
|
|
117
|
+
lines.push('');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Generic Zelari Code conventions
|
|
121
|
+
lines.push('<!-- Zelari Code defaults -->');
|
|
122
|
+
lines.push('');
|
|
123
|
+
lines.push('- One tool definition per file in `src/main/core/tools/builtin/`');
|
|
124
|
+
lines.push('- Async-first; never block the event loop');
|
|
125
|
+
lines.push('- Zod schemas for all LLM tool args');
|
|
126
|
+
lines.push('- Single-task atomic commits; no batching');
|
|
127
|
+
lines.push('- Zero new heavy deps (lodash, immer, etc.) — use std lib');
|
|
128
|
+
lines.push('- Files ≤ 300 LOC preferred for new modules');
|
|
129
|
+
lines.push('');
|
|
130
|
+
return lines.join('\n');
|
|
131
|
+
}
|
|
132
|
+
/** Generate the build section from package.json scripts. */
|
|
133
|
+
async function genBuild(ctx) {
|
|
134
|
+
const pkg = await readPackageJson(ctx.projectRoot);
|
|
135
|
+
if (!pkg?.scripts)
|
|
136
|
+
return '_No scripts defined._';
|
|
137
|
+
const scriptLines = Object.entries(pkg.scripts)
|
|
138
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
139
|
+
.map(([k, v]) => `\`npm run ${k}\` — ${v.length > 80 ? v.slice(0, 77) + '…' : v}`)
|
|
140
|
+
.join('\n');
|
|
141
|
+
return [
|
|
142
|
+
'<!-- Auto-derived from package.json scripts -->',
|
|
143
|
+
'',
|
|
144
|
+
scriptLines,
|
|
145
|
+
'',
|
|
146
|
+
].join('\n');
|
|
147
|
+
}
|
|
148
|
+
/** Generate the open-questions section from `.zelari/risks.md` info-level items. */
|
|
149
|
+
async function genOpenQuestions(ctx) {
|
|
150
|
+
const path = join(ctx.rootDir, 'risks.md');
|
|
151
|
+
if (!existsSync(path))
|
|
152
|
+
return '_No open questions._';
|
|
153
|
+
const content = readFileSync(path, 'utf8');
|
|
154
|
+
// Extract items that look like info-level questions
|
|
155
|
+
const lines = content.split('\n');
|
|
156
|
+
const questions = [];
|
|
157
|
+
let currentTitle = '';
|
|
158
|
+
let inInfo = false;
|
|
159
|
+
for (const line of lines) {
|
|
160
|
+
if (line.startsWith('## ')) {
|
|
161
|
+
currentTitle = line.slice(3).trim();
|
|
162
|
+
inInfo = currentTitle.toLowerCase().includes('info');
|
|
163
|
+
}
|
|
164
|
+
else if (inInfo && line.startsWith('- ')) {
|
|
165
|
+
questions.push(line);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (questions.length === 0)
|
|
169
|
+
return '_No open questions._';
|
|
170
|
+
return [
|
|
171
|
+
'<!-- Auto-derived from `.zelari/risks.md` info-level items -->',
|
|
172
|
+
'',
|
|
173
|
+
...questions,
|
|
174
|
+
'',
|
|
175
|
+
].join('\n');
|
|
176
|
+
}
|
|
177
|
+
/** Map section id to its generator. */
|
|
178
|
+
const GENERATORS = {
|
|
179
|
+
'tech-stack': genTechStack,
|
|
180
|
+
'decisions': genDecisions,
|
|
181
|
+
'conventions': genConventions,
|
|
182
|
+
'build': genBuild,
|
|
183
|
+
'open-questions': genOpenQuestions,
|
|
184
|
+
};
|
|
185
|
+
// ── File parser / writer ─────────────────────────────────────────────
|
|
186
|
+
/** Parse AGENTS.MD into manual content + per-section content. */
|
|
187
|
+
export function parseAgentsMd(content) {
|
|
188
|
+
const sections = new Map();
|
|
189
|
+
let cursor = 0;
|
|
190
|
+
for (const id of AUTO_SECTIONS) {
|
|
191
|
+
const startMarker = MARKER_OPEN(id);
|
|
192
|
+
const endMarker = MARKER_CLOSE(id);
|
|
193
|
+
const startIdx = content.indexOf(startMarker, cursor);
|
|
194
|
+
if (startIdx < 0)
|
|
195
|
+
continue;
|
|
196
|
+
const endIdx = content.indexOf(endMarker, startIdx);
|
|
197
|
+
if (endIdx < 0)
|
|
198
|
+
continue;
|
|
199
|
+
const innerStart = startIdx + startMarker.length;
|
|
200
|
+
const innerContent = content.slice(innerStart, endIdx).replace(/^\n/, '').replace(/\n$/, '');
|
|
201
|
+
sections.set(id, {
|
|
202
|
+
id,
|
|
203
|
+
startMarker,
|
|
204
|
+
endMarker,
|
|
205
|
+
content: innerContent,
|
|
206
|
+
});
|
|
207
|
+
cursor = endIdx + endMarker.length;
|
|
208
|
+
}
|
|
209
|
+
// Manual content = the file minus all auto-managed sections.
|
|
210
|
+
// We rebuild it by walking through and replacing each section block.
|
|
211
|
+
let manual = content;
|
|
212
|
+
for (const section of sections.values()) {
|
|
213
|
+
const block = `${section.startMarker}\n${section.content}\n${section.endMarker}`;
|
|
214
|
+
manual = manual.replace(block, '');
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
manualBlocks: { before: '', after: manual },
|
|
218
|
+
sections,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** Serialize AGENTS.MD from manual content + auto sections. */
|
|
222
|
+
export function serializeAgentsMd(manualContent, sections) {
|
|
223
|
+
// Insert each section into the manual content at its original position
|
|
224
|
+
// if possible; otherwise append at the end.
|
|
225
|
+
const out = [];
|
|
226
|
+
const lines = manualContent.split('\n');
|
|
227
|
+
let cursor = 0;
|
|
228
|
+
// Find a good insertion point: after the first heading + first paragraph.
|
|
229
|
+
// For v1: just append sections at the end of the file.
|
|
230
|
+
out.push(...lines);
|
|
231
|
+
for (const id of AUTO_SECTIONS) {
|
|
232
|
+
const content = sections.get(id);
|
|
233
|
+
if (!content)
|
|
234
|
+
continue;
|
|
235
|
+
out.push('');
|
|
236
|
+
out.push(`## ${titleCase(id)}`);
|
|
237
|
+
out.push('');
|
|
238
|
+
out.push(MARKER_OPEN(id));
|
|
239
|
+
out.push(content);
|
|
240
|
+
out.push(MARKER_CLOSE(id));
|
|
241
|
+
}
|
|
242
|
+
return out.join('\n').replace(/\n{3,}/g, '\n\n').trim() + '\n';
|
|
243
|
+
}
|
|
244
|
+
function titleCase(id) {
|
|
245
|
+
return id.split('-').map((w) => w[0].toUpperCase() + w.slice(1)).join(' ');
|
|
246
|
+
}
|
|
247
|
+
// ── Public API ────────────────────────────────────────────────────────
|
|
248
|
+
/**
|
|
249
|
+
* Update AGENTS.MD based on current workspace state.
|
|
250
|
+
* Returns whether the file was actually changed (idempotent).
|
|
251
|
+
*/
|
|
252
|
+
export async function updateAgentsMd(ctx, projectRoot) {
|
|
253
|
+
const agentsPath = join(projectRoot, 'AGENTS.MD');
|
|
254
|
+
// Fail-safe: if AGENTS.MD exists but no markers at all → manual file, skip.
|
|
255
|
+
if (existsSync(agentsPath)) {
|
|
256
|
+
const content = readFileSync(agentsPath, 'utf8');
|
|
257
|
+
const hasAnyMarker = AUTO_SECTIONS.some((id) => content.includes(MARKER_OPEN(id)));
|
|
258
|
+
if (!hasAnyMarker) {
|
|
259
|
+
return {
|
|
260
|
+
changed: false,
|
|
261
|
+
sections: [],
|
|
262
|
+
reason: 'AGENTS.MD exists without zelari markers — treating as manual file, skipping auto-update.',
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Generate content for all sections.
|
|
267
|
+
const newSections = new Map();
|
|
268
|
+
for (const id of AUTO_SECTIONS) {
|
|
269
|
+
newSections.set(id, await GENERATORS[id](ctx));
|
|
270
|
+
}
|
|
271
|
+
// Parse existing manual content (if file exists).
|
|
272
|
+
let manualContent = '';
|
|
273
|
+
if (existsSync(agentsPath)) {
|
|
274
|
+
const { manualBlocks } = parseAgentsMd(readFileSync(agentsPath, 'utf8'));
|
|
275
|
+
manualContent = manualBlocks.after;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// First-time creation: build a minimal skeleton.
|
|
279
|
+
const projectName = deriveProjectName(projectRoot);
|
|
280
|
+
manualContent = [
|
|
281
|
+
`# AGENTS.MD — ${projectName}`,
|
|
282
|
+
'',
|
|
283
|
+
'> Auto-curated by Zelari Code council. Run `/council` to refresh.',
|
|
284
|
+
'> See `.zelari/` for raw decision log.',
|
|
285
|
+
'',
|
|
286
|
+
'## Overview',
|
|
287
|
+
'',
|
|
288
|
+
'_Free-form project description. This section is manual and preserved across updates._',
|
|
289
|
+
'',
|
|
290
|
+
].join('\n');
|
|
291
|
+
}
|
|
292
|
+
// Check idempotency: compare each section's hash.
|
|
293
|
+
const oldContent = existsSync(agentsPath) ? readFileSync(agentsPath, 'utf8') : '';
|
|
294
|
+
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
295
|
+
const changedSections = [];
|
|
296
|
+
for (const id of AUTO_SECTIONS) {
|
|
297
|
+
const oldHash = oldSections.get(id)?.content ? hash(oldSections.get(id).content) : null;
|
|
298
|
+
const newHash = hash(newSections.get(id));
|
|
299
|
+
if (oldHash !== newHash)
|
|
300
|
+
changedSections.push(id);
|
|
301
|
+
}
|
|
302
|
+
if (changedSections.length === 0) {
|
|
303
|
+
return { changed: false, sections: [] };
|
|
304
|
+
}
|
|
305
|
+
// Serialize and write.
|
|
306
|
+
const newContent = serializeAgentsMd(manualContent, newSections);
|
|
307
|
+
writeFileSync(agentsPath, newContent, 'utf8');
|
|
308
|
+
return { changed: true, sections: changedSections };
|
|
309
|
+
}
|
|
310
|
+
/** Hash a string to detect changes. */
|
|
311
|
+
function hash(s) {
|
|
312
|
+
return createHash('sha256').update(s).digest('hex').slice(0, 16);
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=agentsMd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentsMd.js","sourceRoot":"","sources":["../../../src/cli/workspace/agentsMd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace/index.ts — Public API barrel for the council workspace subsystem.
|
|
3
|
+
*
|
|
4
|
+
* The council workspace persists council output (plan/risks/decisions/reviews/docs)
|
|
5
|
+
* to `.zelari/` at the project root and auto-curates `AGENTS.MD` from the
|
|
6
|
+
* collected artifacts. This is the CLI replacement for the Electron-only
|
|
7
|
+
* `ctx.createPhase`/etc. injection that AnathemaBrain uses.
|
|
8
|
+
*
|
|
9
|
+
* @see docs/plans/2026-07-01-council-workspace-cli-stubs.md
|
|
10
|
+
* @module cli/workspace
|
|
11
|
+
*/
|
|
12
|
+
// Storage primitives — YAML frontmatter parser/serializer + per-key mutex.
|
|
13
|
+
export { Storage, workspaceMutex, parseFrontmatter, serializeFrontmatter, parseYaml, serializeYaml, } from './storage.js';
|
|
14
|
+
// Filesystem paths + workspace root resolution.
|
|
15
|
+
export { resolveWorkspaceRoot, workspaceFile, workspaceArtifact, projectName, WORKSPACE_SUBDIRS, } from './paths.js';
|
|
16
|
+
// Tool stubs — the 9 council workspace tools as filesystem-backed implementations.
|
|
17
|
+
export { createWorkspaceContext, createWorkspaceStubs, } from './stubs.js';
|
|
18
|
+
// Tool registry — wraps stubs as EnhancedToolDefinition[] for the harness.
|
|
19
|
+
export { createWorkspaceToolRegistry, } from './toolRegistry.js';
|
|
20
|
+
// AGENTS.MD auto-maintenance — marker-delimited sections + idempotent writes.
|
|
21
|
+
export { updateAgentsMd, parseAgentsMd, serializeAgentsMd, AUTO_SECTIONS, } from './agentsMd.js';
|
|
22
|
+
// Post-council hook — orchestrates `updateAgentsMd` after every council run.
|
|
23
|
+
export { runPostCouncilHook, } from './postCouncilHook.js';
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/workspace/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,OAAO,EACL,OAAO,EACP,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,gDAAgD;AAChD,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAYpB,mFAAmF;AACnF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,2EAA2E;AAC3E,OAAO,EACL,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAE3B,8EAA8E;AAC9E,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB,6EAA6E;AAC7E,OAAO,EACL,kBAAkB,GACnB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace/paths.ts — Workspace root resolution.
|
|
3
|
+
*
|
|
4
|
+
* Default: project-local `.zelari/` (auto-gitignored).
|
|
5
|
+
* Fallback: `~/.zelari-code/workspace/<project-hash>/` if cwd not writable.
|
|
6
|
+
*
|
|
7
|
+
* The fallback ensures the workspace always works — even in read-only
|
|
8
|
+
* directories (Docker containers, system dirs, etc.).
|
|
9
|
+
*/
|
|
10
|
+
import { mkdirSync, writeFileSync, existsSync, accessSync, constants, realpathSync } from 'node:fs';
|
|
11
|
+
import { join, basename } from 'node:path';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { createHash } from 'node:crypto';
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the workspace root. Returns the first writable option:
|
|
16
|
+
* 1. `<cwd>/.zelari/` if cwd is writable
|
|
17
|
+
* 2. `~/.zelari-code/workspace/<project-hash>/` otherwise
|
|
18
|
+
*
|
|
19
|
+
* Side effect: creates the directory + auto-gitignore if missing.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
22
|
+
const candidates = [
|
|
23
|
+
join(projectRoot, '.zelari'),
|
|
24
|
+
join(homedir(), '.zelari-code', 'workspace', hashProject(projectRoot)),
|
|
25
|
+
];
|
|
26
|
+
for (const candidate of candidates) {
|
|
27
|
+
if (isWritableDir(projectRoot) || candidate !== candidates[0]) {
|
|
28
|
+
ensureWorkspaceDir(candidate);
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Last resort: first candidate (will likely fail on write but we tried)
|
|
33
|
+
ensureWorkspaceDir(candidates[0]);
|
|
34
|
+
return candidates[0];
|
|
35
|
+
}
|
|
36
|
+
/** Hash a project path to a stable short id (used in global fallback path). */
|
|
37
|
+
function hashProject(projectPath) {
|
|
38
|
+
return createHash('sha1').update(realpathSync(projectPath)).digest('hex').slice(0, 12);
|
|
39
|
+
}
|
|
40
|
+
/** Check if a directory is writable (creates if missing). */
|
|
41
|
+
function isWritableDir(dir) {
|
|
42
|
+
try {
|
|
43
|
+
if (!existsSync(dir))
|
|
44
|
+
return false; // don't create, just check
|
|
45
|
+
accessSync(dir, constants.W_OK);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Create workspace dir + auto-gitignore (if inside a git repo). */
|
|
53
|
+
function ensureWorkspaceDir(workspaceDir) {
|
|
54
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
55
|
+
// Auto-gitignore ONLY if workspace is project-local AND inside a git repo
|
|
56
|
+
if (workspaceDir.endsWith('/.zelari') && existsSync(join(workspaceDir, '..', '.git'))) {
|
|
57
|
+
const gitignorePath = join(workspaceDir, '.gitignore');
|
|
58
|
+
if (!existsSync(gitignorePath)) {
|
|
59
|
+
writeFileSync(gitignorePath, '*\n!.gitignore\n');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** All standard workspace subdirs. */
|
|
64
|
+
export const WORKSPACE_SUBDIRS = [
|
|
65
|
+
'decisions',
|
|
66
|
+
'reviews',
|
|
67
|
+
'docs',
|
|
68
|
+
'risks', // file, not dir
|
|
69
|
+
'plan.md', // file, not dir
|
|
70
|
+
'workspace.json', // file, index
|
|
71
|
+
];
|
|
72
|
+
/** Get the absolute path to a standard workspace file. */
|
|
73
|
+
export function workspaceFile(rootDir, kind) {
|
|
74
|
+
switch (kind) {
|
|
75
|
+
case 'plan': return join(rootDir, 'plan.md');
|
|
76
|
+
case 'risks': return join(rootDir, 'risks.md');
|
|
77
|
+
case 'index': return join(rootDir, 'workspace.json');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Get the absolute path to a numbered artifact in a subdir. */
|
|
81
|
+
export function workspaceArtifact(rootDir, subdir, slug) {
|
|
82
|
+
return join(rootDir, subdir, `${slug}.md`);
|
|
83
|
+
}
|
|
84
|
+
/** Get human-readable project name from path (basename). */
|
|
85
|
+
export function projectName(projectRoot = process.cwd()) {
|
|
86
|
+
return basename(realpathSync(projectRoot));
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/cli/workspace/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace/postCouncilHook.ts — Run the AGENTS.MD auto-maintenance
|
|
3
|
+
* after every council run completes.
|
|
4
|
+
*
|
|
5
|
+
* Used by `councilDispatcher` (Phase 4 wiring) to keep AGENTS.MD in sync
|
|
6
|
+
* with the latest `.zelari/` artifacts.
|
|
7
|
+
*/
|
|
8
|
+
import { updateAgentsMd } from './agentsMd.js';
|
|
9
|
+
/**
|
|
10
|
+
* Run the post-council AGENTS.MD maintenance hook.
|
|
11
|
+
* Returns info about what happened so the CLI can show a one-line summary
|
|
12
|
+
* to the user (e.g. "AGENTS.MD updated: 2 sections changed (decisions, conventions)").
|
|
13
|
+
*
|
|
14
|
+
* Respects `ZELARI_AGENTS_MD=0` env var to opt out.
|
|
15
|
+
*/
|
|
16
|
+
export async function runPostCouncilHook(ctx) {
|
|
17
|
+
if (process.env['ZELARI_AGENTS_MD'] === '0') {
|
|
18
|
+
return { ran: false, changed: false, sections: [], reason: 'ZELARI_AGENTS_MD=0 (disabled)' };
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = await updateAgentsMd(ctx, ctx.projectRoot);
|
|
22
|
+
return {
|
|
23
|
+
ran: true,
|
|
24
|
+
changed: result.changed,
|
|
25
|
+
sections: result.sections,
|
|
26
|
+
...(result.reason ? { reason: result.reason } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return {
|
|
31
|
+
ran: false,
|
|
32
|
+
changed: false,
|
|
33
|
+
sections: [],
|
|
34
|
+
reason: `error: ${err instanceof Error ? err.message : String(err)}`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=postCouncilHook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postCouncilHook.js","sourceRoot":"","sources":["../../../src/cli/workspace/postCouncilHook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAU/C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAqB;IAC5D,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,KAAK,GAAG,EAAE,CAAC;QAC5C,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;IAC/F,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QAC1D,OAAO;YACL,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,GAAG,EAAE,KAAK;YACV,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACrE,CAAC;IACJ,CAAC;AACH,CAAC"}
|