@vantagesec/socc 0.1.15 → 0.1.17

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/dist/cli.mjs CHANGED
@@ -112869,7 +112869,7 @@ function printStartupScreen() {
112869
112869
  const sLen = ` ● ${sL} Ready — type /help to begin`.length;
112870
112870
  out.push(boxRow(sRow, W2, sLen));
112871
112871
  out.push(`${rgb(...BORDER)}╚${"═".repeat(W2 - 2)}╝${RESET}`);
112872
- out.push(` ${DIM}${rgb(...DIMCOL)}socc ${RESET}${rgb(...ACCENT)}v${"0.1.15"}${RESET}`);
112872
+ out.push(` ${DIM}${rgb(...DIMCOL)}socc ${RESET}${rgb(...ACCENT)}v${"0.1.17"}${RESET}`);
112873
112873
  out.push("");
112874
112874
  process.stdout.write(out.join(`
112875
112875
  `) + `
@@ -373638,7 +373638,7 @@ function getAnthropicEnvMetadata() {
373638
373638
  function getBuildAgeMinutes() {
373639
373639
  if (false)
373640
373640
  ;
373641
- const buildTime = new Date("2026-04-13T17:17:55.615Z").getTime();
373641
+ const buildTime = new Date("2026-04-13T20:35:20.206Z").getTime();
373642
373642
  if (isNaN(buildTime))
373643
373643
  return;
373644
373644
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -400082,7 +400082,7 @@ function buildPrimarySection() {
400082
400082
  }, undefined, false, undefined, this);
400083
400083
  return [{
400084
400084
  label: "Version",
400085
- value: "0.1.15"
400085
+ value: "0.1.17"
400086
400086
  }, {
400087
400087
  label: "Session name",
400088
400088
  value: nameValue
@@ -466429,7 +466429,7 @@ var init_bridge_kick = __esm(() => {
466429
466429
  var call58 = async () => {
466430
466430
  return {
466431
466431
  type: "text",
466432
- value: `${"99.0.0"} (built ${"2026-04-13T17:17:55.615Z"})`
466432
+ value: `${"99.0.0"} (built ${"2026-04-13T20:35:20.206Z"})`
466433
466433
  };
466434
466434
  }, version2, version_default;
466435
466435
  var init_version = __esm(() => {
@@ -541037,7 +541037,7 @@ function WelcomeV2() {
541037
541037
  " ",
541038
541038
  /* @__PURE__ */ jsx_dev_runtime468.jsxDEV(ThemedText, {
541039
541039
  dimColor: true,
541040
- children: `v${"0.1.15"}`
541040
+ children: `v${"0.1.17"}`
541041
541041
  }, undefined, false, undefined, this)
541042
541042
  ]
541043
541043
  }, undefined, true, undefined, this),
@@ -557838,19 +557838,57 @@ var init_plugins = __esm(() => {
557838
557838
  init_stringUtils();
557839
557839
  });
557840
557840
 
557841
+ // src/utils/windowsWorkspace.ts
557842
+ import { mkdir as mkdir44 } from "node:fs/promises";
557843
+ import { homedir as homedir39 } from "node:os";
557844
+ import { join as join147, resolve as resolve43 } from "node:path";
557845
+ function getWindowsWorkspaceLayout(envLike = process.env) {
557846
+ if (env2.platform !== "win32") {
557847
+ return null;
557848
+ }
557849
+ const userProfile = envLike.USERPROFILE || envLike.HOME || homedir39();
557850
+ const configHome = envLike.SOCC_CONFIG_DIR && envLike.SOCC_CONFIG_DIR.trim().length > 0 ? resolve43(envLike.SOCC_CONFIG_DIR) : join147(userProfile, ".socc");
557851
+ const documentsDir = join147(userProfile, "Documents");
557852
+ return {
557853
+ configHome,
557854
+ documentsDir,
557855
+ generatedAlertsDir: join147(documentsDir, "Alertas_Gerados"),
557856
+ modelsDir: join147(documentsDir, "Modelos"),
557857
+ generatedNotesDir: join147(documentsDir, "Notas_Geradas"),
557858
+ trainingDir: join147(documentsDir, "Training")
557859
+ };
557860
+ }
557861
+ async function ensureWindowsWorkspaceLayout(envLike = process.env) {
557862
+ const layout = getWindowsWorkspaceLayout(envLike);
557863
+ if (!layout) {
557864
+ return null;
557865
+ }
557866
+ await Promise.all([
557867
+ mkdir44(layout.configHome, { recursive: true }),
557868
+ mkdir44(layout.generatedAlertsDir, { recursive: true }),
557869
+ mkdir44(layout.modelsDir, { recursive: true }),
557870
+ mkdir44(layout.generatedNotesDir, { recursive: true }),
557871
+ mkdir44(layout.trainingDir, { recursive: true })
557872
+ ]);
557873
+ return layout;
557874
+ }
557875
+ var init_windowsWorkspace = __esm(() => {
557876
+ init_env();
557877
+ });
557878
+
557841
557879
  // src/commands/install.tsx
557842
557880
  var exports_install = {};
557843
557881
  __export(exports_install, {
557844
557882
  install: () => install,
557845
557883
  getInstallationPath: () => getInstallationPath2
557846
557884
  });
557847
- import { homedir as homedir39 } from "node:os";
557848
- import { join as join147 } from "node:path";
557885
+ import { homedir as homedir40 } from "node:os";
557886
+ import { join as join148 } from "node:path";
557849
557887
  function getInstallationPath2() {
557850
557888
  const isWindows2 = env2.platform === "win32";
557851
- const homeDir = homedir39();
557889
+ const homeDir = homedir40();
557852
557890
  if (isWindows2) {
557853
- const windowsPath = join147(homeDir, ".local", "bin", "socc.exe");
557891
+ const windowsPath = join148(homeDir, ".local", "bin", "socc.exe");
557854
557892
  return windowsPath.replace(/\//g, "\\");
557855
557893
  }
557856
557894
  return "~/.local/bin/socc";
@@ -557958,6 +557996,10 @@ function Install({
557958
557996
  if (setupMessages.length > 0) {
557959
557997
  setupMessages.forEach((msg) => logForDebugging2(`Install: Setup message: ${msg.message}`));
557960
557998
  }
557999
+ const windowsWorkspace = await ensureWindowsWorkspaceLayout();
558000
+ if (windowsWorkspace) {
558001
+ logForDebugging2(`Install: Windows workspace ready at ${windowsWorkspace.documentsDir}`);
558002
+ }
557961
558003
  logForDebugging2("Install: Cleaning up npm installations after successful install");
557962
558004
  const {
557963
558005
  removed,
@@ -558170,6 +558212,7 @@ var init_install = __esm(() => {
558170
558212
  init_errors();
558171
558213
  init_nativeInstaller();
558172
558214
  init_settings2();
558215
+ init_windowsWorkspace();
558173
558216
  import_react_compiler_runtime373 = __toESM(require_dist3(), 1);
558174
558217
  import_react331 = __toESM(require_react(), 1);
558175
558218
  jsx_dev_runtime485 = __toESM(require_jsx_dev_runtime(), 1);
@@ -558210,7 +558253,7 @@ async function setupTokenHandler(root2) {
558210
558253
  const {
558211
558254
  ConsoleOAuthFlow: ConsoleOAuthFlow2
558212
558255
  } = await Promise.resolve().then(() => (init_ConsoleOAuthFlow(), exports_ConsoleOAuthFlow));
558213
- await new Promise((resolve43) => {
558256
+ await new Promise((resolve44) => {
558214
558257
  root2.render(/* @__PURE__ */ jsx_dev_runtime486.jsxDEV(AppStateProvider, {
558215
558258
  onChangeAppState,
558216
558259
  children: /* @__PURE__ */ jsx_dev_runtime486.jsxDEV(KeybindingSetup, {
@@ -558234,7 +558277,7 @@ async function setupTokenHandler(root2) {
558234
558277
  }, undefined, true, undefined, this),
558235
558278
  /* @__PURE__ */ jsx_dev_runtime486.jsxDEV(ConsoleOAuthFlow2, {
558236
558279
  onDone: () => {
558237
- resolve43();
558280
+ resolve44();
558238
558281
  },
558239
558282
  mode: "setup-token",
558240
558283
  startingMessage: "This will guide you through long-lived (1-year) auth token setup for your subscription-backed account. A subscription-backed login is required."
@@ -558270,7 +558313,7 @@ function DoctorWithPlugins(t0) {
558270
558313
  }
558271
558314
  async function doctorHandler(root2) {
558272
558315
  logEvent("tengu_doctor_command", {});
558273
- await new Promise((resolve43) => {
558316
+ await new Promise((resolve44) => {
558274
558317
  root2.render(/* @__PURE__ */ jsx_dev_runtime486.jsxDEV(AppStateProvider, {
558275
558318
  children: /* @__PURE__ */ jsx_dev_runtime486.jsxDEV(KeybindingSetup, {
558276
558319
  children: /* @__PURE__ */ jsx_dev_runtime486.jsxDEV(MCPConnectionManager, {
@@ -558278,7 +558321,7 @@ async function doctorHandler(root2) {
558278
558321
  isStrictMcpConfig: false,
558279
558322
  children: /* @__PURE__ */ jsx_dev_runtime486.jsxDEV(DoctorWithPlugins, {
558280
558323
  onDone: () => {
558281
- resolve43();
558324
+ resolve44();
558282
558325
  }
558283
558326
  }, undefined, false, undefined, this)
558284
558327
  }, undefined, false, undefined, this)
@@ -558296,14 +558339,14 @@ async function installHandler(target, options2) {
558296
558339
  const {
558297
558340
  install: install2
558298
558341
  } = await Promise.resolve().then(() => (init_install(), exports_install));
558299
- await new Promise((resolve43) => {
558342
+ await new Promise((resolve44) => {
558300
558343
  const args = [];
558301
558344
  if (target)
558302
558345
  args.push(target);
558303
558346
  if (options2.force)
558304
558347
  args.push("--force");
558305
558348
  install2.call((result) => {
558306
- resolve43();
558349
+ resolve44();
558307
558350
  process.exit(result.includes("failed") ? 1 : 0);
558308
558351
  }, {}, args);
558309
558352
  });
@@ -558749,7 +558792,7 @@ __export(exports_main, {
558749
558792
  });
558750
558793
  import { readFileSync as readFileSync11 } from "fs";
558751
558794
  import { fileURLToPath as fileURLToPath8 } from "url";
558752
- import { dirname as dirname62, resolve as resolve43 } from "path";
558795
+ import { dirname as dirname62, resolve as resolve44 } from "path";
558753
558796
  function logManagedSettings() {
558754
558797
  try {
558755
558798
  const policySettings = getSettingsForSource("policySettings");
@@ -559306,12 +559349,12 @@ ${getTmuxInstallInstructions2()}
559306
559349
  process.exit(1);
559307
559350
  }
559308
559351
  try {
559309
- const filePath = resolve43(options2.systemPromptFile);
559352
+ const filePath = resolve44(options2.systemPromptFile);
559310
559353
  systemPrompt = readFileSync11(filePath, "utf8");
559311
559354
  } catch (error42) {
559312
559355
  const code = getErrnoCode(error42);
559313
559356
  if (code === "ENOENT") {
559314
- process.stderr.write(source_default.red(`Error: System prompt file not found: ${resolve43(options2.systemPromptFile)}
559357
+ process.stderr.write(source_default.red(`Error: System prompt file not found: ${resolve44(options2.systemPromptFile)}
559315
559358
  `));
559316
559359
  process.exit(1);
559317
559360
  }
@@ -559328,12 +559371,12 @@ ${getTmuxInstallInstructions2()}
559328
559371
  process.exit(1);
559329
559372
  }
