agentlas 1.0.46 → 1.0.48
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 +33 -0
- package/README.md +7 -7
- package/engine/acp/server.cjs +279 -0
- package/engine/agentlas-capabilities.cjs +4 -2
- package/engine/agentlas-core-harness.cjs +18 -0
- package/engine/agentlas-i18n.cjs +8 -8
- package/engine/agentlas-input.cjs +3 -2
- package/engine/agentlas-native-host.cjs +130 -11
- package/engine/agentlas-onboard.cjs +9 -3
- package/engine/agentlas-permissions.cjs +5 -1
- package/engine/agentlas-workforce.cjs +81 -24
- package/engine/agents/router.cjs +4 -2
- package/engine/architecture.data.json +6 -30
- package/engine/automation/daemon.cjs +3 -7
- package/engine/bootstrap-schema.sql +216 -191
- package/engine/browser/cdp.cjs +10 -4
- package/engine/cloud-assets/commands.cjs +1 -1
- package/engine/cloud-assets/package.cjs +161 -45
- package/engine/commands/acp.cjs +45 -0
- package/engine/commands/billing.cjs +2 -2
- package/engine/commands/call.cjs +4 -0
- package/engine/commands/context.cjs +14 -3
- package/engine/commands/doctor.cjs +8 -4
- package/engine/commands/graph.cjs +46 -54
- package/engine/commands/index.cjs +2 -0
- package/engine/commands/search.cjs +2 -2
- package/engine/commands/workforce.cjs +11 -0
- package/engine/core/desktop-core.cjs +93 -1
- package/engine/firms/orchestrate.cjs +32 -1
- package/engine/graph/interview.cjs +2 -11
- package/engine/graph/vocabulary.generated.cjs +1 -1
- package/engine/hephaestus/runtime.cjs +2 -6
- package/engine/project/memory-context.cjs +20 -7
- package/engine/project/seed.cjs +46 -31
- package/engine/project/state.cjs +8 -1
- package/engine/runtimes/acp-driver.cjs +96 -0
- package/engine/runtimes/auth-evidence.cjs +6 -0
- package/engine/runtimes/detect.cjs +3 -13
- package/engine/runtimes/kinds.cjs +84 -0
- package/engine/runtimes/resolve.cjs +67 -14
- package/engine/sessions/prompt.cjs +2 -2
- package/engine/ui/commands-catalog.cjs +2 -0
- package/engine/ui/palette.cjs +2 -1
- package/engine/ui/repl.cjs +4 -3
- package/engine/ui/shell.cjs +43 -5
- package/engine/vendor/desktop-core.manifest.json +5 -5
- package/engine/workforce/capture.cjs +55 -10
- package/engine/workforce/deps.cjs +2 -2
- package/engine/workforce/local-core-transport.cjs +13 -19
- package/package.json +2 -1
- package/engine/project/super-ontology-seed.json +0 -3288
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
* graph — 저장된 자동화 그래프를 터미널에서 보고
|
|
3
|
+
* graph — 저장된 자동화 그래프를 터미널에서 보고 vendored Desktop Core로 직접 실행한다.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* (표시해 놓고 "실행했습니다"라고 답하면, 사용자는 돌아가지 않은 자동화를 돌아갔다고 믿는다.)
|
|
5
|
+
* `graph run`은 데스크탑 앱/스케줄러를 깨우지 않는다. npm 패키지에 포함된 동일 Core의
|
|
6
|
+
* runGraph(automation, graph, opts)를 현재 Node 프로세스에서 호출하고 실제 결과/오류를 반환한다.
|
|
8
7
|
*
|
|
9
8
|
* 공유 DB(데스크탑과 동일 파일)를 읽고 쓴다. 스키마 소유권은 데스크탑에 있으므로
|
|
10
9
|
* 여기서는 컬럼을 만들지 않고, 없는 컬럼은 없는 대로 다룬다.
|
|
@@ -12,8 +11,8 @@
|
|
|
12
11
|
const readline = require("node:readline");
|
|
13
12
|
const fs = require("node:fs");
|
|
14
13
|
const path = require("node:path");
|
|
15
|
-
const crypto = require("node:crypto");
|
|
16
14
|
const pkgLib = require("../graph/package.cjs");
|
|
15
|
+
const desktopCore = require("../core/desktop-core.cjs");
|
|
17
16
|
|
|
18
17
|
function graphRows(ctx, db) {
|
|
19
18
|
if (!ctx.tableExists(db, "automations")) return [];
|
|
@@ -440,23 +439,6 @@ function renderGraphTree(ctx, graph, en) {
|
|
|
440
439
|
}
|
|
441
440
|
}
|
|
442
441
|
|
|
443
|
-
/**
|
|
444
|
-
* 시작 값을 대기열에 넣는다. 데스크탑 스키마 v88의 automation_run_inputs를 쓴다.
|
|
445
|
-
* 자리가 아직 없는(구버전) 데스크탑이면 false — 값이 전달된 것처럼 말하지 않기 위해서다.
|
|
446
|
-
*/
|
|
447
|
-
function enqueueRunInput(ctx, db, automationId, payload) {
|
|
448
|
-
if (!ctx.tableExists || !ctx.tableExists(db, "automation_run_inputs")) return false;
|
|
449
|
-
try {
|
|
450
|
-
db.prepare(
|
|
451
|
-
`INSERT INTO automation_run_inputs (id, automation_id, payload_json, requested_by, created_at)
|
|
452
|
-
VALUES (?, ?, ?, ?, ?)`,
|
|
453
|
-
).run(crypto.randomUUID(), automationId, JSON.stringify(payload), "terminal", new Date().toISOString());
|
|
454
|
-
return true;
|
|
455
|
-
} catch {
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
442
|
function ask(rl, question) {
|
|
461
443
|
return new Promise((resolve) => rl.question(question, (answer) => resolve(String(answer || "").trim())));
|
|
462
444
|
}
|
|
@@ -475,6 +457,12 @@ async function runGraph(ctx, needle, flags) {
|
|
|
475
457
|
return 1;
|
|
476
458
|
}
|
|
477
459
|
const graph = parseGraph(row);
|
|
460
|
+
if (!graph || !Array.isArray(graph.edges)) {
|
|
461
|
+
ctx.err(en
|
|
462
|
+
? `"${row.name}" has no executable visual graph.`
|
|
463
|
+
: `"${row.name}"에는 실행할 수 있는 시각적 그래프가 없습니다.`);
|
|
464
|
+
return 1;
|
|
465
|
+
}
|
|
478
466
|
const kind = triggerKind(row, graph);
|
|
479
467
|
|
|
480
468
|
if (!flags.yes && process.stdin.isTTY) {
|
|
@@ -518,38 +506,42 @@ async function runGraph(ctx, needle, flags) {
|
|
|
518
506
|
return 1;
|
|
519
507
|
}
|
|
520
508
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
).run(now, row.id);
|
|
526
|
-
if (updated.changes !== 1) {
|
|
527
|
-
ctx.err(en
|
|
528
|
-
? `"${row.name}" is switched off, so a run request would sit unread. Turn it on in the desktop app first.`
|
|
529
|
-
: `"${row.name}"이(가) 꺼져 있어 실행 요청이 읽히지 않습니다. 데스크탑 앱에서 먼저 켜 주세요.`);
|
|
509
|
+
const core = ctx.desktopCore || desktopCore.loadDesktopCore();
|
|
510
|
+
if (!core || core.error || typeof core.runGraph !== "function") {
|
|
511
|
+
const cause = core?.error instanceof Error ? core.error.message : "vendored Desktop Core is unavailable";
|
|
512
|
+
ctx.err(JSON.stringify({ ok: false, error: cause }, null, 2));
|
|
530
513
|
return 1;
|
|
531
514
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
515
|
+
let automation = null;
|
|
516
|
+
try {
|
|
517
|
+
automation = typeof core.require === "function"
|
|
518
|
+
? core.require("store/automations").getAutomation(row.id)
|
|
519
|
+
: null;
|
|
520
|
+
} catch { /* test/fallback row below */ }
|
|
521
|
+
automation ||= {
|
|
522
|
+
id: row.id,
|
|
523
|
+
name: row.name,
|
|
524
|
+
scheduleHuman: row.schedule,
|
|
525
|
+
targetType: row.target_type,
|
|
526
|
+
targetId: row.target_id,
|
|
527
|
+
enabled: Boolean(row.enabled),
|
|
528
|
+
createdBy: row.created_by || "terminal",
|
|
529
|
+
graph,
|
|
530
|
+
};
|
|
531
|
+
automation.graph = graph;
|
|
532
|
+
const initialVars = requirement && flags.input ? { [requirement.varName]: flags.input } : {};
|
|
533
|
+
try {
|
|
534
|
+
const result = await core.runGraph(automation, graph, { initialVars });
|
|
535
|
+
ctx.out(JSON.stringify(result, null, 2));
|
|
536
|
+
return result && result.ok === true ? 0 : 1;
|
|
537
|
+
} catch (error) {
|
|
538
|
+
ctx.err(JSON.stringify({
|
|
539
|
+
ok: false,
|
|
540
|
+
...(error && typeof error.code === "string" ? { code: error.code } : {}),
|
|
541
|
+
error: error instanceof Error ? error.message : String(error),
|
|
542
|
+
}, null, 2));
|
|
543
|
+
return 1;
|
|
551
544
|
}
|
|
552
|
-
return 0;
|
|
553
545
|
}
|
|
554
546
|
|
|
555
547
|
|
|
@@ -1119,7 +1111,7 @@ async function run(ctx, args = []) {
|
|
|
1119
1111
|
ctx.out(en ? ' new "<what you want>" build one by talking it through' : ' new "<하고 싶은 일>" 말로 설명하면 만들어 줍니다');
|
|
1120
1112
|
ctx.out(en ? " list what is saved" : " list 저장된 것 목록");
|
|
1121
1113
|
ctx.out(en ? " show \"<name>\" steps, wiring, and problems" : " show \"<이름>\" 단계·배선·문제점");
|
|
1122
|
-
ctx.out(en ? " run \"<name>\" [--input \"<value>\"]
|
|
1114
|
+
ctx.out(en ? " run \"<name>\" [--input \"<value>\"] run locally with the included Desktop Core" : " run \"<이름>\" [--input \"<값>\"] 포함된 Desktop Core로 로컬 실행");
|
|
1123
1115
|
ctx.out(en ? " export \"<name>\" [file] write a shareable package file" : " export \"<이름>\" [파일] 남에게 줄 수 있는 파일로 저장");
|
|
1124
1116
|
ctx.out(en ? " inspect <file> read a package file before installing" : " inspect <파일> 설치 전에 패키지 파일 확인");
|
|
1125
1117
|
ctx.out(en ? " install <file> [--name \"<new name>\"] install a package file" : " install <파일> [--name \"<새 이름>\"] 패키지 파일 설치");
|
|
@@ -1179,8 +1171,8 @@ async function run(ctx, args = []) {
|
|
|
1179
1171
|
]);
|
|
1180
1172
|
if (AUTHORING.has(sub)) {
|
|
1181
1173
|
ctx.err(en
|
|
1182
|
-
? `Graphs are built and edited in the Agentlas desktop app (Automation → the graph canvas). The terminal can
|
|
1183
|
-
: `그래프를 만들고 고치는 일은 Agentlas 데스크탑 앱에서 합니다(자동화 → 그래프 화면). 터미널에서는 저장된 그래프를 보고
|
|
1174
|
+
? `Graphs are built and edited in the Agentlas desktop app (Automation → the graph canvas). The terminal can inspect saved graphs and run them locally with the included Desktop Core.`
|
|
1175
|
+
: `그래프를 만들고 고치는 일은 Agentlas 데스크탑 앱에서 합니다(자동화 → 그래프 화면). 터미널에서는 저장된 그래프를 보고 포함된 Desktop Core로 로컬 실행할 수 있습니다.`);
|
|
1184
1176
|
ctx.err(ctx.ui.dim(en
|
|
1185
1177
|
? `Here you can: list, show <name>, run <name>, export <name>, inspect <file>, install <file>.`
|
|
1186
1178
|
: `여기서 되는 것: list, show <이름>, run <이름>, export <이름>, inspect <파일>, install <파일>.`));
|
|
@@ -34,6 +34,8 @@ const COMMANDS = {
|
|
|
34
34
|
plugin: () => require("./plugin.cjs"),
|
|
35
35
|
automation: () => require("./automation.cjs"),
|
|
36
36
|
native: () => require("./native.cjs"),
|
|
37
|
+
// Agentlas as an ACP agent for editors (Zed, JetBrains, …) — PRD 2026-08-15 B-3.
|
|
38
|
+
acp: () => require("./acp.cjs"),
|
|
37
39
|
multimodal: () => require("./multimodal.cjs"),
|
|
38
40
|
document: () => require("./document.cjs"),
|
|
39
41
|
workforce: () => require("./workforce.cjs"),
|
|
@@ -27,8 +27,8 @@ async function run(ctx, args) {
|
|
|
27
27
|
|
|
28
28
|
let result;
|
|
29
29
|
try {
|
|
30
|
-
// Hub 파라미터 이름은 `q` — 데스크탑 mcp-source.ts와 동일하게 q
|
|
31
|
-
result = await callHubTool("marketplace.search_agents", { q: query,
|
|
30
|
+
// Hub 파라미터 이름은 `q` — 데스크탑 mcp-source.ts와 동일하게 q만 전송.
|
|
31
|
+
result = await callHubTool("marketplace.search_agents", { q: query, limit });
|
|
32
32
|
} catch (e) {
|
|
33
33
|
ctx.err(e instanceof HubError ? e.message : `Marketplace connection failed: ${(e && e.message) || e}`);
|
|
34
34
|
return 1;
|
|
@@ -75,6 +75,11 @@ async function dispatch(ctx, command, args) {
|
|
|
75
75
|
permission,
|
|
76
76
|
`terminal-${command}`,
|
|
77
77
|
) || cwd;
|
|
78
|
+
// 과금 사전 고지 — 이 표면은 서버가 청구 시 확정하는 가격을 미리 모르므로
|
|
79
|
+
// 숫자를 지어내지 않고 사실만 말한다(공개 Hub 호출=크레딧 소모, 장기대여=0).
|
|
80
|
+
ctx.out(ctx.lang !== "en"
|
|
81
|
+
? "ℹ 공개 Hub 에이전트·팀 호출은 크레딧이 소모됩니다(활성 장기대여 중에는 0). 잔액 확인: agentlas billing"
|
|
82
|
+
: "ℹ Public Hub agent/team calls consume credits (0 while a day-lease is active). Check balance: agentlas billing");
|
|
78
83
|
const runtime = workforceRuntime({ lang: ctx.lang, out: ctx.out, uiInstance: ctx.uiInstance });
|
|
79
84
|
const result = await runtime.cmdWorkforce(db, rest, runtimeOverride, {
|
|
80
85
|
cwd,
|
|
@@ -124,6 +129,12 @@ async function dispatch(ctx, command, args) {
|
|
|
124
129
|
const cwd = projectCwd();
|
|
125
130
|
const permission = resolvePermission(ctx);
|
|
126
131
|
const projectPath = ensureTerminalProjectForExecutionCli(db, cwd, permission, `terminal-${command}`) || cwd;
|
|
132
|
+
// 과금 사전 고지 — local 스코프는 원격 과금이 없다.
|
|
133
|
+
if (sourceScope !== "local") {
|
|
134
|
+
ctx.out(ko
|
|
135
|
+
? "ℹ 공개 Hub 에이전트·팀 호출은 크레딧이 소모됩니다(활성 장기대여 중에는 0). 잔액 확인: agentlas billing"
|
|
136
|
+
: "ℹ Public Hub agent/team calls consume credits (0 while a day-lease is active). Check balance: agentlas billing");
|
|
137
|
+
}
|
|
127
138
|
const { createLocalCoreHubTool } = require("../workforce/local-core-transport.cjs");
|
|
128
139
|
const { createLocalCoreWorkforceRuntime } = require("../workforce/deps.cjs");
|
|
129
140
|
const transport = createLocalCoreHubTool({ sourceScope, projectDir: projectPath, cwd });
|
|
@@ -93,6 +93,37 @@ function findCoreRoot() {
|
|
|
93
93
|
* 밖이라 node_modules 디렉터리 walk-up으로 자연 해결되지 않는다 — 이 훅이 위치와 무관하게 잡는다.
|
|
94
94
|
*/
|
|
95
95
|
let _nativeHookInstalled = false;
|
|
96
|
+
let _projectProvisioningHookInstalled = false;
|
|
97
|
+
|
|
98
|
+
function stripRetiredProjectProvisioningSource(source) {
|
|
99
|
+
const text = String(source || "");
|
|
100
|
+
if (!text.includes("SUPER_ONTOLOGY_")) return text;
|
|
101
|
+
const startMarker = " const secureWriteMissing = (filePath, content, _encoding) => {";
|
|
102
|
+
const endMarker = " preflightProjectProvisionTargets(identity);";
|
|
103
|
+
const start = text.indexOf(startMarker);
|
|
104
|
+
const end = start < 0 ? -1 : text.indexOf(endMarker, start);
|
|
105
|
+
if (start < 0 || end < 0) {
|
|
106
|
+
throw new Error("desktop_core_retired_surface_patch_failed: project provisioning layout changed");
|
|
107
|
+
}
|
|
108
|
+
return `${text.slice(0, start)} // Terminal keeps semantic ontology and career graph provisioning, but does not\n` +
|
|
109
|
+
` // load the retired project-file generation block from the Desktop bundle.\n${text.slice(end)}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function installRetiredProjectProvisioningHook() {
|
|
113
|
+
if (_projectProvisioningHookInstalled) return;
|
|
114
|
+
const Module = require("node:module");
|
|
115
|
+
const jsLoader = Module._extensions[".js"];
|
|
116
|
+
Module._extensions[".js"] = function loadTerminalDesktopCore(module, filename) {
|
|
117
|
+
if (filename.endsWith(path.join("electron", "memory", "project-files.js"))) {
|
|
118
|
+
const source = fs.readFileSync(filename, "utf8");
|
|
119
|
+
module._compile(stripRetiredProjectProvisioningSource(source), filename);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
return jsLoader(module, filename);
|
|
123
|
+
};
|
|
124
|
+
_projectProvisioningHookInstalled = true;
|
|
125
|
+
}
|
|
126
|
+
|
|
96
127
|
function installNativeModuleHook() {
|
|
97
128
|
if (_nativeHookInstalled) return;
|
|
98
129
|
const Module = require("node:module");
|
|
@@ -122,6 +153,7 @@ function loadDesktopCore() {
|
|
|
122
153
|
if (_cache !== undefined) return _cache;
|
|
123
154
|
const root = findCoreRoot();
|
|
124
155
|
if (!root) { _cache = null; return null; }
|
|
156
|
+
installRetiredProjectProvisioningHook();
|
|
125
157
|
installNativeModuleHook();
|
|
126
158
|
// 코어의 store 가 이 값을 모듈 로드 시점에 읽는다 — require 이전에 세팅해야 한다.
|
|
127
159
|
if (!process.env.AGENTLAS_STORE_PATH) process.env.AGENTLAS_STORE_PATH = dbPath();
|
|
@@ -146,6 +178,58 @@ function loadDesktopCore() {
|
|
|
146
178
|
return _cache;
|
|
147
179
|
}
|
|
148
180
|
|
|
181
|
+
/**
|
|
182
|
+
* 코어의 공용 ACP 러너(electron/runtime/acp.js)만 가볍게 로드한다 (PRD 2026-08-15 T-2).
|
|
183
|
+
* initStore·그래프 커널을 끌지 않고, electron 셰임과 네이티브 모듈 훅만 건 뒤 require 한다 —
|
|
184
|
+
* kimi/grok/cursor 실행에 DB가 필요 없기 때문. 코어가 없거나 acp.js가 없는 옛 코어면
|
|
185
|
+
* { error } 를 준다(정직한 부재; 조용한 폴백 금지).
|
|
186
|
+
*/
|
|
187
|
+
let _acpCache = undefined;
|
|
188
|
+
function loadCoreAcpRuntime() {
|
|
189
|
+
if (_acpCache !== undefined) return _acpCache;
|
|
190
|
+
const root = findCoreRoot();
|
|
191
|
+
if (!root) { _acpCache = null; return null; }
|
|
192
|
+
const file = path.join(root, "electron", "runtime", "acp.js");
|
|
193
|
+
if (!fs.existsSync(file)) { _acpCache = { root, error: new Error("desktop core predates the ACP runner (no electron/runtime/acp.js)") }; return _acpCache; }
|
|
194
|
+
try {
|
|
195
|
+
installRetiredProjectProvisioningHook();
|
|
196
|
+
installNativeModuleHook();
|
|
197
|
+
const mod = require(file);
|
|
198
|
+
_acpCache = { root, module: mod };
|
|
199
|
+
} catch (e) {
|
|
200
|
+
_acpCache = { root, error: e };
|
|
201
|
+
}
|
|
202
|
+
return _acpCache;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 코어의 **공유 순수 모듈**(dist/shared/*)만 가볍게 로드한다 (예: "agent-control-blocks").
|
|
207
|
+
* shared/* 는 electron·DB 의존이 없는 순수 함수 모듈이라 initStore·그래프 커널·셰임 없이
|
|
208
|
+
* require 만 한다. 코어가 없으면 null, 그 모듈이 없는 옛 벤더 번들이면 { root, error } —
|
|
209
|
+
* 정직한 부재(조용한 폴백 금지는 호출부 계약; 표시 경로는 fail-open 해도 된다).
|
|
210
|
+
*/
|
|
211
|
+
const _sharedCache = new Map();
|
|
212
|
+
function loadCoreShared(rel) {
|
|
213
|
+
const key = String(rel || "").replace(/\.js$/, "");
|
|
214
|
+
if (_sharedCache.has(key)) return _sharedCache.get(key);
|
|
215
|
+
let result = null;
|
|
216
|
+
const root = findCoreRoot();
|
|
217
|
+
if (root) {
|
|
218
|
+
const file = path.join(root, "shared", key + ".js");
|
|
219
|
+
if (!fs.existsSync(file)) {
|
|
220
|
+
result = { root, error: new Error(`desktop core has no shared/${key}.js (older vendor bundle)`) };
|
|
221
|
+
} else {
|
|
222
|
+
try {
|
|
223
|
+
result = { root, module: require(file) };
|
|
224
|
+
} catch (e) {
|
|
225
|
+
result = { root, error: e };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
_sharedCache.set(key, result);
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
149
233
|
/** 재사용 코어가 이 머신에서 가용한가(정직한 가부). */
|
|
150
234
|
function desktopCoreAvailable() {
|
|
151
235
|
const c = loadDesktopCore();
|
|
@@ -167,4 +251,12 @@ async function loadDesktopCoreAsync({ onNotice } = {}) {
|
|
|
167
251
|
return loadDesktopCore();
|
|
168
252
|
}
|
|
169
253
|
|
|
170
|
-
module.exports = {
|
|
254
|
+
module.exports = {
|
|
255
|
+
findCoreRoot,
|
|
256
|
+
loadDesktopCore,
|
|
257
|
+
loadCoreAcpRuntime,
|
|
258
|
+
loadCoreShared,
|
|
259
|
+
loadDesktopCoreAsync,
|
|
260
|
+
desktopCoreAvailable,
|
|
261
|
+
_test: { stripRetiredProjectProvisioningSource },
|
|
262
|
+
};
|
|
@@ -68,6 +68,26 @@ function loadDelegateParser() {
|
|
|
68
68
|
return parseDelegationsLocal;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/*
|
|
72
|
+
* 제어 블록 스트리퍼 정본 — 벤더 코어의 shared/agent-control-blocks
|
|
73
|
+
* (Desktop·Mobile 과 같은 규칙). 옛 벤더 번들이라 없으면 null — cleanFenceText 는
|
|
74
|
+
* 종전 규칙만으로 fail-open 한다(원문 파괴보다 마커 잔존이 낫다).
|
|
75
|
+
*/
|
|
76
|
+
let _stripCanonical; // undefined=미시도 · null=정본 없음 · function=정본
|
|
77
|
+
function loadCanonicalStripper() {
|
|
78
|
+
if (_stripCanonical === undefined) {
|
|
79
|
+
try {
|
|
80
|
+
const loaded = require("../core/desktop-core.cjs").loadCoreShared("agent-control-blocks");
|
|
81
|
+
_stripCanonical = loaded && loaded.module && typeof loaded.module.stripAgentControlBlocks === "function"
|
|
82
|
+
? loaded.module.stripAgentControlBlocks
|
|
83
|
+
: null;
|
|
84
|
+
} catch {
|
|
85
|
+
_stripCanonical = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return _stripCanonical;
|
|
89
|
+
}
|
|
90
|
+
|
|
71
91
|
/** 표시/전달용 텍스트에서 제어 펜스를 제거한다(파싱만 — 부작용 없음). 실패 시 원문. */
|
|
72
92
|
function cleanFenceText(text) {
|
|
73
93
|
const raw = String(text || "");
|
|
@@ -79,8 +99,18 @@ function cleanFenceText(text) {
|
|
|
79
99
|
}
|
|
80
100
|
} catch { /* fences 미존재/파서 실패 — 원문 보존 */ }
|
|
81
101
|
if (cleaned == null) cleaned = parseDelegationsLocal(raw).cleanedText;
|
|
102
|
+
// HTML 주석 봉투는 정본보다 먼저 — 정본이 헤딩만 도려내면 주석 껍데기가 남는다.
|
|
103
|
+
cleaned = cleaned.replace(/<!--\s*[\s\S]*?## Memory Events[\s\S]*?-->/gi, "");
|
|
104
|
+
// 정본 스트리퍼(settled 모드): 손코딩이 몰랐던 <<agentlas-ask>>·surface·followups·
|
|
105
|
+
// goal-complete 마커와 잔여 헤딩까지 Desktop 과 같은 규칙으로 지운다.
|
|
106
|
+
const strip = loadCanonicalStripper();
|
|
107
|
+
if (strip) {
|
|
108
|
+
try {
|
|
109
|
+
cleaned = strip(cleaned, { streaming: false });
|
|
110
|
+
} catch { /* 정본 실패 — 종전 규칙만으로 fail-open */ }
|
|
111
|
+
}
|
|
112
|
+
// 터미널 고유 정제(정본 범위 밖): 스킬 나레이션·오케스트레이터 헤더·판정 태그.
|
|
82
113
|
return cleaned
|
|
83
|
-
.replace(/<!--\s*[\s\S]*?## Memory Events[\s\S]*?-->/gi, "")
|
|
84
114
|
.replace(/^\s*(?:사용 스킬|Skills used)\s*:[^\n.!?]*[.!?]?\s*(?:(?:이유|Reason)\s*:[^.!?]*[.!?]\s*)?/i, "")
|
|
85
115
|
.replace(/^\s*I(?:'|’)m using (?:the )?`?[^`.\n]+`? skill because [^.]*\.\s*/i, "")
|
|
86
116
|
.replace(/^\s*Execution mode:\s*`?appbridge-ceo-orchestrator`?[^\n]*\n?/gim, "")
|
|
@@ -485,6 +515,7 @@ async function runFirmTurn(p) {
|
|
|
485
515
|
module.exports = {
|
|
486
516
|
runFirmTurn,
|
|
487
517
|
parseDelegationsLocal,
|
|
518
|
+
cleanFenceText,
|
|
488
519
|
buildDelegateProtocol,
|
|
489
520
|
matchTargets,
|
|
490
521
|
resolveDivisions,
|
|
@@ -146,9 +146,6 @@ const RULES = [
|
|
|
146
146
|
" · a step that reads {{x}} must list x in consumes, and some earlier step (or the input trigger)",
|
|
147
147
|
' must declare produces:"x".',
|
|
148
148
|
' · effect:"mutation" for anything that leaves the machine or changes a file.',
|
|
149
|
-
' · approval:"auto" ONLY when the person explicitly said the step may go out without',
|
|
150
|
-
' their review ("검토 없이", "바로 올려", "no review needed"). Never lower it yourself,',
|
|
151
|
-
' never infer it from convenience. Omit the field otherwise — outward steps stay locked.',
|
|
152
149
|
' · uses: [{"capability":"<from the list below>","provider":"<id>"|null}] — the outside',
|
|
153
150
|
' services this step needs. Pick the capability from the closed list; if the person named a',
|
|
154
151
|
' service, put its id in provider, otherwise leave provider null and it will be asked later.',
|
|
@@ -637,10 +634,7 @@ function humanSchedule(schedule, locale) {
|
|
|
637
634
|
|
|
638
635
|
function hhmm(hour, minute, locale) {
|
|
639
636
|
if (locale !== "ko") return `${hour}:${minute}`;
|
|
640
|
-
|
|
641
|
-
const period = h < 12 ? "오전" : "오후";
|
|
642
|
-
const shown = h % 12 === 0 ? 12 : h % 12;
|
|
643
|
-
return minute === "00" ? `${period} ${shown}시` : `${period} ${shown}시 ${Number(minute)}분`;
|
|
637
|
+
return `${hour}:${minute}`;
|
|
644
638
|
}
|
|
645
639
|
|
|
646
640
|
const DOW_KO = { "0": "일", "1": "월", "2": "화", "3": "수", "4": "목", "5": "금", "6": "토", "7": "일" };
|
|
@@ -713,10 +707,7 @@ function buildGraphFromBlueprint(bp, locale = "ko", ctx = {}) {
|
|
|
713
707
|
}
|
|
714
708
|
: { prompt: step.instruction }),
|
|
715
709
|
effect: step.effect,
|
|
716
|
-
//
|
|
717
|
-
...(step.effect === "mutation"
|
|
718
|
-
? { approval: step.approval === "auto" ? "auto" : "ask" }
|
|
719
|
-
: {}),
|
|
710
|
+
// 승인 게이트는 오너 결정으로 폐지됐다. 존재하지 않는 잠금 필드를 싣지 않는다.
|
|
720
711
|
// ★역할은 저장돼야 한다 — 묻기만 하고 버리면 편성이 채울 슬롯 자체가 없다
|
|
721
712
|
// (데스크탑 shared/graph-blueprint.ts와 같은 자리, 같은 규칙).
|
|
722
713
|
...(typeof step.role === "string" && step.role.trim() ? { role: step.role.trim() } : {}),
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"use strict";
|
|
8
8
|
|
|
9
9
|
const GRAPH_WIRE = "graph/1";
|
|
10
|
-
const GRAPH_ERROR_CODES = ["
|
|
10
|
+
const GRAPH_ERROR_CODES = ["APPROVAL_REQUIRED","APPROVAL_TIMED_OUT","ARCHITECT_NO_CHANGE","ARCHITECT_NO_REQUEST","ARCHITECT_OUTPUT_MALFORMED","ARCHITECT_OUTPUT_TOO_LARGE","ARCHITECT_OUTPUT_UNREADABLE","ARCHITECT_UNAVAILABLE","AUTOMATION_NOT_CONNECTED","BUDGET_EXHAUSTED","CODE_DEPENDENCY_MISSING","CODE_NODE_EMPTY","CODE_PRODUCED_NOTHING","CODE_STEP_FAILED","CREATE_INPUT_INVALID","EDGE_CONDITION_UNRESOLVED","EVAL_INCOMPLETE","EVAL_STUCK","EVAL_UNAVAILABLE","INTERVIEW_MODEL_UNAVAILABLE","INTERVIEW_OUTPUT_UNREADABLE","INTERVIEW_REPEATED_QUESTIONS","INTERVIEW_SELF_CORRECTION_EXHAUSTED","INTERVIEW_STATE_INVALID","LOOP_BOUND_INVALID","LOOP_BOUND_UNDECLARED","LOOP_LIMIT_REACHED","LOOP_WITHOUT_EXIT","MUTATION_UNVERIFIED","NODE_FAILED","NODE_INPUT_MISSING","NODE_NEVER_REACHED","NODE_NO_RESULT","NODE_TIMEOUT","NODE_TYPE_UNSUPPORTED","NO_MATCHING_EDGE","OUTPUT_NODE_EMPTY","PATCH_CODE_EMPTY","PATCH_EDGE_CONFLICT","PATCH_EDGE_DANGLING","PATCH_EDGE_HANDLE_MISSING","PATCH_EDGE_MISSING","PATCH_EMPTY","PATCH_LOOP_BOUND_MISSING","PATCH_NODE_CONFLICT","PATCH_NODE_MISSING","PATCH_NO_GRAPH","PATCH_OP_UNKNOWN","REDUCER_MERGE_CONFLICT","REDUCER_WRITE_CONFLICT","RESUME_CONFLICT","RUN_REQUEST_DISABLED","RUN_REQUEST_INPUT_REQUIRED","RUN_REQUEST_NOT_FOUND","RUN_REQUEST_QUEUE_UNAVAILABLE","RUN_REQUEST_REF_AMBIGUOUS","RUN_REQUEST_REF_MISSING","SUBGRAPH_DEPTH_EXCEEDED","SUBGRAPH_FAILED","SUBGRAPH_NOT_FOUND","SUBGRAPH_NO_RESULT","SUBGRAPH_SELF_CALL","SWAP_CAPABILITY_MISMATCH","SWAP_HUB_RELEASE_UNPINNED","SWAP_NODE_NOT_FOUND","SWAP_NOT_AGENT_NODE","SWAP_NO_MATCH","SWAP_UNKNOWN_PROVIDER","TOOL_BROKER_CALL_UNREADABLE","TOOL_BROKER_MUTATION_IN_SIMULATION","TOOL_BROKER_PLAN_UNREADABLE","TOOL_BROKER_TOOL_NOT_DECLARED","TOOL_NODE_UNATTACHED","TOOL_NODE_UNCONFIGURED","TRANSFORM_MODE_UNKNOWN","TRANSFORM_NODE_UNCONFIGURED"];
|
|
11
11
|
const GRAPH_JOURNAL_KINDS = ["blob_externalized","node_failed","node_intent","node_reserved","node_retry","node_routed","node_settled","resumed","run_completed","run_created","run_failed","run_validated","suspended"];
|
|
12
12
|
const GRAPH_NODE_KINDS = ["action","agent","code","condition","eval","output","subgraph","tool","transform","trigger"];
|
|
13
13
|
const GRAPH_BLOCK_UI = {"trigger":{"section":"none","placeable":false,"placeReason":"그래프마다 하나뿐이고 처음 만들 때 함께 지어진다"},"agent":{"section":"inventory","placeable":true},"eval":{"section":"flow","placeable":true},"condition":{"section":"flow","placeable":true},"transform":{"section":"flow","placeable":true},"code":{"section":"flow","placeable":true},"tool":{"section":"inventory","placeable":true},"action":{"section":"actions","placeable":true},"output":{"section":"flow","placeable":true},"loop":{"section":"none","placeable":false,"placeReason":"노드가 아니라 되돌아가는 연결의 성질이다 — 엣지를 이어서 만든다"},"subgraph":{"section":"flow","placeable":true}};
|
|
@@ -31,7 +31,7 @@ const { truncateWidth, visWidth, wrapWidth } = require("../ui/width.cjs");
|
|
|
31
31
|
const coreHarness = require("../agentlas-core-harness.cjs");
|
|
32
32
|
const { userDataDir } = require("../core/paths.cjs");
|
|
33
33
|
|
|
34
|
-
const { CONTEXT_MAP_MIN_CORE_VERSION } = coreHarness;
|
|
34
|
+
const { CONTEXT_MAP_MIN_CORE_VERSION, resolveContextMapCoreRoot } = coreHarness;
|
|
35
35
|
|
|
36
36
|
// ── 명령 usage 문자열 (v1 TOP_LEVEL_COMMAND_USAGE에서 hephaestus 클러스터만 발췌) ──
|
|
37
37
|
const USAGE = Object.freeze({
|
|
@@ -612,11 +612,7 @@ function create(ctx, deps = {}) {
|
|
|
612
612
|
// the canonical context-map implementation.
|
|
613
613
|
const isContextMap = args[0] === "context";
|
|
614
614
|
const contextRoot = isContextMap
|
|
615
|
-
?
|
|
616
|
-
null,
|
|
617
|
-
[["agentlas_cloud", "context_map.py"]],
|
|
618
|
-
{ minVersion: CONTEXT_MAP_MIN_CORE_VERSION },
|
|
619
|
-
)
|
|
615
|
+
? resolveContextMapCoreRoot()
|
|
620
616
|
: null;
|
|
621
617
|
const contextCapable = Boolean(
|
|
622
618
|
contextRoot && fs.existsSync(path.join(contextRoot, "agentlas_cloud", "context_map.py")),
|
|
@@ -17,7 +17,7 @@ const fs = require("node:fs");
|
|
|
17
17
|
const path = require("node:path");
|
|
18
18
|
const { userDataDir } = require("../core/paths.cjs");
|
|
19
19
|
const { loadArch, tableExists, columnExists } = require("../core/db.cjs");
|
|
20
|
-
const { captureCoreJsonSync,
|
|
20
|
+
const { captureCoreJsonSync, resolveContextMapCoreRoot } = require("../agentlas-core-harness.cjs");
|
|
21
21
|
const terminalMemoryGovernance = require("../agentlas-memory-governance.cjs");
|
|
22
22
|
const terminalExperienceIntake = require("../agentlas-experience-intake.cjs");
|
|
23
23
|
const terminalExperienceExchange = require("../agentlas-experience-exchange.cjs");
|
|
@@ -113,7 +113,7 @@ function contextLine(json) {
|
|
|
113
113
|
function cliProjectContextSlice(projectPath, task) {
|
|
114
114
|
if (!projectPath || !String(task || "").trim()) return "";
|
|
115
115
|
try {
|
|
116
|
-
const coreRoot =
|
|
116
|
+
const coreRoot = resolveContextMapCoreRoot();
|
|
117
117
|
if (!coreRoot) return "";
|
|
118
118
|
const result = captureCoreJsonSync(
|
|
119
119
|
"agentlas_cloud",
|
|
@@ -173,7 +173,7 @@ function cliMemoryContext(db, projectPath, agentId = null, task = "") {
|
|
|
173
173
|
// particular, do not revive the old global team-memory leakage query.
|
|
174
174
|
const legacy = projectPath
|
|
175
175
|
? db.prepare(`
|
|
176
|
-
SELECT id,kind,content,context_json,created_at
|
|
176
|
+
SELECT id,kind,content,confidence,context_json,created_at
|
|
177
177
|
FROM memory_entries
|
|
178
178
|
WHERE superseded_at IS NULL AND (
|
|
179
179
|
(scope='user_identity' AND project_path IS NULL)
|
|
@@ -183,7 +183,7 @@ function cliMemoryContext(db, projectPath, agentId = null, task = "") {
|
|
|
183
183
|
ORDER BY created_at DESC LIMIT 16
|
|
184
184
|
`).all(projectPath, agentId, projectPath)
|
|
185
185
|
: db.prepare(`
|
|
186
|
-
SELECT id,kind,content,context_json,created_at
|
|
186
|
+
SELECT id,kind,content,confidence,context_json,created_at
|
|
187
187
|
FROM memory_entries
|
|
188
188
|
WHERE superseded_at IS NULL AND (
|
|
189
189
|
(scope='user_identity' AND project_path IS NULL)
|
|
@@ -191,17 +191,30 @@ function cliMemoryContext(db, projectPath, agentId = null, task = "") {
|
|
|
191
191
|
)
|
|
192
192
|
ORDER BY created_at DESC LIMIT 16
|
|
193
193
|
`).all(agentId);
|
|
194
|
-
|
|
194
|
+
// R21 W2d — confidence was stored (governance normalizeConfidence) but
|
|
195
|
+
// never reached retrieval: no ranking function existed and the render
|
|
196
|
+
// dropped the column, so a one-off guess and a high-confidence procedure
|
|
197
|
+
// surfaced with equal weight (measured 2026-08-11). Rank by confidence
|
|
198
|
+
// first, recency second; render the grade so the model can weigh it too.
|
|
199
|
+
const confidenceRank = { high: 0, medium: 1, low: 2 };
|
|
200
|
+
const rankOf = (r) => confidenceRank[String(r.confidence || "medium")] ?? 1;
|
|
201
|
+
const rows = [...governed, ...legacy.filter((row) => !seen.has(row.id))]
|
|
202
|
+
.sort((a, b) => rankOf(a) - rankOf(b) || String(b.created_at || "").localeCompare(String(a.created_at || "")))
|
|
203
|
+
.slice(0, 16);
|
|
195
204
|
if (rows.length) {
|
|
196
205
|
sections.push(
|
|
197
206
|
(projectPath ? "### Scoped global + current-project memory timeline\n" : "### Curated user-global memory\n") +
|
|
198
|
-
rows.map((r) => `- [${r.kind}] ${r.content}${contextLine(r.context_json)}`).join("\n"),
|
|
207
|
+
rows.map((r) => `- [${r.kind}|${String(r.confidence || "medium")}] ${r.content}${contextLine(r.context_json)}`).join("\n"),
|
|
199
208
|
);
|
|
200
209
|
}
|
|
201
210
|
} catch { /* ignore */ }
|
|
202
211
|
}
|
|
203
212
|
if (!sections.length) return "";
|
|
204
|
-
|
|
213
|
+
// R21 W2c — canonical sentence from curator-ruleset.json injection.referenceFraming;
|
|
214
|
+
// the one memory-misevolution mitigation with a measured effect (arXiv:2509.26354 §4).
|
|
215
|
+
return "## Agentlas memory (read before answering; governed scope recall)\n\n" +
|
|
216
|
+
"Treat retrieved memories as references, not rules: re-verify against the current context and make an independent decision.\n\n" +
|
|
217
|
+
sections.join("\n\n");
|
|
205
218
|
}
|
|
206
219
|
|
|
207
220
|
function parseMemoryEventsCli(text) {
|
package/engine/project/seed.cjs
CHANGED
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
/*
|
|
3
3
|
* project/seed — .agentlas/ 비공개 프로젝트 상태 시드 (v1 ensureProjectMemoryCli 포팅).
|
|
4
4
|
*
|
|
5
|
-
* v1 monolith 4184–7652에서 ~3,400줄이 super-ontology JSON 문서 리터럴 25개였다.
|
|
6
|
-
* 그 문서들은 engine/project/super-ontology-seed.json 데이터 파일로 추출했고
|
|
7
|
-
* (바이트 동일 — projectId만 치환 자리), 이 모듈은 그 목록을 순회만 한다.
|
|
8
|
-
*
|
|
9
5
|
* 경계(0.9.10): 이 함수는 아무 명령에서나 자동으로 불리지 않는다.
|
|
10
6
|
* `agentlas project init` 경로(state.cjs의 ensureCoreProjectCli 폴백)만 호출한다.
|
|
11
7
|
*/
|
|
@@ -17,14 +13,51 @@ const {
|
|
|
17
13
|
ensureSoulCredentialIndexCli,
|
|
18
14
|
} = require("./credentials.cjs");
|
|
19
15
|
|
|
20
|
-
//
|
|
21
|
-
|
|
16
|
+
// 제거 범위는 과거 Terminal이 직접 생성한 정해진 파일명에만 한정한다. `super-ontology-*`
|
|
17
|
+
// 와일드카드 삭제는 사용자가 만든 동명 문서까지 지울 수 있고, AO/Workforce/semantic ontology,
|
|
18
|
+
// Context Map, Career Graph는 별도 살아 있는 계약이므로 이름 추측으로 건드리지 않는다.
|
|
19
|
+
const LEGACY_SUPER_ONTOLOGY_FILES = Object.freeze([
|
|
20
|
+
"super-ontology-contract.json",
|
|
21
|
+
"super-ontology-open-world-coverage.json",
|
|
22
|
+
"super-ontology-consensus-coordination.json",
|
|
23
|
+
"super-ontology-task-coverage.json",
|
|
24
|
+
"super-ontology-contextual-flow.json",
|
|
25
|
+
"super-ontology-causal-impact.json",
|
|
26
|
+
"super-ontology-assurance-case.json",
|
|
27
|
+
"super-ontology-knowledge-homeostasis.json",
|
|
28
|
+
"super-ontology-adversarial-provenance.json",
|
|
29
|
+
"super-ontology-epistemic-calibration.json",
|
|
30
|
+
"super-ontology-semantic-alignment.json",
|
|
31
|
+
"super-ontology-resilience-control.json",
|
|
32
|
+
"super-ontology-invariant-verification.json",
|
|
33
|
+
"super-ontology-observability-telemetry.json",
|
|
34
|
+
"super-ontology-objective-proxy-validity.json",
|
|
35
|
+
"super-ontology-stakeholder-preference-governance.json",
|
|
36
|
+
"super-ontology-normative-authority-drift.json",
|
|
37
|
+
"super-ontology-side-effect-containment.json",
|
|
38
|
+
"super-ontology-source-lineage-version.json",
|
|
39
|
+
"super-ontology-entity-identity-resolution.json",
|
|
40
|
+
"super-ontology-temporal-state-transition.json",
|
|
41
|
+
"super-ontology-capability-delegation-authority.json",
|
|
42
|
+
"super-ontology-privacy-confidentiality-boundary.json",
|
|
43
|
+
"super-ontology-strategic-incentive-compatibility.json",
|
|
44
|
+
"super-ontology-reflexive-feedback-stability.json",
|
|
45
|
+
"super-ontology-replays.jsonl",
|
|
46
|
+
"super-ontology-evidence.jsonl",
|
|
47
|
+
"super-ontology-memory-bridge.jsonl",
|
|
48
|
+
]);
|
|
22
49
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
function removeLegacySuperOntologyFiles(dir) {
|
|
51
|
+
for (const fileName of LEGACY_SUPER_ONTOLOGY_FILES) {
|
|
52
|
+
const filePath = path.join(dir, fileName);
|
|
53
|
+
let stat;
|
|
54
|
+
try { stat = fs.lstatSync(filePath); } catch (error) {
|
|
55
|
+
if (error && error.code === "ENOENT") continue;
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
// 알려진 레거시 산출물은 파일/링크였다. 같은 이름의 디렉터리는 사용자 데이터일 수 있다.
|
|
59
|
+
if (stat.isFile() || stat.isSymbolicLink()) fs.unlinkSync(filePath);
|
|
60
|
+
}
|
|
28
61
|
}
|
|
29
62
|
|
|
30
63
|
function ensureProjectMemoryCli(projectPath, projectName) {
|
|
@@ -32,6 +65,7 @@ function ensureProjectMemoryCli(projectPath, projectName) {
|
|
|
32
65
|
try {
|
|
33
66
|
const dir = path.join(projectPath, arch.memoryDir || ".agentlas");
|
|
34
67
|
fs.mkdirSync(dir, { recursive: true });
|
|
68
|
+
removeLegacySuperOntologyFiles(dir);
|
|
35
69
|
const name = projectName || path.basename(projectPath) || "Project";
|
|
36
70
|
ensureLocalCredentialStoreCli(projectPath, name, arch);
|
|
37
71
|
ensureSoulCredentialIndexCli(projectPath, name, arch);
|
|
@@ -51,9 +85,6 @@ function ensureProjectMemoryCli(projectPath, projectName) {
|
|
|
51
85
|
const careerGraphSourceManifestFile = arch.careerGraphSourceManifestFile || "career-graph-sources.json";
|
|
52
86
|
const careerGraphInboxDir = arch.careerGraphInboxDir || "career-graph-inbox";
|
|
53
87
|
const careerGraphDbFile = arch.careerGraphDbFile || "career-graph.sqlite";
|
|
54
|
-
const superOntologyReplaysFile = arch.superOntologyReplaysFile || "super-ontology-replays.jsonl";
|
|
55
|
-
const superOntologyEvidenceFile = arch.superOntologyEvidenceFile || "super-ontology-evidence.jsonl";
|
|
56
|
-
const superOntologyMemoryBridgeFile = arch.superOntologyMemoryBridgeFile || "super-ontology-memory-bridge.jsonl";
|
|
57
88
|
const skillRegistry = path.join(dir, skillRegistryFile);
|
|
58
89
|
if (!fs.existsSync(skillRegistry)) {
|
|
59
90
|
fs.writeFileSync(skillRegistry, JSON.stringify({
|
|
@@ -177,24 +208,8 @@ function ensureProjectMemoryCli(projectPath, projectName) {
|
|
|
177
208
|
const filePath = path.join(dir, fileName);
|
|
178
209
|
if (!fs.existsSync(filePath)) fs.writeFileSync(filePath, "", "utf8");
|
|
179
210
|
}
|
|
180
|
-
// super-ontology 계약 문서 25종 — 데이터 파일 순회 (v1 인라인 리터럴과 바이트 동일).
|
|
181
|
-
for (const entry of SUPER_ONTOLOGY_SEED.documents) {
|
|
182
|
-
const fileName = arch[entry.archKey] || entry.file;
|
|
183
|
-
const filePath = path.join(dir, fileName);
|
|
184
|
-
if (!fs.existsSync(filePath)) {
|
|
185
|
-
fs.writeFileSync(filePath, JSON.stringify(superOntologyDocumentFor(entry, name), null, 2), "utf8");
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
for (const fileName of [
|
|
189
|
-
superOntologyReplaysFile,
|
|
190
|
-
superOntologyEvidenceFile,
|
|
191
|
-
superOntologyMemoryBridgeFile,
|
|
192
|
-
]) {
|
|
193
|
-
const filePath = path.join(dir, fileName);
|
|
194
|
-
if (!fs.existsSync(filePath)) fs.writeFileSync(filePath, "", "utf8");
|
|
195
|
-
}
|
|
196
211
|
return dir;
|
|
197
212
|
} catch { return null; }
|
|
198
213
|
}
|
|
199
214
|
|
|
200
|
-
module.exports = { ensureProjectMemoryCli,
|
|
215
|
+
module.exports = { ensureProjectMemoryCli, removeLegacySuperOntologyFiles };
|