harnessed 4.7.0 → 4.9.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/bin/harnessed-inject-state.mjs +35 -4
- package/dist/cli.mjs +190 -85
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/manifests/optional/perturn-inject.yaml +49 -0
- package/messages/zh-Hans.json +16 -2
- package/package.json +1 -1
- package/workflows/auto/SKILL.zh-Hans.md +129 -0
- package/workflows/disciplines/doc-discipline.zh-Hans.yaml +49 -0
- package/workflows/disciplines/karpathy.yaml +5 -5
- package/workflows/disciplines/karpathy.zh-Hans.yaml +47 -0
- package/workflows/disciplines/operational.yaml +6 -6
- package/workflows/disciplines/operational.zh-Hans.yaml +79 -0
- package/workflows/disciplines/output-style.yaml +7 -7
- package/workflows/disciplines/output-style.zh-Hans.yaml +62 -0
- package/workflows/disciplines/priority.yaml +2 -2
- package/workflows/disciplines/priority.zh-Hans.yaml +28 -0
- package/workflows/discuss/auto/SKILL.zh-Hans.md +75 -0
- package/workflows/discuss/phase/SKILL.zh-Hans.md +73 -0
- package/workflows/discuss/strategic/SKILL.zh-Hans.md +78 -0
- package/workflows/discuss/subtask/SKILL.zh-Hans.md +79 -0
- package/workflows/plan/architecture/SKILL.zh-Hans.md +74 -0
- package/workflows/plan/auto/SKILL.zh-Hans.md +75 -0
- package/workflows/plan/phase/SKILL.zh-Hans.md +76 -0
- package/workflows/research/SKILL.zh-Hans.md +81 -0
- package/workflows/retro/SKILL.zh-Hans.md +71 -0
- package/workflows/role-prompts.zh-Hans.yaml +501 -0
- package/workflows/ship/auto/SKILL.zh-Hans.md +46 -0
- package/workflows/ship/preflight/SKILL.zh-Hans.md +38 -0
- package/workflows/task/auto/SKILL.zh-Hans.md +80 -0
- package/workflows/task/clarify/SKILL.zh-Hans.md +79 -0
- package/workflows/task/code/SKILL.zh-Hans.md +85 -0
- package/workflows/task/deliver/SKILL.zh-Hans.md +113 -0
- package/workflows/task/test/SKILL.zh-Hans.md +90 -0
- package/workflows/verify/auto/SKILL.zh-Hans.md +89 -0
- package/workflows/verify/code-review/SKILL.zh-Hans.md +71 -0
- package/workflows/verify/design/SKILL.zh-Hans.md +74 -0
- package/workflows/verify/multispec/SKILL.zh-Hans.md +88 -0
- package/workflows/verify/paranoid/SKILL.zh-Hans.md +74 -0
- package/workflows/verify/progress/SKILL.zh-Hans.md +69 -0
- package/workflows/verify/qa/SKILL.zh-Hans.md +76 -0
- package/workflows/verify/security/SKILL.zh-Hans.md +70 -0
- package/workflows/verify/simplify/SKILL.zh-Hans.md +70 -0
|
@@ -38,11 +38,28 @@ function harnessedRoot() {
|
|
|
38
38
|
: join(homedir(), '.claude', 'harnessed')
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
|
|
41
|
+
// Phase 35 — mirror PlatformDescriptor.sessionIdEnv (src/installers/lib/platform.ts)
|
|
42
|
+
// for the hot path: which env var carries the active session id. Minimal replica —
|
|
43
|
+
// HARNESSED_PLATFORM selects (default claude); codex has none. State-root selection
|
|
44
|
+
// (.platform pin / auto-probe) is orthogonal and already handled via
|
|
45
|
+
// HARNESSED_ROOT_OVERRIDE, so it is not re-derived here. The TS `activeKey` uses the
|
|
46
|
+
// full descriptor; the parity test sets matching signals.
|
|
47
|
+
function sessionIdEnvName() {
|
|
48
|
+
const platform = (process.env.HARNESSED_PLATFORM || 'claude').trim()
|
|
49
|
+
if (platform === 'codex') return null
|
|
50
|
+
return 'CLAUDE_CODE_SESSION_ID' // claude (default)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Phase 35 — try the session-scoped slot first, then the bare repoKey slot, then
|
|
54
|
+
// the legacy singleton (dual-write anchor). `keys` is ordered most→least specific.
|
|
55
|
+
function readWorkflow(root, keys) {
|
|
43
56
|
try {
|
|
44
57
|
const store = JSON.parse(readFileSync(join(root, 'workflows.json'), 'utf8'))
|
|
45
|
-
if (store
|
|
58
|
+
if (store?.workflows) {
|
|
59
|
+
for (const k of keys) {
|
|
60
|
+
if (store.workflows[k]) return store.workflows[k]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
46
63
|
} catch {}
|
|
47
64
|
try {
|
|
48
65
|
return JSON.parse(readFileSync(join(root, 'current-workflow.json'), 'utf8'))
|
|
@@ -76,6 +93,14 @@ function workflowStateBlock(wf) {
|
|
|
76
93
|
'RETRO-DUE: enough phases completed since the last retro — run /retro, then `harnessed retro --done`',
|
|
77
94
|
)
|
|
78
95
|
}
|
|
96
|
+
// Phase 36 — scale-adaptive verify_mode directive (parity with injectState.ts).
|
|
97
|
+
if (wf.verify_mode === 'full') {
|
|
98
|
+
lines.push(
|
|
99
|
+
'VERIFY-MODE: full — run full verification (large/risky change: >5 files / >4 subs / >3 reqs)',
|
|
100
|
+
)
|
|
101
|
+
} else if (wf.verify_mode === 'light') {
|
|
102
|
+
lines.push('VERIFY-MODE: light — scope verification to the changed surface (small change)')
|
|
103
|
+
}
|
|
79
104
|
lines.push('</workflow-state>')
|
|
80
105
|
return lines.join('\n')
|
|
81
106
|
}
|
|
@@ -140,8 +165,14 @@ function projectContextBlock(learnings, contextExcerpt) {
|
|
|
140
165
|
|
|
141
166
|
try {
|
|
142
167
|
const root = harnessedRoot()
|
|
168
|
+
// `key` is the repo ROOT directory (used for .planning/ fs paths below). The
|
|
169
|
+
// workflow LOOKUP uses the session-scoped composite key first (Phase 34/35),
|
|
170
|
+
// falling back to the bare repoKey, then the legacy singleton. The composite
|
|
171
|
+
// key is NOT a real directory — only the bare repoKey is.
|
|
143
172
|
const key = repoKey(process.cwd())
|
|
144
|
-
const
|
|
173
|
+
const envName = sessionIdEnvName()
|
|
174
|
+
const sid = envName ? process.env[envName]?.trim() : undefined
|
|
175
|
+
const wf = readWorkflow(root, sid ? [`${key}::${sid}`, key] : [key])
|
|
145
176
|
if (!wf) process.exit(0)
|
|
146
177
|
|
|
147
178
|
const budget = Number(process.env.HARNESSED_INJECT_BUDGET) || DEFAULT_INJECT_BUDGET
|
package/dist/cli.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import * as ajvFormatsNs from 'ajv-formats';
|
|
|
6
6
|
import { execFileSync, spawnSync, spawn, exec, execFile, execSync } from 'child_process';
|
|
7
7
|
import { existsSync, mkdirSync, renameSync, writeFileSync, readFileSync, readdirSync } from 'fs';
|
|
8
8
|
import { join, dirname, resolve, sep, relative } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
9
10
|
import { homedir } from 'os';
|
|
10
11
|
import { createHash } from 'crypto';
|
|
11
12
|
import { readFile, readdir, unlink, writeFile, stat, rm, cp, mkdir, rename, appendFile, access } from 'fs/promises';
|
|
@@ -13,7 +14,6 @@ import { Value } from '@sinclair/typebox/value';
|
|
|
13
14
|
import lockfile from 'proper-lockfile';
|
|
14
15
|
import { Parser } from 'expr-eval';
|
|
15
16
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
16
|
-
import { fileURLToPath } from 'url';
|
|
17
17
|
import { promisify } from 'util';
|
|
18
18
|
import * as p from '@clack/prompts';
|
|
19
19
|
import { createPatch } from 'diff';
|
|
@@ -38,7 +38,7 @@ var init_package = __esm({
|
|
|
38
38
|
"package.json"() {
|
|
39
39
|
package_default = {
|
|
40
40
|
name: "harnessed",
|
|
41
|
-
version: "4.
|
|
41
|
+
version: "4.9.0",
|
|
42
42
|
description: "AI coding harness package manager + composition orchestrator",
|
|
43
43
|
type: "module",
|
|
44
44
|
license: "Apache-2.0",
|
|
@@ -852,6 +852,76 @@ var init_origin_check = __esm({
|
|
|
852
852
|
"src/cli/lib/origin-check.ts"() {
|
|
853
853
|
}
|
|
854
854
|
});
|
|
855
|
+
function mapToSupported(raw) {
|
|
856
|
+
if (!raw) return "en";
|
|
857
|
+
if (/^zh([^a-z]|$)/i.test(raw)) return "zh-Hans";
|
|
858
|
+
return "en";
|
|
859
|
+
}
|
|
860
|
+
function detectLocale() {
|
|
861
|
+
const raw = process.env.HARNESSED_LANG || process.env.LC_ALL || process.env.LANG || process.env.LANGUAGE || safeIntlLocale();
|
|
862
|
+
return mapToSupported(raw);
|
|
863
|
+
}
|
|
864
|
+
function safeIntlLocale() {
|
|
865
|
+
try {
|
|
866
|
+
return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
867
|
+
} catch {
|
|
868
|
+
return void 0;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
function messagesDir() {
|
|
872
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
873
|
+
const candidates = [resolve(here, "..", "..", "messages"), resolve(here, "..", "messages")];
|
|
874
|
+
for (const c of candidates) {
|
|
875
|
+
try {
|
|
876
|
+
readFileSync(join(c, "en.json"), "utf8");
|
|
877
|
+
return c;
|
|
878
|
+
} catch {
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
return resolve(process.cwd(), "messages");
|
|
882
|
+
}
|
|
883
|
+
function loadLocale(locale) {
|
|
884
|
+
if (cache[locale]) return cache[locale];
|
|
885
|
+
const path = join(messagesDir(), `${locale}.json`);
|
|
886
|
+
try {
|
|
887
|
+
const raw = readFileSync(path, "utf8");
|
|
888
|
+
cache[locale] = JSON.parse(raw);
|
|
889
|
+
} catch {
|
|
890
|
+
cache[locale] = {};
|
|
891
|
+
}
|
|
892
|
+
return cache[locale];
|
|
893
|
+
}
|
|
894
|
+
function setLocale(locale) {
|
|
895
|
+
if (!locale) return;
|
|
896
|
+
const mapped = mapToSupported(locale);
|
|
897
|
+
if (SUPPORTED.has(mapped)) currentLocale = mapped;
|
|
898
|
+
}
|
|
899
|
+
function getLocale() {
|
|
900
|
+
if (currentLocale === null) currentLocale = detectLocale();
|
|
901
|
+
return currentLocale;
|
|
902
|
+
}
|
|
903
|
+
function t(key, params) {
|
|
904
|
+
const locale = getLocale();
|
|
905
|
+
const primary = loadLocale(locale);
|
|
906
|
+
let template = primary[key];
|
|
907
|
+
if (template === void 0 && locale !== "en") {
|
|
908
|
+
template = loadLocale("en")[key];
|
|
909
|
+
}
|
|
910
|
+
if (template === void 0) template = key;
|
|
911
|
+
if (!params) return template;
|
|
912
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
|
|
913
|
+
const v = params[name];
|
|
914
|
+
return v === void 0 ? `{{${name}}}` : String(v);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
var SUPPORTED, currentLocale, cache;
|
|
918
|
+
var init_i18n = __esm({
|
|
919
|
+
"src/i18n/index.ts"() {
|
|
920
|
+
SUPPORTED = /* @__PURE__ */ new Set(["en", "zh-Hans"]);
|
|
921
|
+
currentLocale = null;
|
|
922
|
+
cache = {};
|
|
923
|
+
}
|
|
924
|
+
});
|
|
855
925
|
function claudeDescriptor(home = homedir()) {
|
|
856
926
|
const claudeHome = join(home, ".claude");
|
|
857
927
|
return {
|
|
@@ -866,7 +936,9 @@ function claudeDescriptor(home = homedir()) {
|
|
|
866
936
|
// the same home base — not a child of homeDir.
|
|
867
937
|
mcpConfigPath: join(home, ".claude.json"),
|
|
868
938
|
// claude writes its env keys into JSON settings.json (capability present).
|
|
869
|
-
supportsEnvKeyWrite: true
|
|
939
|
+
supportsEnvKeyWrite: true,
|
|
940
|
+
// Claude Code exposes the active session id to Bash-invoked CLI + hooks.
|
|
941
|
+
sessionIdEnv: "CLAUDE_CODE_SESSION_ID"
|
|
870
942
|
};
|
|
871
943
|
}
|
|
872
944
|
function codexDescriptor(home = homedir()) {
|
|
@@ -882,7 +954,9 @@ function codexDescriptor(home = homedir()) {
|
|
|
882
954
|
commandsDir: join(codexHome, "prompts"),
|
|
883
955
|
pluginsRegistry: null,
|
|
884
956
|
mcpConfigPath: configToml,
|
|
885
|
-
supportsEnvKeyWrite: false
|
|
957
|
+
supportsEnvKeyWrite: false,
|
|
958
|
+
// No verified codex session-id env → single-session fallback (anti-stale).
|
|
959
|
+
sessionIdEnv: null
|
|
886
960
|
};
|
|
887
961
|
}
|
|
888
962
|
function descriptorById(id, home) {
|
|
@@ -1406,6 +1480,7 @@ var workflowStore_exports = {};
|
|
|
1406
1480
|
__export(workflowStore_exports, {
|
|
1407
1481
|
RetroMetaEntry: () => RetroMetaEntry,
|
|
1408
1482
|
WorkflowStoreV1: () => WorkflowStoreV1,
|
|
1483
|
+
activeKey: () => activeKey,
|
|
1409
1484
|
listWorkflows: () => listWorkflows,
|
|
1410
1485
|
readStoreRaw: () => readStoreRaw,
|
|
1411
1486
|
repoKey: () => repoKey,
|
|
@@ -1430,6 +1505,12 @@ function repoKey(cwd = process.cwd()) {
|
|
|
1430
1505
|
}
|
|
1431
1506
|
return resolve(cwd);
|
|
1432
1507
|
}
|
|
1508
|
+
function activeKey(cwd = process.cwd()) {
|
|
1509
|
+
const base = repoKey(cwd);
|
|
1510
|
+
const envName = detectPlatform().sessionIdEnv;
|
|
1511
|
+
const sid = envName ? process.env[envName]?.trim() : void 0;
|
|
1512
|
+
return sid ? `${base}::${sid}` : base;
|
|
1513
|
+
}
|
|
1433
1514
|
async function readStoreRaw() {
|
|
1434
1515
|
try {
|
|
1435
1516
|
const parsed = JSON.parse(await readFile(storePath(), "utf8"));
|
|
@@ -1469,6 +1550,7 @@ var RetroMetaEntry, WorkflowStoreV1;
|
|
|
1469
1550
|
var init_workflowStore = __esm({
|
|
1470
1551
|
"src/checkpoint/workflowStore.ts"() {
|
|
1471
1552
|
init_harnessedRoot();
|
|
1553
|
+
init_platform();
|
|
1472
1554
|
init_schemaVersion();
|
|
1473
1555
|
init_atomicWrite();
|
|
1474
1556
|
init_currentWorkflow_v1();
|
|
@@ -1535,7 +1617,7 @@ async function withLock(fn) {
|
|
|
1535
1617
|
}
|
|
1536
1618
|
async function readCurrentWorkflow() {
|
|
1537
1619
|
const store = await readStoreRaw();
|
|
1538
|
-
return store.workflows[repoKey()] ?? null;
|
|
1620
|
+
return store.workflows[activeKey()] ?? store.workflows[repoKey()] ?? null;
|
|
1539
1621
|
}
|
|
1540
1622
|
async function writeCurrentWorkflowUnlocked(s) {
|
|
1541
1623
|
if (!Value.Check(CurrentWorkflowV1, s)) {
|
|
@@ -1543,7 +1625,7 @@ async function writeCurrentWorkflowUnlocked(s) {
|
|
|
1543
1625
|
throw new WorkflowStateError(`current-workflow schema validation failed: ${errs}`);
|
|
1544
1626
|
}
|
|
1545
1627
|
const store = await readStoreRaw();
|
|
1546
|
-
store.workflows[
|
|
1628
|
+
store.workflows[activeKey()] = s;
|
|
1547
1629
|
await writeStoreRaw(store);
|
|
1548
1630
|
await writeFileAtomic(statePath(), JSON.stringify(s, null, 2));
|
|
1549
1631
|
}
|
|
@@ -1978,8 +2060,20 @@ var init_loadPhases = __esm({
|
|
|
1978
2060
|
};
|
|
1979
2061
|
}
|
|
1980
2062
|
});
|
|
1981
|
-
|
|
1982
|
-
|
|
2063
|
+
function resolveLocaleYaml(dir, baseName, locale = getLocale()) {
|
|
2064
|
+
if (locale !== "en") {
|
|
2065
|
+
const sibling = join(dir, `${baseName}.${locale}.yaml`);
|
|
2066
|
+
if (existsSync(sibling)) return sibling;
|
|
2067
|
+
}
|
|
2068
|
+
return join(dir, `${baseName}.yaml`);
|
|
2069
|
+
}
|
|
2070
|
+
var init_localeYaml = __esm({
|
|
2071
|
+
"src/i18n/localeYaml.ts"() {
|
|
2072
|
+
init_i18n();
|
|
2073
|
+
}
|
|
2074
|
+
});
|
|
2075
|
+
async function loadRolePrompts(workflowsDir, locale = getLocale()) {
|
|
2076
|
+
const path = resolveLocaleYaml(workflowsDir, "role-prompts", locale);
|
|
1983
2077
|
let raw;
|
|
1984
2078
|
try {
|
|
1985
2079
|
raw = await readFile(path, "utf8");
|
|
@@ -2193,6 +2287,8 @@ async function writeAllCommands(slashNames, commandsDir, rolePrompts, capabiliti
|
|
|
2193
2287
|
var INTERACTIVE_COMMANDS, ORCHESTRATOR_COMMANDS, MARKER, LANG_DIRECTIVE, HARNESSED_MARKER_RX, V3_4_3_SIGNATURE_SUB_RX, V3_4_3_SIGNATURE_MASTER_RX;
|
|
2194
2288
|
var init_generateCommands = __esm({
|
|
2195
2289
|
"src/cli/lib/generateCommands.ts"() {
|
|
2290
|
+
init_i18n();
|
|
2291
|
+
init_localeYaml();
|
|
2196
2292
|
INTERACTIVE_COMMANDS = /* @__PURE__ */ new Set([
|
|
2197
2293
|
"discuss",
|
|
2198
2294
|
"discuss-strategic",
|
|
@@ -6875,73 +6971,9 @@ audited ${yamls.length} manifest${yamls.length === 1 ? "" : "s"} \u2014 ${findin
|
|
|
6875
6971
|
process.exit(errorCount > 0 ? 1 : 0);
|
|
6876
6972
|
});
|
|
6877
6973
|
}
|
|
6878
|
-
var SUPPORTED = /* @__PURE__ */ new Set(["en", "zh-Hans"]);
|
|
6879
|
-
var currentLocale = null;
|
|
6880
|
-
var cache = {};
|
|
6881
|
-
function mapToSupported(raw) {
|
|
6882
|
-
if (!raw) return "en";
|
|
6883
|
-
if (/^zh([^a-z]|$)/i.test(raw)) return "zh-Hans";
|
|
6884
|
-
return "en";
|
|
6885
|
-
}
|
|
6886
|
-
function detectLocale() {
|
|
6887
|
-
const raw = process.env.HARNESSED_LANG || process.env.LC_ALL || process.env.LANG || process.env.LANGUAGE || safeIntlLocale();
|
|
6888
|
-
return mapToSupported(raw);
|
|
6889
|
-
}
|
|
6890
|
-
function safeIntlLocale() {
|
|
6891
|
-
try {
|
|
6892
|
-
return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
6893
|
-
} catch {
|
|
6894
|
-
return void 0;
|
|
6895
|
-
}
|
|
6896
|
-
}
|
|
6897
|
-
function messagesDir() {
|
|
6898
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
6899
|
-
const candidates = [resolve(here, "..", "..", "messages"), resolve(here, "..", "messages")];
|
|
6900
|
-
for (const c of candidates) {
|
|
6901
|
-
try {
|
|
6902
|
-
readFileSync(join(c, "en.json"), "utf8");
|
|
6903
|
-
return c;
|
|
6904
|
-
} catch {
|
|
6905
|
-
}
|
|
6906
|
-
}
|
|
6907
|
-
return resolve(process.cwd(), "messages");
|
|
6908
|
-
}
|
|
6909
|
-
function loadLocale(locale) {
|
|
6910
|
-
if (cache[locale]) return cache[locale];
|
|
6911
|
-
const path = join(messagesDir(), `${locale}.json`);
|
|
6912
|
-
try {
|
|
6913
|
-
const raw = readFileSync(path, "utf8");
|
|
6914
|
-
cache[locale] = JSON.parse(raw);
|
|
6915
|
-
} catch {
|
|
6916
|
-
cache[locale] = {};
|
|
6917
|
-
}
|
|
6918
|
-
return cache[locale];
|
|
6919
|
-
}
|
|
6920
|
-
function setLocale(locale) {
|
|
6921
|
-
if (!locale) return;
|
|
6922
|
-
const mapped = mapToSupported(locale);
|
|
6923
|
-
if (SUPPORTED.has(mapped)) currentLocale = mapped;
|
|
6924
|
-
}
|
|
6925
|
-
function getLocale() {
|
|
6926
|
-
if (currentLocale === null) currentLocale = detectLocale();
|
|
6927
|
-
return currentLocale;
|
|
6928
|
-
}
|
|
6929
|
-
function t(key, params) {
|
|
6930
|
-
const locale = getLocale();
|
|
6931
|
-
const primary = loadLocale(locale);
|
|
6932
|
-
let template = primary[key];
|
|
6933
|
-
if (template === void 0 && locale !== "en") {
|
|
6934
|
-
template = loadLocale("en")[key];
|
|
6935
|
-
}
|
|
6936
|
-
if (template === void 0) template = key;
|
|
6937
|
-
if (!params) return template;
|
|
6938
|
-
return template.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
|
|
6939
|
-
const v = params[name];
|
|
6940
|
-
return v === void 0 ? `{{${name}}}` : String(v);
|
|
6941
|
-
});
|
|
6942
|
-
}
|
|
6943
6974
|
|
|
6944
6975
|
// src/cli/audit-log.ts
|
|
6976
|
+
init_i18n();
|
|
6945
6977
|
init_harnessedRoot();
|
|
6946
6978
|
function auditPath() {
|
|
6947
6979
|
return harnessedFile("audit.log");
|
|
@@ -7048,6 +7080,9 @@ function registerAuditLog(program2) {
|
|
|
7048
7080
|
}
|
|
7049
7081
|
);
|
|
7050
7082
|
}
|
|
7083
|
+
|
|
7084
|
+
// src/cli/backup-list.ts
|
|
7085
|
+
init_i18n();
|
|
7051
7086
|
init_backup();
|
|
7052
7087
|
function registerBackupList(program2) {
|
|
7053
7088
|
const backup2 = program2.command("backup").description("Backup snapshot operations");
|
|
@@ -7283,6 +7318,7 @@ function registerCompact(program2) {
|
|
|
7283
7318
|
}
|
|
7284
7319
|
|
|
7285
7320
|
// src/cli/doctor.ts
|
|
7321
|
+
init_i18n();
|
|
7286
7322
|
init_doctor_registry();
|
|
7287
7323
|
function registerDoctor(program2) {
|
|
7288
7324
|
program2.command("doctor").description(
|
|
@@ -7439,6 +7475,9 @@ function fireEntry(clause, master) {
|
|
|
7439
7475
|
if (isMaster) entry.is_master = true;
|
|
7440
7476
|
return entry;
|
|
7441
7477
|
}
|
|
7478
|
+
|
|
7479
|
+
// src/cli/gc.ts
|
|
7480
|
+
init_i18n();
|
|
7442
7481
|
init_backup();
|
|
7443
7482
|
var DURATION_RE = /^(\d+)([dhmw])$/;
|
|
7444
7483
|
function parseDuration(s) {
|
|
@@ -7529,6 +7568,7 @@ ${t("gc.invalid_duration.fix")}`
|
|
|
7529
7568
|
|
|
7530
7569
|
// src/cli/install.ts
|
|
7531
7570
|
init_package();
|
|
7571
|
+
init_i18n();
|
|
7532
7572
|
init_installers();
|
|
7533
7573
|
init_path_guard();
|
|
7534
7574
|
init_validate();
|
|
@@ -7631,12 +7671,14 @@ function registerLearn(program2) {
|
|
|
7631
7671
|
|
|
7632
7672
|
// src/cli/lib/here.ts
|
|
7633
7673
|
init_nextStep();
|
|
7674
|
+
init_i18n();
|
|
7634
7675
|
init_harnessedRoot();
|
|
7635
7676
|
|
|
7636
7677
|
// src/cli/status.ts
|
|
7637
7678
|
init_evidence();
|
|
7638
7679
|
init_ledger();
|
|
7639
7680
|
init_state();
|
|
7681
|
+
init_i18n();
|
|
7640
7682
|
init_harnessedRoot();
|
|
7641
7683
|
init_state2();
|
|
7642
7684
|
function statusMarker(status) {
|
|
@@ -7803,6 +7845,9 @@ async function runHere(opts) {
|
|
|
7803
7845
|
}
|
|
7804
7846
|
process.exit(0);
|
|
7805
7847
|
}
|
|
7848
|
+
|
|
7849
|
+
// src/cli/manifest-add.ts
|
|
7850
|
+
init_i18n();
|
|
7806
7851
|
var QA = [
|
|
7807
7852
|
{ q: "\u2460 \u662F\u771F reusable surface \u8FD8\u662F\u4E34\u65F6 wrapper?", f: "q1_reusable_surface" },
|
|
7808
7853
|
{ q: "\u2461 \u4E0A\u6E38\u540D\u5B57 fit \u9879\u76EE shape \u5417? \u6709\u73B0\u6709\u547D\u540D\u51B2\u7A81\u5417?", f: "q2_name_fit" },
|
|
@@ -7874,6 +7919,8 @@ function registerNext(program2) {
|
|
|
7874
7919
|
}
|
|
7875
7920
|
|
|
7876
7921
|
// src/cli/prompt.ts
|
|
7922
|
+
init_i18n();
|
|
7923
|
+
init_localeYaml();
|
|
7877
7924
|
init_run();
|
|
7878
7925
|
init_generateCommands();
|
|
7879
7926
|
init_packagePath();
|
|
@@ -7919,16 +7966,17 @@ ${lines.join("\n")}
|
|
|
7919
7966
|
return "";
|
|
7920
7967
|
}
|
|
7921
7968
|
}
|
|
7922
|
-
async function buildDisciplinesSection(sub, packageRoot) {
|
|
7969
|
+
async function buildDisciplinesSection(sub, packageRoot, locale = getLocale()) {
|
|
7923
7970
|
try {
|
|
7924
7971
|
const workflowsDir = resolve(packageRoot, "workflows");
|
|
7972
|
+
const disciplinesDir = resolve(workflowsDir, "disciplines");
|
|
7925
7973
|
const applied = await loadSubArrayField(sub, packageRoot, "disciplines_applied");
|
|
7926
7974
|
const names = applied.filter((d) => d !== "language");
|
|
7927
7975
|
if (names.length === 0) return "";
|
|
7928
7976
|
const blocks = [];
|
|
7929
7977
|
for (const name of names) {
|
|
7930
7978
|
try {
|
|
7931
|
-
const dRaw = await readFile(
|
|
7979
|
+
const dRaw = await readFile(resolveLocaleYaml(disciplinesDir, name, locale), "utf8");
|
|
7932
7980
|
const dDoc = parse(dRaw);
|
|
7933
7981
|
const rules = Array.isArray(dDoc?.rules) ? dDoc.rules : [];
|
|
7934
7982
|
const descs = rules.map((r) => typeof r.description === "string" ? r.description.trim() : "").filter((s) => s.length > 0).map((s) => ` - ${s.replace(/\s+/g, " ")}`);
|
|
@@ -8074,6 +8122,9 @@ function registerReleasePreflight(program2) {
|
|
|
8074
8122
|
process.exit(failed ? 1 : 0);
|
|
8075
8123
|
});
|
|
8076
8124
|
}
|
|
8125
|
+
|
|
8126
|
+
// src/cli/research.ts
|
|
8127
|
+
init_i18n();
|
|
8077
8128
|
init_run();
|
|
8078
8129
|
init_packagePath();
|
|
8079
8130
|
init_run2();
|
|
@@ -8115,6 +8166,7 @@ function registerResearch(program2) {
|
|
|
8115
8166
|
}
|
|
8116
8167
|
|
|
8117
8168
|
// src/cli/resume.ts
|
|
8169
|
+
init_i18n();
|
|
8118
8170
|
function registerResume(program2) {
|
|
8119
8171
|
program2.command("resume").description(
|
|
8120
8172
|
"Reload checkpoint from paused workflow + print resume hint (D-03 \u2014 user invokes phase command manually)"
|
|
@@ -8179,6 +8231,9 @@ function registerRetro(program2) {
|
|
|
8179
8231
|
process.exit(0);
|
|
8180
8232
|
});
|
|
8181
8233
|
}
|
|
8234
|
+
|
|
8235
|
+
// src/cli/rollback.ts
|
|
8236
|
+
init_i18n();
|
|
8182
8237
|
init_backup();
|
|
8183
8238
|
function normalizeEol(buf, eol) {
|
|
8184
8239
|
const lf = buf.toString("utf8").replace(/\r\n/g, "\n");
|
|
@@ -8250,6 +8305,9 @@ ${t("rollback.metadata_unreadable.fix")}`
|
|
|
8250
8305
|
|
|
8251
8306
|
// src/cli.ts
|
|
8252
8307
|
init_run2();
|
|
8308
|
+
|
|
8309
|
+
// src/cli/setup.ts
|
|
8310
|
+
init_i18n();
|
|
8253
8311
|
init_platform();
|
|
8254
8312
|
|
|
8255
8313
|
// src/cli/lib/capabilityResolver.ts
|
|
@@ -8504,42 +8562,78 @@ async function enableUserLangInSettings(override) {
|
|
|
8504
8562
|
// src/cli/setup.ts
|
|
8505
8563
|
init_generateCommands();
|
|
8506
8564
|
init_packagePath();
|
|
8565
|
+
|
|
8566
|
+
// src/cli/lib/renderSkillTemplates.ts
|
|
8567
|
+
init_i18n();
|
|
8568
|
+
|
|
8569
|
+
// src/cli/lib/resolveSkillBody.ts
|
|
8570
|
+
init_i18n();
|
|
8571
|
+
function skillBodyFilename(locale) {
|
|
8572
|
+
return locale === "en" ? "SKILL.md" : `SKILL.${locale}.md`;
|
|
8573
|
+
}
|
|
8574
|
+
function resolveSkillBodyFilename(skillDir, locale) {
|
|
8575
|
+
const resolved = locale ?? getLocale();
|
|
8576
|
+
const candidate = skillBodyFilename(resolved);
|
|
8577
|
+
if (candidate === "SKILL.md") return "SKILL.md";
|
|
8578
|
+
return existsSync(join(skillDir, candidate)) ? candidate : "SKILL.md";
|
|
8579
|
+
}
|
|
8580
|
+
|
|
8581
|
+
// src/cli/lib/renderSkillTemplates.ts
|
|
8582
|
+
var LOCALE_SIBLINGS = ["zh-Hans"];
|
|
8507
8583
|
async function loadCapabilities(workflowsDir) {
|
|
8508
8584
|
const path = join(workflowsDir, "capabilities.yaml");
|
|
8509
8585
|
const raw = await readFile(path, "utf8");
|
|
8510
8586
|
const doc = parse(raw);
|
|
8511
8587
|
return doc?.capabilities ?? {};
|
|
8512
8588
|
}
|
|
8513
|
-
async function renderSkillFile(skillName, skillsBase, capabilities, installedPlugins, installedUserSkills) {
|
|
8514
|
-
const
|
|
8589
|
+
async function renderSkillFile(skillName, skillsBase, capabilities, installedPlugins, installedUserSkills, locale) {
|
|
8590
|
+
const dir = join(skillsBase, skillName);
|
|
8591
|
+
const resolved = locale ?? getLocale();
|
|
8592
|
+
const srcName = resolveSkillBodyFilename(dir, resolved);
|
|
8593
|
+
const srcPath = join(dir, srcName);
|
|
8594
|
+
const destPath = join(dir, "SKILL.md");
|
|
8515
8595
|
const result = {
|
|
8516
8596
|
name: skillName,
|
|
8517
|
-
skillPath,
|
|
8597
|
+
skillPath: destPath,
|
|
8518
8598
|
rendered: false,
|
|
8519
8599
|
warnings: []
|
|
8520
8600
|
};
|
|
8521
8601
|
let body;
|
|
8522
8602
|
try {
|
|
8523
|
-
body = await readFile(
|
|
8603
|
+
body = await readFile(srcPath, "utf8");
|
|
8524
8604
|
} catch (e) {
|
|
8525
8605
|
result.error = `read failed: ${e.message}`;
|
|
8526
8606
|
return result;
|
|
8527
8607
|
}
|
|
8528
8608
|
const rendered = renderSkillBody(body, capabilities, installedPlugins, installedUserSkills);
|
|
8529
|
-
|
|
8609
|
+
const localeBodySelected = srcName !== "SKILL.md";
|
|
8610
|
+
const needsWrite = localeBodySelected || rendered.body !== body;
|
|
8611
|
+
if (!needsWrite) {
|
|
8530
8612
|
result.warnings = rendered.warnings;
|
|
8531
8613
|
return result;
|
|
8532
8614
|
}
|
|
8533
8615
|
try {
|
|
8534
|
-
await writeFile(
|
|
8535
|
-
result.rendered =
|
|
8616
|
+
await writeFile(destPath, rendered.body, "utf8");
|
|
8617
|
+
result.rendered = rendered.body !== body;
|
|
8536
8618
|
result.warnings = rendered.warnings;
|
|
8537
8619
|
} catch (e) {
|
|
8538
8620
|
result.error = `write failed: ${e.message}`;
|
|
8621
|
+
return result;
|
|
8622
|
+
}
|
|
8623
|
+
if (localeBodySelected) {
|
|
8624
|
+
for (const loc of LOCALE_SIBLINGS) {
|
|
8625
|
+
const sibling = skillBodyFilename(loc);
|
|
8626
|
+
if (sibling === "SKILL.md") continue;
|
|
8627
|
+
try {
|
|
8628
|
+
await rm(join(dir, sibling), { force: true });
|
|
8629
|
+
} catch {
|
|
8630
|
+
}
|
|
8631
|
+
}
|
|
8539
8632
|
}
|
|
8540
8633
|
return result;
|
|
8541
8634
|
}
|
|
8542
|
-
async function renderAllSkills(skillNames, skillsBase, workflowsDir, homedirOverride) {
|
|
8635
|
+
async function renderAllSkills(skillNames, skillsBase, workflowsDir, homedirOverride, locale) {
|
|
8636
|
+
const resolvedLocale = locale ?? getLocale();
|
|
8543
8637
|
let capabilities = {};
|
|
8544
8638
|
try {
|
|
8545
8639
|
capabilities = await loadCapabilities(workflowsDir);
|
|
@@ -8567,7 +8661,8 @@ async function renderAllSkills(skillNames, skillsBase, workflowsDir, homedirOver
|
|
|
8567
8661
|
skillsBase,
|
|
8568
8662
|
capabilities,
|
|
8569
8663
|
installedPlugins,
|
|
8570
|
-
installedUserSkills
|
|
8664
|
+
installedUserSkills,
|
|
8665
|
+
resolvedLocale
|
|
8571
8666
|
);
|
|
8572
8667
|
results.push(r);
|
|
8573
8668
|
for (const w of r.warnings) warningSet.add(w);
|
|
@@ -8835,7 +8930,13 @@ function registerSetup(program2) {
|
|
|
8835
8930
|
}
|
|
8836
8931
|
console.log(t("setup.step_a_complete", { count: skillsInstalled, path: skillsBase }));
|
|
8837
8932
|
const skillNames = toInstall.map((wf) => wf.name);
|
|
8838
|
-
const rendered = await renderAllSkills(
|
|
8933
|
+
const rendered = await renderAllSkills(
|
|
8934
|
+
skillNames,
|
|
8935
|
+
skillsBase,
|
|
8936
|
+
workflowsDir,
|
|
8937
|
+
void 0,
|
|
8938
|
+
getLocale()
|
|
8939
|
+
);
|
|
8839
8940
|
if (rendered.aggregatedWarnings.length > 0) {
|
|
8840
8941
|
console.warn(t("setup.step_a_render.warnings_header"));
|
|
8841
8942
|
for (const w of rendered.aggregatedWarnings) {
|
|
@@ -8937,6 +9038,9 @@ Force-update pass complete: ${b2.installed.length} installed / ${b2.alreadyInsta
|
|
|
8937
9038
|
process.exit(0);
|
|
8938
9039
|
});
|
|
8939
9040
|
}
|
|
9041
|
+
|
|
9042
|
+
// src/cli/uninstall.ts
|
|
9043
|
+
init_i18n();
|
|
8940
9044
|
init_harnessedRoot();
|
|
8941
9045
|
init_path_guard();
|
|
8942
9046
|
init_validate();
|
|
@@ -9513,6 +9617,7 @@ function registerWorkflows(program2) {
|
|
|
9513
9617
|
}
|
|
9514
9618
|
|
|
9515
9619
|
// src/cli.ts
|
|
9620
|
+
init_i18n();
|
|
9516
9621
|
init_harnessedRoot();
|
|
9517
9622
|
migrateLegacyHarnessedRoot();
|
|
9518
9623
|
var argv = process.argv;
|