559330
559373
  try {
559331
- const filePath = resolve43(options2.appendSystemPromptFile);
559374
+ const filePath = resolve44(options2.appendSystemPromptFile);
559332
559375
  appendSystemPrompt = readFileSync11(filePath, "utf8");
559333
559376
  } catch (error42) {
559334
559377
  const code = getErrnoCode(error42);
559335
559378
  if (code === "ENOENT") {
559336
- process.stderr.write(source_default.red(`Error: Append system prompt file not found: ${resolve43(options2.appendSystemPromptFile)}
559379
+ process.stderr.write(source_default.red(`Error: Append system prompt file not found: ${resolve44(options2.appendSystemPromptFile)}
559337
559380
  `));
559338
559381
  process.exit(1);
559339
559382
  }
@@ -559379,7 +559422,7 @@ ${addendum}` : addendum;
559379
559422
  errors4 = result.errors;
559380
559423
  }
559381
559424
  } else {
559382
- const configPath = resolve43(configItem);
559425
+ const configPath = resolve44(configItem);
559383
559426
  const result = parseMcpConfigFromFilePath({
559384
559427
  filePath: configPath,
559385
559428
  expandVars: true,
@@ -560124,8 +560167,8 @@ ${customInstructions}` : customInstructions;
560124
560167
  return connectMcpBatch(dedupedRemoteConnectors, "claudeai");
560125
560168
  });
560126
560169
  let remoteConnectorTimer;
560127
- const remoteConnectorTimedOut = await Promise.race([remoteConnectorConnect.then(() => false), new Promise((resolve44) => {
560128
- remoteConnectorTimer = setTimeout((r) => r(true), REMOTE_CONNECTOR_MCP_TIMEOUT_MS, resolve44);
560170
+ const remoteConnectorTimedOut = await Promise.race([remoteConnectorConnect.then(() => false), new Promise((resolve45) => {
560171
+ remoteConnectorTimer = setTimeout((r) => r(true), REMOTE_CONNECTOR_MCP_TIMEOUT_MS, resolve45);
560129
560172
  })]);
560130
560173
  if (remoteConnectorTimer)
560131
560174
  clearTimeout(remoteConnectorTimer);
@@ -560703,7 +560746,7 @@ Usage: socc --remote "your task description"`, () => gracefulShutdown(1));
560703
560746
  pendingHookMessages
560704
560747
  }, renderAndRun);
560705
560748
  }
560706
- }).version("0.1.15 (SOCC)", "-v, --version", "Output the version number");
560749
+ }).version("0.1.17 (SOCC)", "-v, --version", "Output the version number");
560707
560750
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
560708
560751
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
560709
560752
  if (canUserConfigureAdvisor()) {
@@ -561187,7 +561230,7 @@ var init_main3 = __esm(() => {
561187
561230
  profileCheckpoint("main_tsx_entry");
561188
561231
  startMdmRawRead();
561189
561232
  startKeychainPrefetch();
561190
- process.env.SOCC_PACKAGE_ROOT ??= resolve43(dirname62(fileURLToPath8(import.meta.url)), "..");
561233
+ process.env.SOCC_PACKAGE_ROOT ??= resolve44(dirname62(fileURLToPath8(import.meta.url)), "..");
561191
561234
  profileCheckpoint("main_tsx_imports_loaded");
561192
561235
  if (isBeingDebugged()) {
561193
561236
  process.exit(1);
@@ -561334,7 +561377,7 @@ if (false) {}
561334
561377
  async function main2() {
561335
561378
  const args = process.argv.slice(2);
561336
561379
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
561337
- console.log(`${"0.1.15"} (SOCC)`);
561380
+ console.log(`${"0.1.17"} (SOCC)`);
561338
561381
  return;
561339
561382
  }
561340
561383
  if (args.includes("--provider")) {
@@ -561458,4 +561501,4 @@ async function main2() {
561458
561501
  }
561459
561502
  main2();
561460
561503
 
561461
- //# debugId=DE38E61A6917C2A564756E2164756E21
561504
+ //# debugId=D2B086382C3CA05E64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vantagesec/socc",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Security operations copiloto for threat intelligence, incident response, and agentic investigation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,7 @@
1
1
  import assert from 'node:assert/strict'
2
2
  import { createHash } from 'node:crypto'
3
3
  import { existsSync } from 'node:fs'
4
+ import { homedir } from 'node:os'
4
5
  import {
5
6
  cp,
6
7
  mkdir,
@@ -10,7 +11,7 @@ import {
10
11
  stat,
11
12
  writeFile,
12
13
  } from 'node:fs/promises'
13
- import { dirname, join, resolve } from 'node:path'
14
+ import { dirname, join, relative, resolve, sep } from 'node:path'
14
15
  import { fileURLToPath } from 'node:url'
15
16
 
16
17
  const SOC_CANONICAL_ROOT = ['socc-canonical', '.agents']
@@ -32,6 +33,105 @@ const RULE_RUNTIME_FILES = [
32
33
  { source: WORKFLOWS_DIR, file: 'SOP.md', title: 'IOC Handling SOP' },
33
34
  ]
34
35
 
36
+ function getWindowsWorkspaceLayout({
37
+ platform = process.platform,
38
+ env = process.env,
39
+ home = homedir(),
40
+ } = {}) {
41
+ if (platform !== 'win32') {
42
+ return null
43
+ }
44
+
45
+ const userProfile = env.USERPROFILE || env.HOME || home
46
+ const configHome =
47
+ env.SOCC_CONFIG_DIR && env.SOCC_CONFIG_DIR.trim().length > 0
48
+ ? resolve(env.SOCC_CONFIG_DIR)
49
+ : join(userProfile, '.socc')
50
+ const documentsDir = join(userProfile, 'Documents')
51
+
52
+ return {
53
+ userProfile,
54
+ configHome,
55
+ documentsDir,
56
+ generatedAlertsDir: join(documentsDir, 'Alertas_Gerados'),
57
+ modelsDir: join(documentsDir, 'Modelos'),
58
+ generatedNotesDir: join(documentsDir, 'Notas_Geradas'),
59
+ trainingDir: join(documentsDir, 'Training'),
60
+ }
61
+ }
62
+
63
+ export async function ensureWindowsWorkspaceLayout(options = {}) {
64
+ const layout = getWindowsWorkspaceLayout(options)
65
+ if (!layout) {
66
+ return null
67
+ }
68
+
69
+ await Promise.all([
70
+ mkdir(layout.configHome, { recursive: true }),
71
+ mkdir(layout.generatedAlertsDir, { recursive: true }),
72
+ mkdir(layout.modelsDir, { recursive: true }),
73
+ mkdir(layout.generatedNotesDir, { recursive: true }),
74
+ mkdir(layout.trainingDir, { recursive: true }),
75
+ ])
76
+
77
+ return layout
78
+ }
79
+
80
+ function applyWindowsWorkspacePaths(ruleBundle, workspaceLayout) {
81
+ if (!workspaceLayout) {
82
+ return ruleBundle
83
+ }
84
+
85
+ const configHomePath = 'USERPROFILE\\.socc'
86
+ const alertsPath = 'USERPROFILE\\Documents\\Alertas_Gerados'
87
+ const modelsPath = 'USERPROFILE\\Documents\\Modelos'
88
+ const notesPath = 'USERPROFILE\\Documents\\Notas_Geradas'
89
+ const trainingPath = 'USERPROFILE\\Documents\\Training'
90
+ const trainingPattern = `${trainingPath}\\Pensamento_Ofensa_*.md`
91
+ const trainingFilePath = `${trainingPath}\\Pensamento_Ofensa_[ID].md`
92
+
93
+ const replacements = [
94
+ ['`Modelos\\`', `\`${modelsPath}\``],
95
+ ['`Training\\Pensamento_Ofensa_*.md`', `\`${trainingPattern}\``],
96
+ ['`Training\\Pensamento_Ofensa_[ID].md`', `\`${trainingFilePath}\``],
97
+ ]
98
+
99
+ let rewrittenBundle = ruleBundle
100
+ for (const [from, to] of replacements) {
101
+ rewrittenBundle = rewrittenBundle.split(from).join(to)
102
+ }
103
+
104
+ return [
105
+ rewrittenBundle.trimEnd(),
106
+ '',
107
+ '## Windows Workspace Paths',
108
+ '',
109
+ '---',
110
+ 'trigger: always_on',
111
+ '---',
112
+ '',
113
+ '# Diretórios operacionais no Windows',
114
+ '',
115
+ 'No Windows, use estes diretórios como destino oficial dos artefatos do SOCC, sempre sob `USERPROFILE\\Documents`:',
116
+ '',
117
+ `- Configuração do usuário: \`${configHomePath}\``,
118
+ `- Alertas gerados: \`${alertsPath}\``,
119
+ `- Modelos do analista: \`${modelsPath}\``,
120
+ `- Notas geradas: \`${notesPath}\``,
121
+ `- Treinamento: \`${trainingPath}\``,
122
+ '',
123
+ 'Regras obrigatórias:',
124
+ '',
125
+ '1. Nunca use a pasta do repositório do SOCC como destino para alertas, notas, modelos ou arquivos de treinamento.',
126
+ `2. Consulte modelos somente em \`${modelsPath}\`.`,
127
+ `3. Salve alertas finais em \`${alertsPath}\`.`,
128
+ `4. Salve notas de encerramento em \`${notesPath}\`.`,
129
+ `5. Salve arquivos de treinamento em \`${trainingPath}\`.`,
130
+ '6. A pasta `.socc` do pacote é a referência final do runtime no Windows; `socc-canonical` não deve ser tratado como diretório operacional.',
131
+ '',
132
+ ].join('\n')
133
+ }
134
+
35
135
  function findPackageRoot(startDir) {
36
136
  let current = resolve(startDir)
37
137
 
@@ -177,7 +277,7 @@ ${parts.skill.trim()}
177
277
  `
178
278
  }
179
279
 
180
- async function buildRuntimeRules(packageRoot) {
280
+ async function buildRuntimeRules(packageRoot, options = {}) {
181
281
  const sections = []
182
282
  for (const section of RULE_RUNTIME_FILES) {
183
283
  const sourcePath = join(packageRoot, ...section.source, section.file)
@@ -194,10 +294,15 @@ async function buildRuntimeRules(packageRoot) {
194
294
 
195
295
  const runtimeRulesDir = join(packageRoot, ...RUNTIME_RULES_DIR)
196
296
  const runtimeRulesPath = join(runtimeRulesDir, 'socc-business-rules.md')
297
+ const workspaceLayout = getWindowsWorkspaceLayout(options)
197
298
 
198
299
  await rm(runtimeRulesDir, { recursive: true, force: true })
199
300
  await mkdir(runtimeRulesDir, { recursive: true })
200
- await writeFile(runtimeRulesPath, composeRuleBundle(sections), 'utf8')
301
+ await writeFile(
302
+ runtimeRulesPath,
303
+ applyWindowsWorkspacePaths(composeRuleBundle(sections), workspaceLayout),
304
+ 'utf8',
305
+ )
201
306
 
202
307
  return {
203
308
  runtimeRulesDir,
@@ -289,6 +394,9 @@ async function buildManifest({
289
394
  runtimeReferencesDir,
290
395
  runtimeSkills,
291
396
  }) {
397
+ const toManifestPath = path =>
398
+ relative(packageRoot, path).split(sep).join('/')
399
+
292
400
  const canonicalRoot = join(packageRoot, ...SOC_COPILOT_DIR)
293
401
  const sourceFiles = {
294
402
  identity: join(canonicalRoot, 'identity.md'),
@@ -308,24 +416,36 @@ async function buildManifest({
308
416
  const sourceBlocks = {}
309
417
  for (const [name, path] of Object.entries(sourceFiles)) {
310
418
  if (existsSync(path)) {
311
- sourceBlocks[name] = await fileMetadata(path)
419
+ const metadata = await fileMetadata(path)
420
+ sourceBlocks[name] = {
421
+ ...metadata,
422
+ path: toManifestPath(metadata.path),
423
+ }
312
424
  }
313
425
  }
314
426
 
315
427
  return {
316
428
  generatedAt: new Date().toISOString(),
317
- sourceRoot: canonicalRoot,
429
+ sourceRoot: toManifestPath(canonicalRoot),
318
430
  upstreamRoot: upstreamRoot || null,
319
- generatedAgentPath,
320
- generatedManifestPath,
321
- runtimeAgentPath,
322
- runtimeRulesPath,
323
- runtimeSkillsDir,
324
- runtimeReferencesDir,
431
+ generatedAgentPath: toManifestPath(generatedAgentPath),
432
+ generatedManifestPath: toManifestPath(generatedManifestPath),
433
+ runtimeAgentPath: toManifestPath(runtimeAgentPath),
434
+ runtimeRulesPath: toManifestPath(runtimeRulesPath),
435
+ runtimeSkillsDir: toManifestPath(runtimeSkillsDir),
436
+ runtimeReferencesDir: toManifestPath(runtimeReferencesDir),
325
437
  runtimeSkillNames: runtimeSkills.map(skill => skill.name),
326
- sourceFiles,
438
+ sourceFiles: Object.fromEntries(
439
+ Object.entries(sourceFiles).map(([name, path]) => [
440
+ name,
441
+ toManifestPath(path),
442
+ ]),
443
+ ),
327
444
  sourceBlocks,
328
- runtimeSkills,
445
+ runtimeSkills: runtimeSkills.map(skill => ({
446
+ ...skill,
447
+ path: toManifestPath(skill.path),
448
+ })),
329
449
  }
330
450
  }
331
451
 
@@ -365,8 +485,12 @@ export async function syncSoccSoul(
365
485
  {
366
486
  upstreamRoot = null,
367
487
  skillNames = null,
488
+ platform = process.platform,
489
+ env = process.env,
368
490
  } = {},
369
491
  ) {
492
+ await ensureWindowsWorkspaceLayout({ platform, env })
493
+
370
494
  if (upstreamRoot) {
371
495
  await syncSoccCanonicalFromUpstream(packageRoot, upstreamRoot)
372
496
  }
@@ -416,7 +540,10 @@ export async function syncSoccSoul(
416
540
  writeFile(runtimeAgentPath, prompt, 'utf8'),
417
541
  ])
418
542
 
419
- const runtimeRules = await buildRuntimeRules(packageRoot)
543
+ const runtimeRules = await buildRuntimeRules(packageRoot, {
544
+ platform,
545
+ env,
546
+ })
420
547
  const runtimeReferences = await buildRuntimeReferences(packageRoot)
421
548
  const runtimeSkills = await buildRuntimeSkills(packageRoot, skillNames)
422
549
 
@@ -471,6 +598,8 @@ async function main() {
471
598
  const packageRoot = findPackageRoot(scriptDir)
472
599
  const { upstreamRoot } = parseArgs(process.argv.slice(2))
473
600
 
601
+ await ensureWindowsWorkspaceLayout()
602
+
474
603
  if (!upstreamRoot && !hasCanonicalSource(packageRoot)) {
475
604
  if (!hasPackagedRuntime(packageRoot)) {
476
605
  throw new Error(