Lines 158-198javascript
158 try { const saved = json(join(root, 'prumo', '.prumo-install.json')).lang; if (['en', 'pt-BR'].includes(saved)) { lang = saved; break } } catch { /* no saved preference */ }
160 lang ??= language(undefined, env)
161 const result = { version: VERSION, harness, home, config, lang, groups: [], data: [], warnings: [], allowedRoots: [...new Set([config, ...targets])] }
163 function group(name, snapshots, build) {
164 const item = { name, snapshots, changes: [], conflicts: [] }
165 result.groups.push(item)
166 try { build(item) } catch (error) { item.changes = []; item.conflicts.push(error.message) }
169 const payload = bundle(lang)
170 for (const root of targets) {
171 const destination = join(root, 'prumo')
172 const legacy = join(root, 'graph-foreman')
173 group(`skill:${root}`, [destination, legacy], item => {
174 // Inspect full old directories before changing anything, including user-added files.
175 for (const folder of [destination, legacy]) { noLinks(folder); walk(folder) }
176 for (const [name, content] of payload) change(item, join(destination, name), content)
177 change(item, join(destination, '.prumo-install.json'), JSON.stringify({ product: 'prumo', version: VERSION, harness, lang }, null, 2) + '\n')
178 if (existsSync(legacy)) {
179 for (const name of ['engine.mjs', 'serve.mjs']) change(item, join(legacy, 'scripts', name), `#!/usr/bin/env node\n// Compatibility entrypoint. Run data and arguments stay unchanged.\nawait import(new URL('../../prumo/scripts/${name}', import.meta.url))\n`)
180 change(item, join(legacy, 'scripts', 'validation.mjs'), "export * from '../../prumo/scripts/validation.mjs'\n")
MediumDynamic Require
Package source references dynamic require/import behavior.
lib/install.mjsView on unpkg · L178 181 // An already-running legacy server still reads its original HTML path.
182 change(item, join(legacy, 'scripts', 'dashboard.html'), localizeDashboard(readFileSync(join(PACKAGE, 'scripts', 'dashboard.html'), 'utf8'), lang))
183 change(item, join(legacy, 'README.md'), '# Prumo\n\nThis directory preserves existing script paths. Use the adjacent `prumo` skill. Run data was not moved.\n')
184 change(item, join(legacy, 'SKILL.md'), '---\nname: graph-foreman\ndescription: Compatibility alias for existing graph-foreman invocations. New work uses the prumo skill.\n---\n\n# Prumo compatibility alias\n\nRead and follow [Prumo](../prumo/SKILL.md). Preserve the selected workspace, run, approved contract and current attempt. The scripts in this directory forward to Prumo. Do not initialize or migrate an existing run just because the product name changed.\n')
189 const po = readFileSync(join(PACKAGE, 'references', 'po-first.md'), 'utf8')
190 if (harness === 'claude') {
191 const style = join(config, 'output-styles', 'po-first.md')
192 const settings = join(config, 'settings.json')
193 group('po-first:claude', [style, settings], item => {
194 change(item, style, `---\nname: PO First\ndescription: Product outcomes, observable behavior and proportionate execution\nkeep-coding-instructions: true\n---\n\n${po}`)
195 settingsChange(item, settings, value => { value.outputStyle = 'PO First' })
197 for (const root of search) for (const name of ['settings.json', 'settings.local.json']) {
198 const file = join(root, '.claude', name)