kortext 2.2.3 → 3.1.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/LICENSE +21 -0
- package/README.md +175 -65
- package/agents/architect.md +85 -0
- package/agents/compliance-expert.md +36 -75
- package/agents/copywriter.md +36 -92
- package/agents/db-admin.md +43 -91
- package/agents/designer.md +40 -77
- package/agents/devops-engineer.md +37 -113
- package/agents/growth-expert.md +45 -88
- package/agents/product-manager.md +38 -83
- package/agents/qa-engineer.md +51 -99
- package/agents/security-engineer.md +47 -92
- package/bin/kortext.js +2 -0
- package/dist/app.js +829 -0
- package/dist/cli-spawn.js +137 -0
- package/dist/daemon.js +40 -0
- package/dist/db.js +78 -0
- package/dist/design-preview.js +533 -0
- package/dist/docs.js +701 -0
- package/dist/engines.js +225 -0
- package/dist/index.js +109 -0
- package/dist/pick-directory.js +38 -0
- package/dist/projects.js +189 -0
- package/dist/readiness.js +288 -0
- package/dist/runner.js +771 -0
- package/dist/update.js +55 -0
- package/docs/CHANGELOG.md +11 -0
- package/package.json +53 -13
- package/templates/AGENTS.md +62 -0
- package/templates/docs/API.md +67 -0
- package/templates/docs/ARCHITECTURE.md +31 -0
- package/templates/docs/BRIEF.md +27 -0
- package/templates/docs/CONTENT.md +66 -0
- package/templates/docs/DATABASE.md +63 -0
- package/templates/docs/DESIGN.md +124 -0
- package/templates/docs/ENGINEERING.md +66 -0
- package/templates/docs/ENVIRONMENT.md +102 -0
- package/templates/docs/GROWTH.md +44 -0
- package/templates/docs/LEGAL.md +48 -0
- package/templates/docs/PRODUCT.md +43 -0
- package/templates/docs/SECURITY.md +65 -0
- package/templates/docs/STACK.md +57 -0
- package/templates/docs/STRUCTURE.md +73 -0
- package/templates/docs/TEST.md +62 -0
- package/ui/dist/assets/abnfDiagram-VCTEODGH-Bm7Q2BML.js +1 -0
- package/ui/dist/assets/arc-BV9hs0Hu.js +1 -0
- package/ui/dist/assets/architecture-7GRP2DOG-RckR3gBI.js +1 -0
- package/ui/dist/assets/architectureDiagram-5GKGNRK7-CHiJ6JFT.js +36 -0
- package/ui/dist/assets/array-BifhSqXX.js +1 -0
- package/ui/dist/assets/blockDiagram-I7D4REHJ-qCbaKVhd.js +129 -0
- package/ui/dist/assets/c4Diagram-7LVT6UL2-DidCDJrv.js +38 -0
- package/ui/dist/assets/channel-CNUQ11ne.js +1 -0
- package/ui/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/ui/dist/assets/chunk-4HAMMTFA-CDGFjfVp.js +62 -0
- package/ui/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/ui/dist/assets/chunk-75Z2AOVW-CbNT4sDh.js +2 -0
- package/ui/dist/assets/chunk-DU6HZSFF-Cq2BVv26.js +127 -0
- package/ui/dist/assets/chunk-F27PBJKO-CE365m0v.js +1 -0
- package/ui/dist/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- package/ui/dist/assets/chunk-GMAD6QVW-DxWL1VC-.js +72 -0
- package/ui/dist/assets/chunk-GVQU2GXP-aARV8YbK.js +1 -0
- package/ui/dist/assets/chunk-IMKFNOWR-CC790Kt2.js +231 -0
- package/ui/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/ui/dist/assets/chunk-L3NEJ4N5-BfE4VE8J.js +1 -0
- package/ui/dist/assets/chunk-OSK3NFVY-BImQbSWH.js +10 -0
- package/ui/dist/assets/chunk-P2QGCYS3-CN3XD313.js +1 -0
- package/ui/dist/assets/chunk-POPQ4Y6H-Dqb6jOrX.js +1 -0
- package/ui/dist/assets/chunk-PWAF6VOD-DfXX6rBk.js +1 -0
- package/ui/dist/assets/chunk-SHT3W25Y-DATyyqPK.js +168 -0
- package/ui/dist/assets/chunk-SVP7TREG-r1chwRmg.js +88 -0
- package/ui/dist/assets/chunk-TICWLB2K-DL4atHUC.js +206 -0
- package/ui/dist/assets/chunk-XXDRQBXY-DXrM6jh7.js +1 -0
- package/ui/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/ui/dist/assets/classDiagram-ZZMXUADV-BpQxfIQ7.js +1 -0
- package/ui/dist/assets/classDiagram-v2-VYDZK3BY-BpQxfIQ7.js +1 -0
- package/ui/dist/assets/cose-bilkent-JH36ORCC-Bhe-ZBlS.js +1 -0
- package/ui/dist/assets/cynefin-OW5HDTMX-D1koLd-G.js +1 -0
- package/ui/dist/assets/cynefinDiagram-5FMLGOSQ-BMcw40hV.js +62 -0
- package/ui/dist/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- package/ui/dist/assets/dagre-GXQ25YYZ-DBun-Rs2.js +4 -0
- package/ui/dist/assets/dagre-PrKaheQc.js +1 -0
- package/ui/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/ui/dist/assets/diagram-S7CK7UJ4-C1fUIGvo.js +30 -0
- package/ui/dist/assets/diagram-UQ7AKVKN-B5FDfkvB.js +41 -0
- package/ui/dist/assets/diagram-VSXAHHWV-CCIpOCNC.js +3 -0
- package/ui/dist/assets/diagram-VX7I27RA-DV0q2xo_.js +24 -0
- package/ui/dist/assets/diagram-Z3DM3KII-B3LCdNgI.js +24 -0
- package/ui/dist/assets/dist-EcW76Zvr.js +1 -0
- package/ui/dist/assets/ebnfDiagram-PWID7BFC-De_oRbYe.js +1 -0
- package/ui/dist/assets/erDiagram-RLTQ6QDP-B9NikMr1.js +99 -0
- package/ui/dist/assets/eventmodeling-NTZA5JFV-DZ4t581k.js +1 -0
- package/ui/dist/assets/flowDiagram-HODETNUW-DuTOJp1C.js +1 -0
- package/ui/dist/assets/ganttDiagram-EL5Y4UJY-BVTqqlPw.js +292 -0
- package/ui/dist/assets/gitGraph-4MIJSDKK-xRFaEJdZ.js +1 -0
- package/ui/dist/assets/gitGraphDiagram-WWUBYQGX-CK5_GCmX.js +106 -0
- package/ui/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/ui/dist/assets/index-CjkpNftW.js +46 -0
- package/ui/dist/assets/index-DVIDTWin.css +1 -0
- package/ui/dist/assets/info-A6RAGUB7-Dg7z-CTI.js +1 -0
- package/ui/dist/assets/infoDiagram-27XIBGKW-YaqsOXh0.js +2 -0
- package/ui/dist/assets/init-C-OQMol4.js +1 -0
- package/ui/dist/assets/ishikawaDiagram-5VMMS53U-C-wtxZPa.js +70 -0
- package/ui/dist/assets/journeyDiagram-3NMN7TZE-DsXSXf16.js +139 -0
- package/ui/dist/assets/kanban-definition-UXKFOSKX-Ct59fuWk.js +89 -0
- package/ui/dist/assets/katex-CXMH3UgJ.js +257 -0
- package/ui/dist/assets/line-BUVw9Mhs.js +1 -0
- package/ui/dist/assets/linear-D8ncLO0X.js +1 -0
- package/ui/dist/assets/mermaid-parser.core-BDC4bG-O.js +7 -0
- package/ui/dist/assets/mermaid.core-DZY3WwzX.js +44 -0
- package/ui/dist/assets/mindmap-definition-YA3MSWOX-DtiuF6Ce.js +96 -0
- package/ui/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/ui/dist/assets/packet-AYTQ26CC-BX2-w9rD.js +1 -0
- package/ui/dist/assets/path-fybaL0A-.js +1 -0
- package/ui/dist/assets/pegDiagram-XKGWAZYB-CotwuIHB.js +1 -0
- package/ui/dist/assets/pie-WAS4IAKB-Hth8ZVpm.js +1 -0
- package/ui/dist/assets/pieDiagram-E7YTZNPT-D9-INs8B.js +39 -0
- package/ui/dist/assets/quadrantDiagram-AXDQQJYC-CMtBXZGV.js +7 -0
- package/ui/dist/assets/radar-RG4KPBEZ-6UuwQPsw.js +1 -0
- package/ui/dist/assets/railroad-74A4TZTK-BF5TZgj0.js +1 -0
- package/ui/dist/assets/railroad-abnf-HS5TGJTU-3KYovtYT.js +1 -0
- package/ui/dist/assets/railroad-ebnf-LZEXJU2U-DeP4WedE.js +1 -0
- package/ui/dist/assets/railroad-peg-WCYAUIDC-i42N1-yk.js +1 -0
- package/ui/dist/assets/railroadDiagram-O6MQD6OU-BS6zkU3Z.js +1 -0
- package/ui/dist/assets/requirementDiagram-BXWQKSXE-J4IOB-kP.js +84 -0
- package/ui/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/ui/dist/assets/sankeyDiagram-P5KCCOFB-jYTCuYzQ.js +40 -0
- package/ui/dist/assets/sequenceDiagram-WJ2MYXX4-Cd2r6PW-.js +162 -0
- package/ui/dist/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/ui/dist/assets/src-7TsfZXRO.js +1 -0
- package/ui/dist/assets/stateDiagram-D77RDMKH-DXOdtOKe.js +1 -0
- package/ui/dist/assets/stateDiagram-v2-MP3YSRHH-9h7sIf3R.js +1 -0
- package/ui/dist/assets/swimlanes-42K2YHIH-BvJGmGs1.js +1 -0
- package/ui/dist/assets/swimlanesDiagram-VR7AAH4N-QA4gPi6a.js +8 -0
- package/ui/dist/assets/timeline-definition-24CTP7MA-CAaD6-yd.js +120 -0
- package/ui/dist/assets/treeView-Q6P3EWNA-4gDEXIyJ.js +1 -0
- package/ui/dist/assets/treemap-WGGIJYW6-CGel5TwW.js +1 -0
- package/ui/dist/assets/vennDiagram-4TSXK5OY-DpxsKboL.js +34 -0
- package/ui/dist/assets/wardley-WFR3VGLG-Ck38v5ns.js +1 -0
- package/ui/dist/assets/wardleyDiagram-VM6X3IG4-Ba0grrqs.js +78 -0
- package/ui/dist/assets/xychartDiagram-S5SC5T6Z-DH_gC96K.js +7 -0
- package/ui/dist/index.html +13 -0
- package/ui/dist/kortext-logo-dark.svg +41 -0
- package/ui/dist/kortext-logo.svg +41 -0
- package/workflows/existing-project-analysis.md +87 -0
- package/workflows/new-project-analysis.md +98 -0
- package/workflows/planning-pipeline.md +61 -0
- package/AGENTS.md +0 -28
- package/agents/backend-developer.md +0 -132
- package/agents/delivery-manager.md +0 -121
- package/agents/engineering-manager.md +0 -208
- package/agents/frontend-developer.md +0 -174
- package/agents/operation-manager.md +0 -122
- package/hooks/audit-logger.sh +0 -25
- package/hooks/auto-locker.sh +0 -74
- package/hooks/auto-unlocker.sh +0 -17
- package/hooks/backlog-sync-guard.sh +0 -12
- package/hooks/branch-guard.sh +0 -32
- package/hooks/commit-msg-guard.sh +0 -43
- package/hooks/git-pre-commit.sh +0 -76
- package/hooks/git-pre-push.sh +0 -17
- package/hooks/handover-guard.sh +0 -33
- package/hooks/kortext-init.sh +0 -194
- package/hooks/kortext-lib.sh +0 -151
- package/hooks/lint-guard.sh +0 -50
- package/hooks/secret-scanner.sh +0 -89
- package/hooks/size-guard.sh +0 -48
- package/hooks/snapshot-guard.sh +0 -39
- package/hooks/write-guard.sh +0 -77
- package/rules/behavior.md +0 -252
- package/rules/branching.md +0 -82
- package/rules/commands.md +0 -112
- package/rules/emergency.md +0 -160
- package/rules/mcp.md +0 -47
- package/rules/models.md +0 -93
- package/scripts/kortext-backlog-add.py +0 -123
- package/scripts/kortext-backlog-health.py +0 -112
- package/scripts/kortext-backlog-sync.py +0 -117
- package/scripts/kortext-bulk-plan.py +0 -63
- package/scripts/kortext-cli.py +0 -376
- package/scripts/kortext-consistency-check.py +0 -74
- package/scripts/kortext-context-check.py +0 -146
- package/scripts/kortext-handover.py +0 -107
- package/scripts/kortext-item-check.py +0 -61
- package/scripts/kortext-item-start.py +0 -70
- package/scripts/kortext-item-transition.py +0 -78
- package/scripts/kortext-lock.py +0 -174
- package/scripts/kortext-session-start.py +0 -127
- package/scripts/lock_kortext.sh +0 -34
- package/settings/.claude-settings.template.json +0 -48
- package/settings/CHANGELOG.md +0 -176
- package/settings/INTEGRATION-MAP.md +0 -276
- package/settings/README.md +0 -255
- package/settings/USER-GUIDE.md +0 -502
- package/settings/VERSION +0 -1
- package/settings/config.md +0 -8
- package/settings/runtime-adapters.md +0 -104
- package/skills/backend-developer/.gitkeep +0 -0
- package/skills/compliance-expert/.gitkeep +0 -0
- package/skills/copywriter/.gitkeep +0 -0
- package/skills/db-admin/.gitkeep +0 -0
- package/skills/delivery-manager/.gitkeep +0 -0
- package/skills/designer/.gitkeep +0 -0
- package/skills/devops-engineer/.gitkeep +0 -0
- package/skills/engineering-manager/.gitkeep +0 -0
- package/skills/frontend-developer/.gitkeep +0 -0
- package/skills/growth-expert/.gitkeep +0 -0
- package/skills/operation-manager/.gitkeep +0 -0
- package/skills/product-manager/.gitkeep +0 -0
- package/skills/qa-engineer/.gitkeep +0 -0
- package/skills/security-engineer/.gitkeep +0 -0
- package/workflows/00-kortext-setup.md +0 -53
- package/workflows/01a-analysis-pipeline.md +0 -117
- package/workflows/01b-onboarding-pipeline.md +0 -110
- package/workflows/02-planning-pipeline.md +0 -146
- package/workflows/02b-spike-workflow.md +0 -120
- package/workflows/03-environment-setup.md +0 -99
- package/workflows/04-development-cycle.md +0 -203
- package/workflows/05-test-cycle.md +0 -123
- package/workflows/06-deployment-cycle.md +0 -224
- package/workflows/07-rollback-pipeline.md +0 -203
- package/workflows/08-hotfix-pipeline.md +0 -196
- package/workflows/09-maintenance-cycle.md +0 -133
- package/workspace/archive/.gitkeep +0 -0
- package/workspace/backups/.gitkeep +0 -0
- package/workspace/memory/backlog/.gitkeep +0 -0
- package/workspace/memory/backlog/BXX-[bug-name].md +0 -2
- package/workspace/memory/backlog/DXX-[debt-name].md +0 -2
- package/workspace/memory/backlog/README.md +0 -31
- package/workspace/memory/backlog/TXX-[task-name].md +0 -2
- package/workspace/memory/backlog/debt-dashboard.md +0 -3
- package/workspace/memory/backlog/epic-dashboard.md +0 -10
- package/workspace/memory/backlog/version-dashboard.md +0 -7
- package/workspace/memory/context/.gitkeep +0 -0
- package/workspace/memory/context/README.md +0 -35
- package/workspace/memory/context/[agent-name]-active.md +0 -2
- package/workspace/memory/decisions.md +0 -17
- package/workspace/memory/handover.md +0 -40
- package/workspace/memory/learned.md +0 -21
- package/workspace/references/access.md +0 -47
- package/workspace/references/api-reference.md +0 -59
- package/workspace/references/blueprint.md +0 -29
- package/workspace/references/content-strategy.md +0 -39
- package/workspace/references/db-schema.md +0 -51
- package/workspace/references/design-system.md +0 -107
- package/workspace/references/dictionary.md +0 -42
- package/workspace/references/file-system.md +0 -42
- package/workspace/references/growth-strategy.md +0 -46
- package/workspace/references/legal-strategy.md +0 -35
- package/workspace/references/required-skills.md +0 -11
- package/workspace/references/security-rules.md +0 -34
- package/workspace/references/tech-stack.md +0 -49
- package/workspace/references/test-strategy.md +0 -48
- package/workspace/reports/analysis-reports.md +0 -40
- package/workspace/reports/content-reports.md +0 -29
- package/workspace/reports/delivery-reports.md +0 -26
- package/workspace/reports/growth-reports.md +0 -9
- package/workspace/reports/legal-reports.md +0 -29
- package/workspace/reports/product-requirements.md +0 -28
- package/workspace/reports/release-notes.md +0 -20
- package/workspace/reports/security-reports.md +0 -27
- package/workspace/reports/status-reports.md +0 -48
- package/workspace/reports/tech-requirements.md +0 -30
- package/workspace/reports/test-reports.md +0 -61
- package/workspace/templates/BXX-[bug-name].md +0 -34
- package/workspace/templates/DXX-[debt-name].md +0 -35
- package/workspace/templates/EXX-[epic-name].md +0 -48
- package/workspace/templates/HXX-[hotfix-name].md +0 -73
- package/workspace/templates/SXX-[spike-name].md +0 -51
- package/workspace/templates/TXX-[task-name].md +0 -34
- package/workspace/templates/[agent-name]-active.md +0 -4
- package/workspace/templates/[original-name]_[YYYY-MM-DD_HHMMSS].md +0 -5
- package/workspace/templates/adr-XXX.md +0 -66
- package/workspace/templates/debt-dashboard.md +0 -10
- package/workspace/templates/epic-dashboard.md +0 -10
- package/workspace/templates/version-dashboard.md +0 -10
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { createWriteStream, mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
export async function spawnCli(opts) {
|
|
5
|
+
// Keep escalation shorter than the restart/cancel delay before project files are removed.
|
|
6
|
+
const sigkillDelayMs = opts.sigkillDelayMs ?? 1000;
|
|
7
|
+
const summaryCap = opts.summaryBufferBytes ?? 64 * 1024;
|
|
8
|
+
if (opts.signal.aborted) {
|
|
9
|
+
return {
|
|
10
|
+
exitCode: null,
|
|
11
|
+
signal: null,
|
|
12
|
+
stdoutTail: '',
|
|
13
|
+
stderrTail: '',
|
|
14
|
+
aborted: true,
|
|
15
|
+
timedOut: false,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
// Windows support is experimental: .cmd shims require a shell and process-tree termination
|
|
19
|
+
// uses taskkill. Keep binary/arguments trusted and send user-written prompts through stdin.
|
|
20
|
+
const onWindows = process.platform === 'win32';
|
|
21
|
+
// A prompt on the command line is untrusted text; the Windows path runs
|
|
22
|
+
// through a shell, so it stays on stdin there or not at all.
|
|
23
|
+
const asArg = opts.promptFlag !== undefined;
|
|
24
|
+
if (asArg && onWindows)
|
|
25
|
+
throw new Error(`${opts.binary} needs stdin prompts on Windows`);
|
|
26
|
+
const args = asArg && opts.stdin !== undefined
|
|
27
|
+
? [...opts.args, ...(opts.promptFlag ? [opts.promptFlag] : []), opts.stdin]
|
|
28
|
+
: opts.args;
|
|
29
|
+
const stdin = asArg ? undefined : opts.stdin;
|
|
30
|
+
const proc = spawn(opts.binary, args, {
|
|
31
|
+
cwd: opts.cwd,
|
|
32
|
+
env: opts.env,
|
|
33
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
34
|
+
shell: onWindows,
|
|
35
|
+
// Use a POSIX process group to terminate descendants that could keep output pipes open.
|
|
36
|
+
detached: !onWindows,
|
|
37
|
+
});
|
|
38
|
+
const killTree = (sig) => {
|
|
39
|
+
try {
|
|
40
|
+
if (onWindows)
|
|
41
|
+
throw new Error('no process groups'); // straight to the fallback
|
|
42
|
+
process.kill(-proc.pid, sig); // negative pid = the process group
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
try {
|
|
46
|
+
proc.kill(sig);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
/* already gone */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
// Create the log directory before opening the stream to prevent an unhandled ENOENT error.
|
|
54
|
+
mkdirSync(dirname(opts.logPath), { recursive: true });
|
|
55
|
+
const log = createWriteStream(opts.logPath, { flags: 'a' });
|
|
56
|
+
log.write(`\n# kortext cli-executor — ${new Date().toISOString()}\n# binary: ${opts.binary}\n# args: ${JSON.stringify(opts.args)}\n# cwd: ${opts.cwd}\n\n`);
|
|
57
|
+
// Bound output buffers to limit memory use.
|
|
58
|
+
let stdoutBuf = '';
|
|
59
|
+
let stderrBuf = '';
|
|
60
|
+
const appendCapped = (current, chunk) => {
|
|
61
|
+
const combined = current + chunk;
|
|
62
|
+
return combined.length > summaryCap ? combined.slice(combined.length - summaryCap) : combined;
|
|
63
|
+
};
|
|
64
|
+
proc.stdout?.on('data', (chunk) => {
|
|
65
|
+
const s = chunk.toString('utf8');
|
|
66
|
+
stdoutBuf = appendCapped(stdoutBuf, s);
|
|
67
|
+
log.write(s);
|
|
68
|
+
});
|
|
69
|
+
proc.stderr?.on('data', (chunk) => {
|
|
70
|
+
const s = chunk.toString('utf8');
|
|
71
|
+
stderrBuf = appendCapped(stderrBuf, s);
|
|
72
|
+
log.write(`[stderr] ${s}`);
|
|
73
|
+
});
|
|
74
|
+
// A child can close stdin before the prompt is written; handle EPIPE without crashing the server.
|
|
75
|
+
if (proc.stdin) {
|
|
76
|
+
proc.stdin.on('error', (err) => {
|
|
77
|
+
const code = err.code;
|
|
78
|
+
if (code !== 'EPIPE') {
|
|
79
|
+
log.write(`\n[stdin-error] ${err.message}\n`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
if (stdin !== undefined) {
|
|
83
|
+
proc.stdin.write(stdin);
|
|
84
|
+
}
|
|
85
|
+
proc.stdin.end();
|
|
86
|
+
}
|
|
87
|
+
let aborted = false;
|
|
88
|
+
let timedOut = false;
|
|
89
|
+
let killTimer = null;
|
|
90
|
+
let timeoutTimer = null;
|
|
91
|
+
const onAbort = () => {
|
|
92
|
+
aborted = true;
|
|
93
|
+
killTree('SIGTERM');
|
|
94
|
+
killTimer = setTimeout(() => killTree('SIGKILL'), sigkillDelayMs);
|
|
95
|
+
};
|
|
96
|
+
opts.signal.addEventListener('abort', onAbort, { once: true });
|
|
97
|
+
if (opts.timeoutMs !== undefined) {
|
|
98
|
+
timeoutTimer = setTimeout(() => {
|
|
99
|
+
timedOut = true; // the caller aborted nothing; this run outstayed its limit
|
|
100
|
+
onAbort();
|
|
101
|
+
}, opts.timeoutMs);
|
|
102
|
+
}
|
|
103
|
+
const result = await new Promise((resolveResult) => {
|
|
104
|
+
// Resolve after the log stream finishes so callers can read complete output.
|
|
105
|
+
// Spawn failures emit both error and close; settle once to avoid writes after the log has ended.
|
|
106
|
+
let settled = false;
|
|
107
|
+
const finish = (line, result) => {
|
|
108
|
+
if (settled)
|
|
109
|
+
return;
|
|
110
|
+
settled = true;
|
|
111
|
+
log.write(line);
|
|
112
|
+
log.end(() => resolveResult({ ...result, aborted, timedOut }));
|
|
113
|
+
};
|
|
114
|
+
proc.on('error', (err) => {
|
|
115
|
+
finish(`\n[spawn-error] ${err.message}\n`, {
|
|
116
|
+
exitCode: null,
|
|
117
|
+
signal: null,
|
|
118
|
+
stdoutTail: stdoutBuf,
|
|
119
|
+
stderrTail: stderrBuf + `\n[spawn-error] ${err.message}`,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
proc.on('close', (code, signal) => {
|
|
123
|
+
finish(`\n# exit code=${code} signal=${signal} aborted=${aborted}\n`, {
|
|
124
|
+
exitCode: code,
|
|
125
|
+
signal,
|
|
126
|
+
stdoutTail: stdoutBuf,
|
|
127
|
+
stderrTail: stderrBuf,
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
if (killTimer)
|
|
132
|
+
clearTimeout(killTimer);
|
|
133
|
+
if (timeoutTimer)
|
|
134
|
+
clearTimeout(timeoutTimer);
|
|
135
|
+
opts.signal.removeEventListener('abort', onAbort);
|
|
136
|
+
return result;
|
|
137
|
+
}
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdirSync, openSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
/** Is a kortext already answering on this port? */
|
|
5
|
+
export async function serverUp(port) {
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/health`, {
|
|
8
|
+
signal: AbortSignal.timeout(700),
|
|
9
|
+
});
|
|
10
|
+
return res.ok;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Wait for the detached server health check, including initial SQLite startup. */
|
|
17
|
+
export async function waitForServer(port, timeoutMs = 15000) {
|
|
18
|
+
const deadline = Date.now() + timeoutMs;
|
|
19
|
+
for (;;) {
|
|
20
|
+
if (await serverUp(port))
|
|
21
|
+
return true;
|
|
22
|
+
if (Date.now() >= deadline)
|
|
23
|
+
return false;
|
|
24
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Detach into a separate process group and redirect output to a log file.
|
|
29
|
+
* Unref the child so the parent can exit without stopping the server.
|
|
30
|
+
*/
|
|
31
|
+
export function respawnDetached(entry, args, logPath) {
|
|
32
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
33
|
+
const log = openSync(logPath, 'a');
|
|
34
|
+
const child = spawn(process.execPath, [entry, ...args], {
|
|
35
|
+
detached: true,
|
|
36
|
+
stdio: ['ignore', log, log],
|
|
37
|
+
env: { ...process.env, KORTEXT_CHILD: '1' },
|
|
38
|
+
});
|
|
39
|
+
child.unref();
|
|
40
|
+
}
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
export function defaultDbPath() {
|
|
6
|
+
return join(homedir(), '.kortext', 'kortext.db');
|
|
7
|
+
}
|
|
8
|
+
// The database filename is part of the namespace, including for sibling DBs.
|
|
9
|
+
export function logRootDir(db) {
|
|
10
|
+
return `${resolve(db.name)}.logs`;
|
|
11
|
+
}
|
|
12
|
+
export function logPathFor(db, name) {
|
|
13
|
+
return join(logRootDir(db), name);
|
|
14
|
+
}
|
|
15
|
+
const SCHEMA = `
|
|
16
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
17
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
|
+
name TEXT NOT NULL,
|
|
19
|
+
repo_path TEXT NOT NULL UNIQUE,
|
|
20
|
+
kind TEXT NOT NULL DEFAULT 'new', -- new | existing → which analysis workflow applies
|
|
21
|
+
code TEXT NOT NULL DEFAULT '', -- task-id prefix, e.g. ACME
|
|
22
|
+
paused INTEGER NOT NULL DEFAULT 0, -- 1 = the chain starts no new steps
|
|
23
|
+
archived INTEGER NOT NULL DEFAULT 0,-- 1 = folded away in the panel; files untouched
|
|
24
|
+
doc_lang TEXT NOT NULL DEFAULT '', -- the language the documents are written in
|
|
25
|
+
engine TEXT NOT NULL DEFAULT '', -- the agent CLI this project runs on
|
|
26
|
+
model TEXT NOT NULL DEFAULT '', -- the model that CLI is told to use; '' = the CLI's own default
|
|
27
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
28
|
+
);
|
|
29
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
30
|
+
key TEXT PRIMARY KEY,
|
|
31
|
+
value TEXT NOT NULL
|
|
32
|
+
);
|
|
33
|
+
CREATE TABLE IF NOT EXISTS jobs (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
36
|
+
doc_rel TEXT NOT NULL,
|
|
37
|
+
kind TEXT NOT NULL DEFAULT 'doc', -- doc (analysis step) | plan (kopeng split)
|
|
38
|
+
status TEXT NOT NULL DEFAULT 'running', -- running | done | failed | stopped
|
|
39
|
+
error TEXT,
|
|
40
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
41
|
+
finished_at TEXT
|
|
42
|
+
);
|
|
43
|
+
-- What a document said before it was last written. Not document state — the
|
|
44
|
+
-- current text still lives only on disk — but a write log, like the jobs table,
|
|
45
|
+
-- so the panel can show what a revision replaced.
|
|
46
|
+
CREATE TABLE IF NOT EXISTS doc_versions (
|
|
47
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
48
|
+
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
49
|
+
rel TEXT NOT NULL,
|
|
50
|
+
sha TEXT NOT NULL,
|
|
51
|
+
content TEXT NOT NULL,
|
|
52
|
+
source TEXT NOT NULL, -- agent | prime | proposal | pre-existing
|
|
53
|
+
job_id INTEGER,
|
|
54
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
55
|
+
);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_doc_versions ON doc_versions(project_id, rel, id DESC);
|
|
57
|
+
CREATE TABLE IF NOT EXISTS pending_rechecks (
|
|
58
|
+
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
59
|
+
source_rel TEXT NOT NULL,
|
|
60
|
+
reader_rel TEXT NOT NULL,
|
|
61
|
+
generation INTEGER NOT NULL DEFAULT 1,
|
|
62
|
+
PRIMARY KEY (project_id, source_rel, reader_rel)
|
|
63
|
+
);
|
|
64
|
+
`;
|
|
65
|
+
export function openDb(path = defaultDbPath()) {
|
|
66
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
67
|
+
const db = new Database(path);
|
|
68
|
+
db.pragma('journal_mode = WAL');
|
|
69
|
+
db.pragma('foreign_keys = ON');
|
|
70
|
+
db.exec(SCHEMA);
|
|
71
|
+
if (!db.pragma('table_info(jobs)').some((c) => c.name === 'notes')) {
|
|
72
|
+
db.exec("ALTER TABLE jobs ADD COLUMN notes TEXT NOT NULL DEFAULT '[]'");
|
|
73
|
+
}
|
|
74
|
+
if (!db.pragma('table_info(projects)').some((c) => c.name === 'model')) {
|
|
75
|
+
db.exec("ALTER TABLE projects ADD COLUMN model TEXT NOT NULL DEFAULT ''");
|
|
76
|
+
}
|
|
77
|
+
return db;
|
|
78
|
+
}
|