mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
chore(torch): update package and sanitize colon timestamps
This commit is contained in:
1 parent
5e01d04e1d
commit
25b590647b
46 files changed
+356
-42
No files matched your search
@@ -692,3 +692,8 @@ Please read these documents next.
|
||||
And if you need to create new nostr kinds please keep the logic centralized there in `nostrEventSchemas.js` and the `nostr-event-schemas.md` up to date.
|
||||
|
||||
**End of AGENTS.md**
|
||||
|
||||
## TORCH Memory Integration
|
||||
You have access to the TORCH memory system.
|
||||
1. READ: Check `.scheduler-memory/latest/${cadence}/memories.md` for past learnings.
|
||||
2. WRITE: Before exiting, save new insights to `memory-update.md` so future runs can learn from this session.
|
||||
@@ -636,3 +636,8 @@ Validation: Must have `title` + at least one of `url` or `magnet`.
|
||||
5. **Token-first styling** — no raw colors, no inline styles
|
||||
6. **Keep magnets raw** — decode only at playback time
|
||||
7. **Document rollback steps** — especially for playback changes
|
||||
|
||||
## TORCH Memory Integration
|
||||
You have access to the TORCH memory system.
|
||||
1. READ: Check `.scheduler-memory/latest/${cadence}/memories.md` for past learnings.
|
||||
2. WRITE: Before exiting, save new insights to `memory-update.md` so future runs can learn from this session.
|
||||
Generated
+3
-3
@@ -17,7 +17,7 @@
|
||||
"nostr-tools": "^2.19.4",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"torch-lock": "https://github.com/PR0M3TH3AN/TORCH/archive/b5023799d34ee0f7064c2d0f0591aef22eaa2288.tar.gz",
|
||||
"torch-lock": "https://github.com/PR0M3TH3AN/TORCH/archive/1e3f88e.tar.gz",
|
||||
"ws": "^8.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -6106,8 +6106,8 @@
|
||||
},
|
||||
"node_modules/torch-lock": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://github.com/PR0M3TH3AN/TORCH/archive/b5023799d34ee0f7064c2d0f0591aef22eaa2288.tar.gz",
|
||||
"integrity": "sha512-HpA3zjTulnNR8WRTfE+4SzGKsHlVMu+wqloFXU3Zotm3z2+YC+ucZPjkBzZ6hgGCM1NS2vCiwnNW8Xwdt2X7cQ==",
|
||||
"resolved": "https://github.com/PR0M3TH3AN/TORCH/archive/1e3f88e.tar.gz",
|
||||
"integrity": "sha512-iAA5mMXf0BT6NsAUprd4QldSJtT3NayfN7eORCGkRI+v3hNV9lJtMOkfu2xAlERKk9wvV8GBSMNjYF8R6KsQTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nostr-tools": "2.23.1",
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@
|
||||
"nostr-tools": "^2.19.4",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"torch-lock": "https://github.com/PR0M3TH3AN/TORCH/archive/b5023799d34ee0f7064c2d0f0591aef22eaa2288.tar.gz",
|
||||
"torch-lock": "https://github.com/PR0M3TH3AN/TORCH/archive/1e3f88e.tar.gz",
|
||||
"ws": "^8.19.0"
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ npx --no-install torch-lock check --cadence daily
|
||||
npx --no-install torch-lock dashboard --port 4173 --host 127.0.0.1
|
||||
```
|
||||
|
||||
`torch-lock init` and `torch-lock update` now auto-upsert the `## TORCH Memory Integration` block into root-level `AGENTS.md` and `CLAUDE.md` (and create `AGENTS.md` if neither file exists).
|
||||
|
||||
> TORCH is distributed from GitHub tarballs and is not currently published to the npm registry.
|
||||
> Use pinned commit tarballs (`archive/<commit-sha>.tar.gz`) for repeatable installs. Avoid `refs/heads/main.tar.gz` for production rollouts.
|
||||
|
||||
@@ -119,6 +121,9 @@ npx --no-install torch-lock init
|
||||
# Update TORCH configuration and scripts
|
||||
npx --no-install torch-lock update
|
||||
|
||||
# Validate setup and print actionable fixes
|
||||
npx --no-install torch-lock doctor
|
||||
|
||||
# Remove TORCH completely from this project
|
||||
npx --no-install torch-lock remove
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+15
-38
@@ -938,9 +938,9 @@
|
||||
</div>
|
||||
|
||||
<p class="install-label" style="margin-top: 1rem;">Copy this happy-path prompt to onboard TORCH:</p>
|
||||
<p class="text-muted" style="margin-top: 0; margin-bottom: 0.75rem; font-size: 0.85rem;">Requires Node.js 22+.</p>
|
||||
<p class="text-muted" style="margin-top: 0; margin-bottom: 0.75rem; font-size: 0.85rem;">Requires Node.js 22+. `init` also hooks TORCH memory instructions into AGENTS.md / CLAUDE.md.</p>
|
||||
<div class="install-code-wrapper multiline">
|
||||
<code id="install-cmd">Hey Jules, can you install and setup TORCH into this repo? Here is the install command:
|
||||
<code id="install-cmd">Hey Jules, can you install and setup TORCH into this repo in one pass? Please run this command:
|
||||
|
||||
npm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init</code>
|
||||
<button class="copy-install-btn" onclick="copyToClipboard('install-cmd', this, true)">
|
||||
@@ -1022,27 +1022,6 @@ npm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz &
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="hook-memory scroll-reveal" style="max-width: 800px; margin: 4rem auto; padding: 0 2rem; text-align: center;">
|
||||
<h2 style="font-size: 2rem; margin-bottom: 1.5rem; color: var(--text-strong);">Hook memory into your existing agents</h2>
|
||||
<p style="font-size: 1.1rem; color: var(--muted); margin-bottom: 2rem; line-height: 1.6;">
|
||||
Add these instructions to your agent's system prompt (e.g. in <code>AGENTS.md</code> or <code>CLAUDE.md</code>) to enable the TORCH memory system.
|
||||
</p>
|
||||
|
||||
<div class="install-code-wrapper multiline" style="margin: 0 auto; text-align: left;">
|
||||
<code id="memory-hook-code">## TORCH Memory Integration
|
||||
You have access to the TORCH memory system.
|
||||
1. READ: Check `.scheduler-memory/latest/${cadence}/memories.md` for past learnings.
|
||||
2. WRITE: Before exiting, save new insights to `memory-update.md` so future runs can learn from this session.</code>
|
||||
<button class="copy-install-btn" onclick="copyToClipboard('memory-hook-code', this)">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="meta-prompts scroll-reveal">
|
||||
<h2>Scheduler Meta Prompts</h2>
|
||||
<div class="prompts-grid">
|
||||
@@ -1637,21 +1616,19 @@ You have access to the TORCH memory system.
|
||||
// Update prompt text
|
||||
const installCmd = document.getElementById('install-cmd');
|
||||
let promptText = '';
|
||||
|
||||
if (agent === 'jules') {
|
||||
promptText = "Hey Jules, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'codex') {
|
||||
promptText = "Hey Codex, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'opencode') {
|
||||
promptText = "Hey OpenCode, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'claude') {
|
||||
promptText = "Hey Claude, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'gemini') {
|
||||
promptText = "Hey Gemini, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'qwen') {
|
||||
promptText = "Hey Qwen, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
} else if (agent === 'antigravity') {
|
||||
promptText = "Hey Antigravity, can you install and setup TORCH into this repo? Here is the install command:\n\nnpm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init";
|
||||
const agentLabelById = {
|
||||
jules: 'Jules',
|
||||
codex: 'Codex',
|
||||
opencode: 'OpenCode',
|
||||
claude: 'Claude',
|
||||
gemini: 'Gemini',
|
||||
qwen: 'Qwen',
|
||||
antigravity: 'Antigravity',
|
||||
};
|
||||
const installCommand = 'npm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz && npx --no-install torch-lock init';
|
||||
const agentLabel = agentLabelById[agent];
|
||||
if (agentLabel) {
|
||||
promptText = `Hey ${agentLabel}, can you install and setup TORCH into this repo in one pass? Please run this command:\n\n${installCommand}`;
|
||||
}
|
||||
|
||||
if (installCmd) {
|
||||
|
||||
@@ -26,6 +26,8 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
- `docs/agent-handoffs/README.md`
|
||||
- Recent notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`
|
||||
2. **Update run artifacts** in `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/` during the run, or explicitly document why each artifact update is not needed for that run.
|
||||
- When creating filenames with `<timestamp>`, use the scheduler-provided `SCHEDULER_RUN_TIMESTAMP` value when available.
|
||||
- Required filename-safe format: `YYYY-MM-DDTHH-MM-SSZ` (for example `2026-02-15T01-03-31Z`); never use `:` in filenames.
|
||||
3. **Capture reusable failures and unresolved issues**:
|
||||
- Record reusable failures in `docs/agent-handoffs/incidents/`
|
||||
- Record active unresolved reproducible items in `KNOWN_ISSUES.md`
|
||||
|
||||
@@ -889,6 +889,7 @@ async function main() {
|
||||
schedulerRunState.lock_deferral = null;
|
||||
await writeRunState(runStatePath, schedulerRunState);
|
||||
const runArtifactSince = new Date().toISOString();
|
||||
const runArtifactTimestamp = ts();
|
||||
const runStartMs = Date.parse(runArtifactSince);
|
||||
const outputChunks = [];
|
||||
|
||||
@@ -904,6 +905,7 @@ async function main() {
|
||||
SCHEDULER_CADENCE: cadence,
|
||||
SCHEDULER_PROMPT_PATH: promptPath,
|
||||
SCHEDULER_MEMORY_FILE: memoryFile,
|
||||
SCHEDULER_RUN_TIMESTAMP: runArtifactTimestamp,
|
||||
};
|
||||
|
||||
if (schedulerConfig.memoryPolicy.retrieveCommand) {
|
||||
|
||||
@@ -133,6 +133,14 @@ function getMatchingArtifacts(files, { expectedPrefix, session }) {
|
||||
return files.filter((file) => file.name.startsWith(expectedPrefix));
|
||||
}
|
||||
|
||||
function findInvalidFilenameCharacters(files) {
|
||||
// Windows-invalid filename characters: <>:"/\|?*
|
||||
const invalidCharRe = /[<>:"/\\|?*]/;
|
||||
return files
|
||||
.filter((file) => invalidCharRe.test(file.name))
|
||||
.map((file) => file.name);
|
||||
}
|
||||
|
||||
async function hasValidArtifactStructure(files, artifact) {
|
||||
for (const file of files) {
|
||||
const content = await fs.readFile(file.filePath, 'utf8').catch(() => '');
|
||||
@@ -336,6 +344,11 @@ async function main() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const invalidFilenames = findInvalidFilenameCharacters(matchingArtifacts);
|
||||
if (invalidFilenames.length) {
|
||||
missing.push(`${artifact.dir}: invalid filename characters for cross-platform sync in ${invalidFilenames.join(', ')}`);
|
||||
}
|
||||
|
||||
const hasValidStructure = await hasValidArtifactStructure(matchingArtifacts, artifact);
|
||||
if (!hasValidStructure) {
|
||||
missing.push(`${artifact.dir}: ${artifact.structureHint}`);
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { detectTorchInstallDir } from './cmd-remove.mjs';
|
||||
|
||||
const MEMORY_HEADING = '## TORCH Memory Integration';
|
||||
const MEMORY_READ_LINE = '`.scheduler-memory/latest/${cadence}/memories.md`';
|
||||
const MEMORY_WRITE_LINE = '`memory-update.md`';
|
||||
|
||||
function parseMajorNodeVersion(version) {
|
||||
const major = Number.parseInt(String(version).split('.')[0], 10);
|
||||
return Number.isFinite(major) ? major : null;
|
||||
}
|
||||
|
||||
function createCheck(id, status, summary, fix = null) {
|
||||
return { id, status, summary, fix };
|
||||
}
|
||||
|
||||
function hasMemoryHook(content) {
|
||||
return content.includes(MEMORY_HEADING)
|
||||
&& content.includes(MEMORY_READ_LINE)
|
||||
&& content.includes(MEMORY_WRITE_LINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs setup and install diagnostics for a TORCH-enabled repository.
|
||||
*
|
||||
* @param {Object} [opts]
|
||||
* @param {string} [opts.cwd]
|
||||
* @param {string} [opts.nodeVersion]
|
||||
* @returns {{
|
||||
* ok: boolean,
|
||||
* summary: { passed: number, warned: number, failed: number },
|
||||
* checks: Array<{ id: string, status: 'pass'|'warn'|'fail', summary: string, fix: string|null }>
|
||||
* }}
|
||||
*/
|
||||
export function runDoctorChecks(opts = {}) {
|
||||
const cwd = opts.cwd || process.cwd();
|
||||
const nodeVersion = opts.nodeVersion || process.versions.node;
|
||||
const checks = [];
|
||||
|
||||
const nodeMajor = parseMajorNodeVersion(nodeVersion);
|
||||
if (nodeMajor !== null && nodeMajor >= 22) {
|
||||
checks.push(createCheck('node-version', 'pass', `Node.js ${nodeVersion} meets requirement (>= 22).`));
|
||||
} else {
|
||||
checks.push(createCheck(
|
||||
'node-version',
|
||||
'fail',
|
||||
`Node.js ${nodeVersion} is below requirement (>= 22).`,
|
||||
'Install Node.js 22+ and rerun `npx --no-install torch-lock doctor`.',
|
||||
));
|
||||
}
|
||||
|
||||
const installDir = detectTorchInstallDir(cwd);
|
||||
if (!installDir) {
|
||||
checks.push(createCheck(
|
||||
'install-detection',
|
||||
'fail',
|
||||
'No TORCH installation detected.',
|
||||
'Run `npm install <torch-tarball> --force && npx --no-install torch-lock init`.',
|
||||
));
|
||||
} else {
|
||||
const installLabel = installDir === '.' ? 'root install (.)' : `${installDir}/`;
|
||||
checks.push(createCheck('install-detection', 'pass', `Detected TORCH install at ${installLabel}.`));
|
||||
}
|
||||
|
||||
const configPath = path.join(cwd, 'torch-config.json');
|
||||
let config = null;
|
||||
if (!fs.existsSync(configPath)) {
|
||||
checks.push(createCheck(
|
||||
'torch-config',
|
||||
'fail',
|
||||
'Missing torch-config.json in project root.',
|
||||
'Run `npx --no-install torch-lock init --force` or `npx --no-install torch-lock update --force`.',
|
||||
));
|
||||
} else {
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
checks.push(createCheck('torch-config', 'pass', 'torch-config.json exists and parses as JSON.'));
|
||||
} catch (error) {
|
||||
checks.push(createCheck(
|
||||
'torch-config',
|
||||
'fail',
|
||||
`torch-config.json is invalid JSON: ${error.message}`,
|
||||
'Fix JSON syntax or regenerate with `npx --no-install torch-lock update --force`.',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (config) {
|
||||
const dailyHandoff = config?.scheduler?.handoffCommandByCadence?.daily;
|
||||
const weeklyHandoff = config?.scheduler?.handoffCommandByCadence?.weekly;
|
||||
if (dailyHandoff && weeklyHandoff) {
|
||||
checks.push(createCheck('handoff-config', 'pass', 'Scheduler handoff commands are configured for daily and weekly.'));
|
||||
} else {
|
||||
checks.push(createCheck(
|
||||
'handoff-config',
|
||||
'fail',
|
||||
'Scheduler handoff command is missing for daily and/or weekly cadence.',
|
||||
'Run `npx --no-install torch-lock update --force` to rehydrate scheduler config.',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (installDir) {
|
||||
const installRoot = path.resolve(cwd, installDir);
|
||||
const expectedPaths = [
|
||||
path.join(installRoot, 'roster.json'),
|
||||
path.join(installRoot, 'prompts', 'daily'),
|
||||
path.join(installRoot, 'prompts', 'weekly'),
|
||||
path.join(installRoot, 'scripts', 'agent', 'run-selected-prompt.mjs'),
|
||||
];
|
||||
const missing = expectedPaths.filter((targetPath) => !fs.existsSync(targetPath));
|
||||
if (missing.length === 0) {
|
||||
checks.push(createCheck('install-files', 'pass', 'Core TORCH install files are present.'));
|
||||
} else {
|
||||
const missingRel = missing.map((targetPath) => path.relative(cwd, targetPath)).join(', ');
|
||||
checks.push(createCheck(
|
||||
'install-files',
|
||||
'fail',
|
||||
`Missing install artifacts: ${missingRel}`,
|
||||
'Run `npx --no-install torch-lock update --force` to repair copied files.',
|
||||
));
|
||||
}
|
||||
|
||||
const nodeModulesPath = path.join(installRoot, 'node_modules');
|
||||
if (fs.existsSync(nodeModulesPath)) {
|
||||
checks.push(createCheck('install-deps', 'pass', `${path.relative(cwd, nodeModulesPath)} exists.`));
|
||||
} else {
|
||||
checks.push(createCheck(
|
||||
'install-deps',
|
||||
'warn',
|
||||
`${path.relative(cwd, nodeModulesPath)} is missing; TORCH package dependencies may not be installed yet.`,
|
||||
`Run \`npm install --prefix ${installDir === '.' ? '.' : installDir}\`.`,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
const promptFiles = ['AGENTS.md', 'CLAUDE.md']
|
||||
.map((name) => ({ name, filePath: path.join(cwd, name) }))
|
||||
.filter((entry) => fs.existsSync(entry.filePath));
|
||||
|
||||
if (promptFiles.length === 0) {
|
||||
checks.push(createCheck(
|
||||
'memory-hook',
|
||||
'warn',
|
||||
'No AGENTS.md or CLAUDE.md found in repository root.',
|
||||
'Run `npx --no-install torch-lock update --force` to create/update agent prompt hooks.',
|
||||
));
|
||||
} else {
|
||||
const withHook = [];
|
||||
const withoutHook = [];
|
||||
for (const entry of promptFiles) {
|
||||
const content = fs.readFileSync(entry.filePath, 'utf8');
|
||||
if (hasMemoryHook(content)) {
|
||||
withHook.push(entry.name);
|
||||
} else {
|
||||
withoutHook.push(entry.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (withHook.length > 0 && withoutHook.length === 0) {
|
||||
checks.push(createCheck('memory-hook', 'pass', `Memory hook present in: ${withHook.join(', ')}.`));
|
||||
} else if (withHook.length > 0) {
|
||||
checks.push(createCheck(
|
||||
'memory-hook',
|
||||
'warn',
|
||||
`Memory hook present in ${withHook.join(', ')} but missing in ${withoutHook.join(', ')}.`,
|
||||
'Run `npx --no-install torch-lock update --force` to upsert missing prompt hooks.',
|
||||
));
|
||||
} else {
|
||||
checks.push(createCheck(
|
||||
'memory-hook',
|
||||
'fail',
|
||||
`Memory hook missing from: ${withoutHook.join(', ')}.`,
|
||||
'Run `npx --no-install torch-lock update --force` to inject TORCH memory integration.',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
const summary = {
|
||||
passed: checks.filter((check) => check.status === 'pass').length,
|
||||
warned: checks.filter((check) => check.status === 'warn').length,
|
||||
failed: checks.filter((check) => check.status === 'fail').length,
|
||||
};
|
||||
|
||||
return {
|
||||
ok: summary.failed === 0,
|
||||
summary,
|
||||
checks,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a human-readable setup diagnostic report.
|
||||
*
|
||||
* @param {Object} [opts]
|
||||
* @param {string} [opts.cwd]
|
||||
* @param {boolean} [opts.json]
|
||||
* @param {Function} [opts.log]
|
||||
* @returns {ReturnType<typeof runDoctorChecks>}
|
||||
*/
|
||||
export function cmdDoctor(opts = {}) {
|
||||
const {
|
||||
cwd = process.cwd(),
|
||||
json = false,
|
||||
log = console.log,
|
||||
} = opts;
|
||||
|
||||
const report = runDoctorChecks({ cwd, nodeVersion: opts.nodeVersion });
|
||||
if (json) {
|
||||
log(JSON.stringify(report, null, 2));
|
||||
return report;
|
||||
}
|
||||
|
||||
log('TORCH Doctor Report');
|
||||
log(`Root: ${cwd}`);
|
||||
for (const check of report.checks) {
|
||||
const badge = check.status === 'pass' ? '[PASS]' : check.status === 'warn' ? '[WARN]' : '[FAIL]';
|
||||
log(`${badge} ${check.id}: ${check.summary}`);
|
||||
}
|
||||
|
||||
log('');
|
||||
log(`Summary: ${report.summary.passed} passed, ${report.summary.warned} warned, ${report.summary.failed} failed.`);
|
||||
if (report.summary.warned > 0 || report.summary.failed > 0) {
|
||||
log('Recommended fixes:');
|
||||
for (const check of report.checks.filter((item) => item.status !== 'pass' && item.fix)) {
|
||||
log(`- ${check.fix}`);
|
||||
}
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
@@ -45,6 +45,7 @@ Commands:
|
||||
list [--cadence <daily|weekly>] Print active lock table
|
||||
health --cadence <daily|weekly> Probe relay websocket + publish/read health
|
||||
dashboard [--port <port>] [--host <host>] Serve the dashboard (default: ${DEFAULT_DASHBOARD_PORT})
|
||||
doctor [--json] Validate local TORCH setup and print fixes
|
||||
init [--force] Initialize torch/ directory in current project
|
||||
update [--force] Update torch/ configuration (backups, merges)
|
||||
remove [--force] Remove all TORCH files and configuration from project
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -44,6 +44,7 @@ import { cmdRollback } from './cmd-rollback.mjs';
|
||||
import { cmdCheck } from './cmd-check.mjs';
|
||||
import { cmdList } from './cmd-list.mjs';
|
||||
import { cmdComplete } from './cmd-complete.mjs';
|
||||
import { cmdDoctor } from './cmd-doctor.mjs';
|
||||
|
||||
useWebSocketImplementation(WebSocket);
|
||||
|
||||
@@ -308,6 +309,12 @@ const COMMAND_HANDLERS = {
|
||||
dashboard: async (args) => {
|
||||
await cmdDashboard(args.port, args.host);
|
||||
},
|
||||
doctor: async (args) => {
|
||||
const report = cmdDoctor({ json: args.json });
|
||||
if (!report.ok) {
|
||||
throw new ExitError(2, 'Doctor found setup failures');
|
||||
}
|
||||
},
|
||||
init: async (args) => {
|
||||
await cmdInit(args.force);
|
||||
},
|
||||
|
||||
@@ -54,6 +54,12 @@ const APP_DIRS = ['src', 'bin', 'dashboard', 'landing', 'assets', 'scripts'];
|
||||
|
||||
/** Individual files to sync from package root to install directory. */
|
||||
const APP_FILES = ['package.json', 'build.mjs', 'README.md', 'torch-config.example.json', 'TORCH.md', 'eslint.config.mjs'];
|
||||
const MEMORY_PROMPT_FILES = ['AGENTS.md', 'CLAUDE.md'];
|
||||
const MEMORY_INTEGRATION_HEADING = '## TORCH Memory Integration';
|
||||
const MEMORY_INTEGRATION_BLOCK = `${MEMORY_INTEGRATION_HEADING}
|
||||
You have access to the TORCH memory system.
|
||||
1. READ: Check \`.scheduler-memory/latest/\${cadence}/memories.md\` for past learnings.
|
||||
2. WRITE: Before exiting, save new insights to \`memory-update.md\` so future runs can learn from this session.`;
|
||||
|
||||
/**
|
||||
* Resolves the absolute paths for the installation.
|
||||
@@ -478,6 +484,61 @@ function injectHostScriptsIfNeeded(paths, installDir) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upserts the TORCH memory integration section inside a system prompt file.
|
||||
*
|
||||
* @param {string} content - Existing file content.
|
||||
* @returns {string} Updated file content.
|
||||
*/
|
||||
function upsertMemoryIntegrationBlock(content) {
|
||||
if (content.includes(MEMORY_INTEGRATION_BLOCK)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const escapedHeading = MEMORY_INTEGRATION_HEADING.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const sectionRegex = new RegExp(`(^|\\n)${escapedHeading}\\n[\\s\\S]*?(?=\\n##\\s|$)`, 'm');
|
||||
|
||||
if (sectionRegex.test(content)) {
|
||||
return content.replace(sectionRegex, (_match, prefix) => `${prefix}${MEMORY_INTEGRATION_BLOCK}`);
|
||||
}
|
||||
|
||||
const trimmed = content.trimEnd();
|
||||
if (!trimmed) {
|
||||
return `${MEMORY_INTEGRATION_BLOCK}\n`;
|
||||
}
|
||||
return `${trimmed}\n\n${MEMORY_INTEGRATION_BLOCK}\n`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures AGENTS/CLAUDE system prompt files include TORCH memory integration.
|
||||
* If neither file exists, creates AGENTS.md with the integration block.
|
||||
*
|
||||
* @param {string} root - Host project root.
|
||||
*/
|
||||
function ensureMemoryPromptHook(root) {
|
||||
const existingTargets = MEMORY_PROMPT_FILES.filter((file) => fs.existsSync(path.join(root, file)));
|
||||
|
||||
if (existingTargets.length === 0) {
|
||||
const defaultPath = path.join(root, 'AGENTS.md');
|
||||
fs.writeFileSync(defaultPath, `${MEMORY_INTEGRATION_BLOCK}\n`, 'utf8');
|
||||
console.log(`Created ${path.relative(root, defaultPath)} with TORCH memory integration.`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const file of existingTargets) {
|
||||
const filePath = path.join(root, file);
|
||||
const current = fs.readFileSync(filePath, 'utf8');
|
||||
const next = upsertMemoryIntegrationBlock(current);
|
||||
|
||||
if (next !== current) {
|
||||
fs.writeFileSync(filePath, next, 'utf8');
|
||||
console.log(`Updated ${path.relative(root, filePath)} with TORCH memory integration.`);
|
||||
} else {
|
||||
console.log(`TORCH memory integration already present in ${path.relative(root, filePath)}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point for `torch-lock init`.
|
||||
*
|
||||
@@ -505,6 +566,7 @@ export async function cmdInit(force = false, cwd = process.cwd(), mockAnswers =
|
||||
configureTorch(cwd, paths, installDir, namespace, relays, hashtag);
|
||||
const dashboardUrl = createDashboardLinkFile(paths, namespace, relays, hashtag);
|
||||
injectHostScriptsIfNeeded(paths, installDir);
|
||||
ensureMemoryPromptHook(paths.root);
|
||||
|
||||
console.log('\nInitialization complete.');
|
||||
console.log('You can now customize the files in ' + path.relative(cwd, paths.torchDir) + '/');
|
||||
@@ -712,5 +774,6 @@ export function cmdUpdate(force = false, cwd = process.cwd()) {
|
||||
}
|
||||
}
|
||||
|
||||
ensureMemoryPromptHook(paths.root);
|
||||
console.log('\nUpdate complete.');
|
||||
}
|
||||
@@ -26,6 +26,8 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
- `docs/agent-handoffs/README.md`
|
||||
- Recent notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`
|
||||
2. **Update run artifacts** in `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/` during the run, or explicitly document why each artifact update is not needed for that run.
|
||||
- When creating filenames with `<timestamp>`, use the scheduler-provided `SCHEDULER_RUN_TIMESTAMP` value when available.
|
||||
- Required filename-safe format: `YYYY-MM-DDTHH-MM-SSZ` (for example `2026-02-15T01-03-31Z`); never use `:` in filenames.
|
||||
3. **Capture reusable failures and unresolved issues**:
|
||||
- Record reusable failures in `docs/agent-handoffs/incidents/`
|
||||
- Record active unresolved reproducible items in `KNOWN_ISSUES.md`
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user