iosm-cli 0.1.3 → 0.2.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/CHANGELOG.md +27 -0
- package/README.md +33 -2
- package/dist/core/blast.d.ts +62 -0
- package/dist/core/blast.d.ts.map +1 -0
- package/dist/core/blast.js +448 -0
- package/dist/core/blast.js.map +1 -0
- package/dist/core/contract.d.ts +54 -0
- package/dist/core/contract.d.ts.map +1 -0
- package/dist/core/contract.js +300 -0
- package/dist/core/contract.js.map +1 -0
- package/dist/core/semantic/config.d.ts.map +1 -1
- package/dist/core/semantic/config.js +5 -0
- package/dist/core/semantic/config.js.map +1 -1
- package/dist/core/semantic/index.d.ts +1 -1
- package/dist/core/semantic/index.d.ts.map +1 -1
- package/dist/core/semantic/index.js +1 -1
- package/dist/core/semantic/index.js.map +1 -1
- package/dist/core/semantic/runtime.d.ts.map +1 -1
- package/dist/core/semantic/runtime.js +12 -1
- package/dist/core/semantic/runtime.js.map +1 -1
- package/dist/core/semantic/types.d.ts +6 -0
- package/dist/core/semantic/types.d.ts.map +1 -1
- package/dist/core/semantic/types.js +6 -0
- package/dist/core/semantic/types.js.map +1 -1
- package/dist/core/shadow-guard.d.ts +30 -0
- package/dist/core/shadow-guard.d.ts.map +1 -0
- package/dist/core/shadow-guard.js +81 -0
- package/dist/core/shadow-guard.js.map +1 -0
- package/dist/core/singular.d.ts +73 -0
- package/dist/core/singular.d.ts.map +1 -0
- package/dist/core/singular.js +413 -0
- package/dist/core/singular.js.map +1 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +9 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/semantic-search.d.ts.map +1 -1
- package/dist/core/tools/semantic-search.js +1 -0
- package/dist/core/tools/semantic-search.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +8 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +8 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +70 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +43 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1304 -24
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/cli-reference.md +19 -1
- package/docs/configuration.md +5 -0
- package/docs/interactive-mode.md +131 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blast.js","sourceRoot":"","sources":["../../src/core/blast.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\nimport type { EngineeringContract } from \"./contract.js\";\n\nexport type BlastProfile = \"quick\" | \"full\";\nexport type BlastSeverity = \"low\" | \"medium\" | \"high\";\n\nexport interface BlastFinding {\n\tid: string;\n\ttitle: string;\n\tseverity: BlastSeverity;\n\tcategory: string;\n\tdetail: string;\n\tpath?: string;\n\tline?: number;\n\trecommendation?: string;\n}\n\nexport interface BlastRunOptions {\n\tprofile: BlastProfile;\n\tautosave?: boolean;\n\tcontract?: EngineeringContract;\n}\n\nexport interface BlastRunResult {\n\trunId: string;\n\tprofile: BlastProfile;\n\tstartedAt: string;\n\tcompletedAt: string;\n\tdurationMs: number;\n\tscannedFiles: number;\n\tscannedLines: number;\n\tfindings: BlastFinding[];\n\tsummary: string;\n\tnextSteps: string[];\n\treportMarkdown: string;\n\tcontract: EngineeringContract;\n\tautosaved: boolean;\n\treportPath?: string;\n\tfindingsPath?: string;\n}\n\nexport interface BlastLastRun {\n\trunId: string;\n\treportPath: string;\n\tfindingsPath: string;\n\tmetaPath?: string;\n\tsummary?: string;\n\tprofile?: BlastProfile;\n\tcompletedAt?: string;\n\tfindings?: number;\n}\n\ntype BlastScanCounters = {\n\tfiles: number;\n\tlines: number;\n\ttodoCount: number;\n\tdebugCount: number;\n\tunsafeEvalCount: number;\n\tanyTypeCount: number;\n\ttsIgnoreCount: number;\n\ttestFiles: number;\n\tlargeFiles: number;\n};\n\nconst SCAN_TEXT_EXTENSIONS = new Set([\n\t\".ts\",\n\t\".tsx\",\n\t\".js\",\n\t\".jsx\",\n\t\".mjs\",\n\t\".cjs\",\n\t\".py\",\n\t\".go\",\n\t\".rs\",\n\t\".java\",\n\t\".json\",\n\t\".yaml\",\n\t\".yml\",\n\t\".toml\",\n\t\".md\",\n\t\".sh\",\n\t\".env\",\n\t\".sql\",\n\t\".html\",\n\t\".css\",\n]);\n\nconst EXCLUDED_DIR_NAMES = new Set([\".git\", \"node_modules\", \"dist\", \"build\", \".iosm\", \".next\", \"coverage\"]);\n\nfunction toPosixPath(value: string): string {\n\treturn value.split(sep).join(\"/\");\n}\n\nfunction getExtension(filePath: string): string {\n\tconst normalized = filePath.toLowerCase();\n\tconst index = normalized.lastIndexOf(\".\");\n\treturn index >= 0 ? normalized.slice(index) : \"\";\n}\n\nfunction containsAny(text: string, terms: string[]): boolean {\n\tconst normalized = text.toLowerCase();\n\treturn terms.some((term) => normalized.includes(term.toLowerCase()));\n}\n\nfunction countSeverity(findings: BlastFinding[], severity: BlastSeverity): number {\n\treturn findings.filter((item) => item.severity === severity).length;\n}\n\nfunction clampFindings(findings: BlastFinding[], max: number): BlastFinding[] {\n\tif (findings.length <= max) return findings;\n\treturn findings.slice(0, max);\n}\n\nfunction serializeFinding(finding: BlastFinding): string {\n\tconst location = finding.path ? ` (${finding.path}${finding.line ? `:${finding.line}` : \"\"})` : \"\";\n\treturn `- [${finding.severity.toUpperCase()}] ${finding.title}${location}\\n ${finding.detail}${finding.recommendation ? `\\n fix: ${finding.recommendation}` : \"\"}`;\n}\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nfunction buildRunId(date = new Date()): string {\n\tconst year = date.getUTCFullYear();\n\tconst month = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getUTCDate()).padStart(2, \"0\");\n\tconst hours = String(date.getUTCHours()).padStart(2, \"0\");\n\tconst minutes = String(date.getUTCMinutes()).padStart(2, \"0\");\n\tconst seconds = String(date.getUTCSeconds()).padStart(2, \"0\");\n\treturn `${year}-${month}-${day}-${hours}${minutes}${seconds}`;\n}\n\nexport interface BlastServiceOptions {\n\tcwd: string;\n}\n\nexport class BlastService {\n\tprivate readonly cwd: string;\n\n\tconstructor(options: BlastServiceOptions) {\n\t\tthis.cwd = options.cwd;\n\t}\n\n\tgetAuditsRoot(): string {\n\t\treturn join(this.cwd, \".iosm\", \"audits\");\n\t}\n\n\tgetLastRun(): BlastLastRun | undefined {\n\t\tconst root = this.getAuditsRoot();\n\t\tif (!existsSync(root)) return undefined;\n\t\tconst candidates = readdirSync(root, { withFileTypes: true })\n\t\t\t.filter((entry) => entry.isDirectory())\n\t\t\t.map((entry) => entry.name)\n\t\t\t.sort((a, b) => a.localeCompare(b));\n\t\tconst runId = candidates[candidates.length - 1];\n\t\tif (!runId) return undefined;\n\n\t\tconst runDir = join(root, runId);\n\t\tconst reportPath = join(runDir, \"report.md\");\n\t\tconst findingsPath = join(runDir, \"findings.json\");\n\t\tif (!existsSync(reportPath) || !existsSync(findingsPath)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst metaPath = join(runDir, \"meta.json\");\n\t\tlet summary: string | undefined;\n\t\tlet profile: BlastProfile | undefined;\n\t\tlet completedAt: string | undefined;\n\t\tlet findingsCount: number | undefined;\n\t\tif (existsSync(metaPath)) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(readFileSync(metaPath, \"utf8\")) as Record<string, unknown>;\n\t\t\t\tsummary = typeof parsed.summary === \"string\" ? parsed.summary : undefined;\n\t\t\t\tprofile =\n\t\t\t\t\tparsed.profile === \"quick\" || parsed.profile === \"full\" ? (parsed.profile as BlastProfile) : undefined;\n\t\t\t\tcompletedAt = typeof parsed.completedAt === \"string\" ? parsed.completedAt : undefined;\n\t\t\t\tfindingsCount = typeof parsed.findings === \"number\" ? parsed.findings : undefined;\n\t\t\t} catch {\n\t\t\t\t// Keep metadata optional.\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\trunId,\n\t\t\treportPath,\n\t\t\tfindingsPath,\n\t\t\tmetaPath: existsSync(metaPath) ? metaPath : undefined,\n\t\t\tsummary,\n\t\t\tprofile,\n\t\t\tcompletedAt,\n\t\t\tfindings: findingsCount,\n\t\t};\n\t}\n\n\tasync run(options: BlastRunOptions): Promise<BlastRunResult> {\n\t\tconst startedAt = nowIso();\n\t\tconst started = Date.now();\n\t\tconst profile = options.profile;\n\t\tconst runId = buildRunId(new Date());\n\t\tconst autosave = options.autosave !== false;\n\t\tconst contract = options.contract ? { ...options.contract } : {};\n\n\t\tconst { files, findings, counters } = this.scanRepository(profile, contract);\n\t\tconst findingsLimited = clampFindings(findings, profile === \"full\" ? 150 : 80);\n\t\tconst summary = this.buildSummary(counters, findingsLimited);\n\t\tconst nextSteps = this.buildNextSteps(findingsLimited, contract);\n\t\tconst completedAt = nowIso();\n\t\tconst durationMs = Date.now() - started;\n\t\tconst reportMarkdown = this.buildReportMarkdown({\n\t\t\trunId,\n\t\t\tprofile,\n\t\t\tstartedAt,\n\t\t\tcompletedAt,\n\t\t\tdurationMs,\n\t\t\tcounters,\n\t\t\tfindings: findingsLimited,\n\t\t\tsummary,\n\t\t\tnextSteps,\n\t\t\tcontract,\n\t\t});\n\n\t\tconst result: BlastRunResult = {\n\t\t\trunId,\n\t\t\tprofile,\n\t\t\tstartedAt,\n\t\t\tcompletedAt,\n\t\t\tdurationMs,\n\t\t\tscannedFiles: counters.files,\n\t\t\tscannedLines: counters.lines,\n\t\t\tfindings: findingsLimited,\n\t\t\tsummary,\n\t\t\tnextSteps,\n\t\t\treportMarkdown,\n\t\t\tcontract,\n\t\t\tautosaved: false,\n\t\t};\n\n\t\tif (autosave) {\n\t\t\tconst saved = this.saveRunArtifacts(result);\n\t\t\tresult.autosaved = true;\n\t\t\tresult.reportPath = saved.reportPath;\n\t\t\tresult.findingsPath = saved.findingsPath;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate saveRunArtifacts(result: BlastRunResult): { reportPath: string; findingsPath: string } {\n\t\tconst runDir = join(this.getAuditsRoot(), result.runId);\n\t\tmkdirSync(runDir, { recursive: true });\n\n\t\tconst reportPath = join(runDir, \"report.md\");\n\t\tconst findingsPath = join(runDir, \"findings.json\");\n\t\tconst metaPath = join(runDir, \"meta.json\");\n\n\t\twriteFileSync(reportPath, `${result.reportMarkdown}\\n`, \"utf8\");\n\t\twriteFileSync(findingsPath, `${JSON.stringify(result.findings, null, 2)}\\n`, \"utf8\");\n\t\twriteFileSync(\n\t\t\tmetaPath,\n\t\t\t`${JSON.stringify(\n\t\t\t\t{\n\t\t\t\t\trunId: result.runId,\n\t\t\t\t\tprofile: result.profile,\n\t\t\t\t\tsummary: result.summary,\n\t\t\t\t\tstartedAt: result.startedAt,\n\t\t\t\t\tcompletedAt: result.completedAt,\n\t\t\t\t\tdurationMs: result.durationMs,\n\t\t\t\t\tfiles: result.scannedFiles,\n\t\t\t\t\tlines: result.scannedLines,\n\t\t\t\t\tfindings: result.findings.length,\n\t\t\t\t},\n\t\t\t\tnull,\n\t\t\t\t2,\n\t\t\t)}\\n`,\n\t\t\t\"utf8\",\n\t\t);\n\n\t\treturn { reportPath, findingsPath };\n\t}\n\n\tprivate scanRepository(\n\t\tprofile: BlastProfile,\n\t\tcontract: EngineeringContract,\n\t): { files: string[]; findings: BlastFinding[]; counters: BlastScanCounters } {\n\t\tconst counters: BlastScanCounters = {\n\t\t\tfiles: 0,\n\t\t\tlines: 0,\n\t\t\ttodoCount: 0,\n\t\t\tdebugCount: 0,\n\t\t\tunsafeEvalCount: 0,\n\t\t\tanyTypeCount: 0,\n\t\t\ttsIgnoreCount: 0,\n\t\t\ttestFiles: 0,\n\t\t\tlargeFiles: 0,\n\t\t};\n\n\t\tconst findings: BlastFinding[] = [];\n\t\tconst files = this.walkFiles(profile);\n\t\tconst maxFileBytes = profile === \"full\" ? 512_000 : 256_000;\n\n\t\tfor (const absolutePath of files) {\n\t\t\tconst relativePath = toPosixPath(relative(this.cwd, absolutePath));\n\t\t\tconst stat = statSync(absolutePath);\n\t\t\tif (stat.size > maxFileBytes) {\n\t\t\t\tcounters.largeFiles += 1;\n\t\t\t\tfindings.push({\n\t\t\t\t\tid: `large-file:${relativePath}`,\n\t\t\t\t\ttitle: \"Large file in scan scope\",\n\t\t\t\t\tseverity: \"medium\",\n\t\t\t\t\tcategory: \"maintainability\",\n\t\t\t\t\tdetail: `File size ${stat.size} bytes exceeds ${maxFileBytes} bytes threshold for ${profile} profile.`,\n\t\t\t\t\tpath: relativePath,\n\t\t\t\t\trecommendation: \"Split file into smaller modules or exclude it from scope if generated.\",\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet content: string;\n\t\t\ttry {\n\t\t\t\tcontent = readFileSync(absolutePath, \"utf8\");\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (content.includes(\"\\u0000\")) continue;\n\n\t\t\tconst lines = content.split(/\\r?\\n/);\n\t\t\tcounters.files += 1;\n\t\t\tcounters.lines += lines.length;\n\t\t\tif (/(^|\\/)(test|tests|__tests__)\\//i.test(relativePath) || /\\.test\\./i.test(relativePath)) {\n\t\t\t\tcounters.testFiles += 1;\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tconst line = lines[i] ?? \"\";\n\t\t\t\tconst lineNumber = i + 1;\n\n\t\t\t\tif (/(TODO|FIXME|HACK)\\b/i.test(line)) {\n\t\t\t\t\tcounters.todoCount += 1;\n\t\t\t\t\tif (findings.length < 220) {\n\t\t\t\t\t\tfindings.push({\n\t\t\t\t\t\t\tid: `todo:${relativePath}:${lineNumber}`,\n\t\t\t\t\t\t\ttitle: \"Outstanding TODO/FIXME marker\",\n\t\t\t\t\t\t\tseverity: \"low\",\n\t\t\t\t\t\t\tcategory: \"maintainability\",\n\t\t\t\t\t\t\tdetail: line.trim(),\n\t\t\t\t\t\t\tpath: relativePath,\n\t\t\t\t\t\t\tline: lineNumber,\n\t\t\t\t\t\t\trecommendation: \"Convert to tracked issue or resolve before release.\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (/\\bconsole\\.log\\(|\\bdebugger\\b/.test(line)) {\n\t\t\t\t\tcounters.debugCount += 1;\n\t\t\t\t\tif (findings.length < 220) {\n\t\t\t\t\t\tfindings.push({\n\t\t\t\t\t\t\tid: `debug:${relativePath}:${lineNumber}`,\n\t\t\t\t\t\t\ttitle: \"Debug artifact in code path\",\n\t\t\t\t\t\t\tseverity: \"medium\",\n\t\t\t\t\t\t\tcategory: \"quality\",\n\t\t\t\t\t\t\tdetail: line.trim(),\n\t\t\t\t\t\t\tpath: relativePath,\n\t\t\t\t\t\t\tline: lineNumber,\n\t\t\t\t\t\t\trecommendation: \"Remove debug call or guard behind explicit debug flag.\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (/\\beval\\s*\\(|\\bnew Function\\s*\\(|child_process\\.(exec|execSync)\\s*\\(/.test(line)) {\n\t\t\t\t\tcounters.unsafeEvalCount += 1;\n\t\t\t\t\tif (findings.length < 220) {\n\t\t\t\t\t\tfindings.push({\n\t\t\t\t\t\t\tid: `unsafe:${relativePath}:${lineNumber}`,\n\t\t\t\t\t\t\ttitle: \"Potentially unsafe dynamic execution\",\n\t\t\t\t\t\t\tseverity: \"high\",\n\t\t\t\t\t\t\tcategory: \"security\",\n\t\t\t\t\t\t\tdetail: line.trim(),\n\t\t\t\t\t\t\tpath: relativePath,\n\t\t\t\t\t\t\tline: lineNumber,\n\t\t\t\t\t\t\trecommendation: \"Replace with safer static alternatives or strictly sanitize inputs.\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (/:\\s*any\\b|<any>/.test(line)) {\n\t\t\t\t\tcounters.anyTypeCount += 1;\n\t\t\t\t}\n\n\t\t\t\tif (/@ts-ignore\\b/.test(line)) {\n\t\t\t\t\tcounters.tsIgnoreCount += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (counters.anyTypeCount > 15) {\n\t\t\tfindings.push({\n\t\t\t\tid: \"types:any-overuse\",\n\t\t\t\ttitle: \"High usage of `any` type\",\n\t\t\t\tseverity: \"medium\",\n\t\t\t\tcategory: \"type-safety\",\n\t\t\t\tdetail: `Detected ${counters.anyTypeCount} occurrences of explicit any type usage.`,\n\t\t\t\trecommendation: \"Replace broad any usage with domain types or unknown + narrowing.\",\n\t\t\t});\n\t\t}\n\t\tif (counters.tsIgnoreCount > 5) {\n\t\t\tfindings.push({\n\t\t\t\tid: \"types:ts-ignore-overuse\",\n\t\t\t\ttitle: \"Excessive @ts-ignore usage\",\n\t\t\t\tseverity: \"medium\",\n\t\t\t\tcategory: \"type-safety\",\n\t\t\t\tdetail: `Detected ${counters.tsIgnoreCount} @ts-ignore directives.`,\n\t\t\t\trecommendation: \"Audit and remove ignored type errors; keep only documented exceptions.\",\n\t\t\t});\n\t\t}\n\n\t\tconst gates = contract.quality_gates ?? [];\n\t\tif (containsAny(gates.join(\" \"), [\"test\", \"coverage\"]) && counters.testFiles === 0) {\n\t\t\tfindings.push({\n\t\t\t\tid: \"contract:tests-missing\",\n\t\t\t\ttitle: \"Contract gate mismatch: tests expected\",\n\t\t\t\tseverity: \"high\",\n\t\t\t\tcategory: \"contract\",\n\t\t\t\tdetail: \"Quality gates mention tests/coverage but no test files were detected in scan scope.\",\n\t\t\t\trecommendation: \"Add coverage-aligned tests or adjust contract gates before implementation.\",\n\t\t\t});\n\t\t}\n\t\tif (containsAny(gates.join(\" \"), [\"no todo\", \"todo=0\", \"todo:0\"]) && counters.todoCount > 0) {\n\t\t\tfindings.push({\n\t\t\t\tid: \"contract:todo-mismatch\",\n\t\t\t\ttitle: \"Contract gate mismatch: TODO markers present\",\n\t\t\t\tseverity: \"medium\",\n\t\t\t\tcategory: \"contract\",\n\t\t\t\tdetail: `Contract requires TODO cleanup but ${counters.todoCount} markers were found.`,\n\t\t\t\trecommendation: \"Resolve TODO/FIXME markers or relax gate for current cycle.\",\n\t\t\t});\n\t\t}\n\n\t\treturn { files, findings, counters };\n\t}\n\n\tprivate walkFiles(profile: BlastProfile): string[] {\n\t\tconst maxFiles = profile === \"full\" ? 18_000 : 6_000;\n\t\tconst stack = [this.cwd];\n\t\tconst files: string[] = [];\n\n\t\twhile (stack.length > 0 && files.length < maxFiles) {\n\t\t\tconst dir = stack.pop();\n\t\t\tif (!dir) break;\n\n\t\t\tlet entries;\n\t\t\ttry {\n\t\t\t\tentries = readdirSync(dir, { withFileTypes: true });\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst absolutePath = join(dir, entry.name);\n\t\t\t\tif (entry.isDirectory()) {\n\t\t\t\t\tif (EXCLUDED_DIR_NAMES.has(entry.name)) continue;\n\t\t\t\t\tstack.push(absolutePath);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!entry.isFile()) continue;\n\t\t\t\tif (!SCAN_TEXT_EXTENSIONS.has(getExtension(entry.name))) continue;\n\t\t\t\tfiles.push(absolutePath);\n\t\t\t\tif (files.length >= maxFiles) break;\n\t\t\t}\n\t\t}\n\n\t\treturn files.sort((a, b) => a.localeCompare(b));\n\t}\n\n\tprivate buildSummary(counters: BlastScanCounters, findings: BlastFinding[]): string {\n\t\tconst high = countSeverity(findings, \"high\");\n\t\tconst medium = countSeverity(findings, \"medium\");\n\t\tconst low = countSeverity(findings, \"low\");\n\t\tconst highestRisk = findings.find((item) => item.severity === \"high\") ?? findings[0];\n\n\t\tconst highestLine = highestRisk\n\t\t\t? ` Highest risk: ${highestRisk.title}${highestRisk.path ? ` (${highestRisk.path})` : \"\"}.`\n\t\t\t: \"\";\n\t\treturn `Scanned ${counters.files} files (${counters.lines} lines). Findings: ${high} high, ${medium} medium, ${low} low.${highestLine}`;\n\t}\n\n\tprivate buildNextSteps(findings: BlastFinding[], contract: EngineeringContract): string[] {\n\t\tconst steps: string[] = [];\n\t\tconst high = findings.filter((item) => item.severity === \"high\");\n\t\tconst medium = findings.filter((item) => item.severity === \"medium\");\n\n\t\tif (high.length > 0) {\n\t\t\tsteps.push(\"Address all HIGH findings first and add regression checks before refactors.\");\n\t\t}\n\t\tif (medium.length > 0) {\n\t\t\tsteps.push(\"Batch MEDIUM findings by module and apply low-blast-radius fixes incrementally.\");\n\t\t}\n\t\tif ((contract.quality_gates ?? []).length > 0) {\n\t\t\tsteps.push(\"Re-run /blast after changes to verify contract quality gates.\");\n\t\t}\n\t\tif (steps.length === 0) {\n\t\t\tsteps.push(\"No major risks detected; proceed with planned changes and keep /blast as pre-merge audit.\");\n\t\t}\n\t\treturn steps.slice(0, 3);\n\t}\n\n\tprivate buildReportMarkdown(payload: {\n\t\trunId: string;\n\t\tprofile: BlastProfile;\n\t\tstartedAt: string;\n\t\tcompletedAt: string;\n\t\tdurationMs: number;\n\t\tcounters: BlastScanCounters;\n\t\tfindings: BlastFinding[];\n\t\tsummary: string;\n\t\tnextSteps: string[];\n\t\tcontract: EngineeringContract;\n\t}): string {\n\t\tconst high = countSeverity(payload.findings, \"high\");\n\t\tconst medium = countSeverity(payload.findings, \"medium\");\n\t\tconst low = countSeverity(payload.findings, \"low\");\n\t\tconst topFindings = payload.findings\n\t\t\t.sort((a, b) => {\n\t\t\t\tconst score = (severity: BlastSeverity): number => (severity === \"high\" ? 3 : severity === \"medium\" ? 2 : 1);\n\t\t\t\treturn score(b.severity) - score(a.severity);\n\t\t\t})\n\t\t\t.slice(0, 20);\n\n\t\tconst contractLines: string[] = [];\n\t\tif (payload.contract.goal) contractLines.push(`- goal: ${payload.contract.goal}`);\n\t\tif (payload.contract.quality_gates && payload.contract.quality_gates.length > 0) {\n\t\t\tcontractLines.push(`- quality_gates: ${payload.contract.quality_gates.join(\"; \")}`);\n\t\t}\n\t\tif (payload.contract.constraints && payload.contract.constraints.length > 0) {\n\t\t\tcontractLines.push(`- constraints: ${payload.contract.constraints.join(\"; \")}`);\n\t\t}\n\t\tconst contractSection = contractLines.length > 0 ? contractLines.join(\"\\n\") : \"- none\";\n\n\t\treturn [\n\t\t\t`# Blast Audit Report`,\n\t\t\t``,\n\t\t\t`- run_id: ${payload.runId}`,\n\t\t\t`- profile: ${payload.profile}`,\n\t\t\t`- started_at: ${payload.startedAt}`,\n\t\t\t`- completed_at: ${payload.completedAt}`,\n\t\t\t`- duration_ms: ${payload.durationMs}`,\n\t\t\t``,\n\t\t\t`## Executive Summary`,\n\t\t\t`${payload.summary}`,\n\t\t\t``,\n\t\t\t`## Scan Metrics`,\n\t\t\t`- files_scanned: ${payload.counters.files}`,\n\t\t\t`- lines_scanned: ${payload.counters.lines}`,\n\t\t\t`- test_files: ${payload.counters.testFiles}`,\n\t\t\t`- TODO/FIXME markers: ${payload.counters.todoCount}`,\n\t\t\t`- debug artifacts: ${payload.counters.debugCount}`,\n\t\t\t`- unsafe dynamic execution markers: ${payload.counters.unsafeEvalCount}`,\n\t\t\t`- large files skipped: ${payload.counters.largeFiles}`,\n\t\t\t``,\n\t\t\t`## Findings Overview`,\n\t\t\t`- high: ${high}`,\n\t\t\t`- medium: ${medium}`,\n\t\t\t`- low: ${low}`,\n\t\t\t``,\n\t\t\t`## Contract Context`,\n\t\t\t`${contractSection}`,\n\t\t\t``,\n\t\t\t`## Top Findings`,\n\t\t\ttopFindings.length > 0 ? topFindings.map(serializeFinding).join(\"\\n\") : \"- none\",\n\t\t\t``,\n\t\t\t`## Recommended Next Steps`,\n\t\t\tpayload.nextSteps.map((step, index) => `${index + 1}. ${step}`).join(\"\\n\"),\n\t\t].join(\"\\n\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type ContractScope = "project" | "session";
|
|
2
|
+
export interface EngineeringContract {
|
|
3
|
+
goal?: string;
|
|
4
|
+
scope_include?: string[];
|
|
5
|
+
scope_exclude?: string[];
|
|
6
|
+
constraints?: string[];
|
|
7
|
+
quality_gates?: string[];
|
|
8
|
+
definition_of_done?: string[];
|
|
9
|
+
assumptions?: string[];
|
|
10
|
+
non_goals?: string[];
|
|
11
|
+
risks?: string[];
|
|
12
|
+
deliverables?: string[];
|
|
13
|
+
success_metrics?: string[];
|
|
14
|
+
stakeholders?: string[];
|
|
15
|
+
owner?: string;
|
|
16
|
+
timebox?: string;
|
|
17
|
+
notes?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ContractState {
|
|
20
|
+
projectPath: string;
|
|
21
|
+
hasProjectFile: boolean;
|
|
22
|
+
project: EngineeringContract;
|
|
23
|
+
sessionOverlay: EngineeringContract;
|
|
24
|
+
effective: EngineeringContract;
|
|
25
|
+
}
|
|
26
|
+
export declare class ContractValidationError extends Error {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
export declare class ContractParseError extends Error {
|
|
30
|
+
readonly filePath: string;
|
|
31
|
+
constructor(filePath: string, message: string);
|
|
32
|
+
}
|
|
33
|
+
export declare function normalizeEngineeringContract(payload: unknown): EngineeringContract;
|
|
34
|
+
export declare function deepMergeContracts(base: EngineeringContract, override: EngineeringContract): EngineeringContract;
|
|
35
|
+
export interface ContractServiceOptions {
|
|
36
|
+
cwd: string;
|
|
37
|
+
}
|
|
38
|
+
export declare class ContractService {
|
|
39
|
+
private readonly cwd;
|
|
40
|
+
private sessionOverlay;
|
|
41
|
+
constructor(options: ContractServiceOptions);
|
|
42
|
+
getProjectPath(): string;
|
|
43
|
+
getSessionOverlay(): EngineeringContract;
|
|
44
|
+
setSessionOverlay(payload: unknown): EngineeringContract;
|
|
45
|
+
clearSessionOverlay(): void;
|
|
46
|
+
loadProjectContract(): EngineeringContract;
|
|
47
|
+
saveProjectContract(payload: unknown): EngineeringContract;
|
|
48
|
+
clearProjectContract(): boolean;
|
|
49
|
+
save(scope: ContractScope, payload: unknown): EngineeringContract;
|
|
50
|
+
clear(scope: ContractScope): boolean;
|
|
51
|
+
getState(): ContractState;
|
|
52
|
+
buildPromptContext(maxItemsPerList?: number): string | undefined;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/core/contract.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,mBAAmB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,cAAc,EAAE,mBAAmB,CAAC;IACpC,SAAS,EAAE,mBAAmB,CAAC;CAC/B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI3B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK7C;AAsID,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAyClF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,mBAAmB,GAAG,mBAAmB,CAWhH;AA4BD,MAAM,WAAW,sBAAsB;IACtC,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,cAAc,CAA2B;gBAErC,OAAO,EAAE,sBAAsB;IAI3C,cAAc,IAAI,MAAM;IAIxB,iBAAiB,IAAI,mBAAmB;IAIxC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB;IAMxD,mBAAmB,IAAI,IAAI;IAI3B,mBAAmB,IAAI,mBAAmB;IAI1C,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB;IAM1D,oBAAoB,IAAI,OAAO;IAO/B,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,GAAG,mBAAmB;IAOjE,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAQpC,QAAQ,IAAI,aAAa;IAezB,kBAAkB,CAAC,eAAe,SAAI,GAAG,MAAM,GAAG,SAAS;CAkC3D"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import AjvModule from "ajv";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
const Ajv = AjvModule.default || AjvModule;
|
|
5
|
+
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true });
|
|
6
|
+
export class ContractValidationError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "ContractValidationError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class ContractParseError extends Error {
|
|
13
|
+
constructor(filePath, message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "ContractParseError";
|
|
16
|
+
this.filePath = filePath;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const CONTRACT_SCHEMA = {
|
|
20
|
+
type: "object",
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
properties: {
|
|
23
|
+
goal: { type: "string" },
|
|
24
|
+
scope_include: {
|
|
25
|
+
type: "array",
|
|
26
|
+
items: { type: "string" },
|
|
27
|
+
},
|
|
28
|
+
scope_exclude: {
|
|
29
|
+
type: "array",
|
|
30
|
+
items: { type: "string" },
|
|
31
|
+
},
|
|
32
|
+
constraints: {
|
|
33
|
+
type: "array",
|
|
34
|
+
items: { type: "string" },
|
|
35
|
+
},
|
|
36
|
+
quality_gates: {
|
|
37
|
+
type: "array",
|
|
38
|
+
items: { type: "string" },
|
|
39
|
+
},
|
|
40
|
+
definition_of_done: {
|
|
41
|
+
type: "array",
|
|
42
|
+
items: { type: "string" },
|
|
43
|
+
},
|
|
44
|
+
assumptions: {
|
|
45
|
+
type: "array",
|
|
46
|
+
items: { type: "string" },
|
|
47
|
+
},
|
|
48
|
+
non_goals: {
|
|
49
|
+
type: "array",
|
|
50
|
+
items: { type: "string" },
|
|
51
|
+
},
|
|
52
|
+
risks: {
|
|
53
|
+
type: "array",
|
|
54
|
+
items: { type: "string" },
|
|
55
|
+
},
|
|
56
|
+
deliverables: {
|
|
57
|
+
type: "array",
|
|
58
|
+
items: { type: "string" },
|
|
59
|
+
},
|
|
60
|
+
success_metrics: {
|
|
61
|
+
type: "array",
|
|
62
|
+
items: { type: "string" },
|
|
63
|
+
},
|
|
64
|
+
stakeholders: {
|
|
65
|
+
type: "array",
|
|
66
|
+
items: { type: "string" },
|
|
67
|
+
},
|
|
68
|
+
owner: { type: "string" },
|
|
69
|
+
timebox: { type: "string" },
|
|
70
|
+
notes: { type: "string" },
|
|
71
|
+
},
|
|
72
|
+
required: [],
|
|
73
|
+
};
|
|
74
|
+
const validateContract = ajv.compile(CONTRACT_SCHEMA);
|
|
75
|
+
function isRecord(value) {
|
|
76
|
+
return typeof value === "object" && value !== null;
|
|
77
|
+
}
|
|
78
|
+
function normalizeString(value) {
|
|
79
|
+
if (typeof value !== "string")
|
|
80
|
+
return undefined;
|
|
81
|
+
const normalized = value.trim();
|
|
82
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
83
|
+
}
|
|
84
|
+
function normalizeStringArray(value) {
|
|
85
|
+
if (!Array.isArray(value))
|
|
86
|
+
return undefined;
|
|
87
|
+
const normalized = value
|
|
88
|
+
.filter((item) => typeof item === "string")
|
|
89
|
+
.map((item) => item.trim())
|
|
90
|
+
.filter((item) => item.length > 0);
|
|
91
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
92
|
+
}
|
|
93
|
+
function cloneContract(contract) {
|
|
94
|
+
return {
|
|
95
|
+
...(contract.goal ? { goal: contract.goal } : {}),
|
|
96
|
+
...(contract.scope_include ? { scope_include: [...contract.scope_include] } : {}),
|
|
97
|
+
...(contract.scope_exclude ? { scope_exclude: [...contract.scope_exclude] } : {}),
|
|
98
|
+
...(contract.constraints ? { constraints: [...contract.constraints] } : {}),
|
|
99
|
+
...(contract.quality_gates ? { quality_gates: [...contract.quality_gates] } : {}),
|
|
100
|
+
...(contract.definition_of_done ? { definition_of_done: [...contract.definition_of_done] } : {}),
|
|
101
|
+
...(contract.assumptions ? { assumptions: [...contract.assumptions] } : {}),
|
|
102
|
+
...(contract.non_goals ? { non_goals: [...contract.non_goals] } : {}),
|
|
103
|
+
...(contract.risks ? { risks: [...contract.risks] } : {}),
|
|
104
|
+
...(contract.deliverables ? { deliverables: [...contract.deliverables] } : {}),
|
|
105
|
+
...(contract.success_metrics ? { success_metrics: [...contract.success_metrics] } : {}),
|
|
106
|
+
...(contract.stakeholders ? { stakeholders: [...contract.stakeholders] } : {}),
|
|
107
|
+
...(contract.owner ? { owner: contract.owner } : {}),
|
|
108
|
+
...(contract.timebox ? { timebox: contract.timebox } : {}),
|
|
109
|
+
...(contract.notes ? { notes: contract.notes } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function formatValidationError(payload) {
|
|
113
|
+
const errors = validateContract.errors ?? [];
|
|
114
|
+
if (errors.length === 0) {
|
|
115
|
+
return `Invalid contract payload: ${JSON.stringify(payload)}`;
|
|
116
|
+
}
|
|
117
|
+
const details = errors
|
|
118
|
+
.map((error) => {
|
|
119
|
+
const path = error.instancePath || "/";
|
|
120
|
+
return `${path} ${error.message ?? "is invalid"}`;
|
|
121
|
+
})
|
|
122
|
+
.join("; ");
|
|
123
|
+
return `Invalid contract payload: ${details}`;
|
|
124
|
+
}
|
|
125
|
+
export function normalizeEngineeringContract(payload) {
|
|
126
|
+
if (!isRecord(payload)) {
|
|
127
|
+
throw new ContractValidationError("Contract payload must be a JSON object.");
|
|
128
|
+
}
|
|
129
|
+
if (!validateContract(payload)) {
|
|
130
|
+
throw new ContractValidationError(formatValidationError(payload));
|
|
131
|
+
}
|
|
132
|
+
const goal = normalizeString(payload.goal);
|
|
133
|
+
const scopeInclude = normalizeStringArray(payload.scope_include);
|
|
134
|
+
const scopeExclude = normalizeStringArray(payload.scope_exclude);
|
|
135
|
+
const constraints = normalizeStringArray(payload.constraints);
|
|
136
|
+
const qualityGates = normalizeStringArray(payload.quality_gates);
|
|
137
|
+
const definitionOfDone = normalizeStringArray(payload.definition_of_done);
|
|
138
|
+
const assumptions = normalizeStringArray(payload.assumptions);
|
|
139
|
+
const nonGoals = normalizeStringArray(payload.non_goals);
|
|
140
|
+
const risks = normalizeStringArray(payload.risks);
|
|
141
|
+
const deliverables = normalizeStringArray(payload.deliverables);
|
|
142
|
+
const successMetrics = normalizeStringArray(payload.success_metrics);
|
|
143
|
+
const stakeholders = normalizeStringArray(payload.stakeholders);
|
|
144
|
+
const owner = normalizeString(payload.owner);
|
|
145
|
+
const timebox = normalizeString(payload.timebox);
|
|
146
|
+
const notes = normalizeString(payload.notes);
|
|
147
|
+
return {
|
|
148
|
+
...(goal ? { goal } : {}),
|
|
149
|
+
...(scopeInclude ? { scope_include: scopeInclude } : {}),
|
|
150
|
+
...(scopeExclude ? { scope_exclude: scopeExclude } : {}),
|
|
151
|
+
...(constraints ? { constraints } : {}),
|
|
152
|
+
...(qualityGates ? { quality_gates: qualityGates } : {}),
|
|
153
|
+
...(definitionOfDone ? { definition_of_done: definitionOfDone } : {}),
|
|
154
|
+
...(assumptions ? { assumptions } : {}),
|
|
155
|
+
...(nonGoals ? { non_goals: nonGoals } : {}),
|
|
156
|
+
...(risks ? { risks } : {}),
|
|
157
|
+
...(deliverables ? { deliverables } : {}),
|
|
158
|
+
...(successMetrics ? { success_metrics: successMetrics } : {}),
|
|
159
|
+
...(stakeholders ? { stakeholders } : {}),
|
|
160
|
+
...(owner ? { owner } : {}),
|
|
161
|
+
...(timebox ? { timebox } : {}),
|
|
162
|
+
...(notes ? { notes } : {}),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
export function deepMergeContracts(base, override) {
|
|
166
|
+
const merged = cloneContract(base);
|
|
167
|
+
for (const [key, value] of Object.entries(override)) {
|
|
168
|
+
if (value === undefined)
|
|
169
|
+
continue;
|
|
170
|
+
if (Array.isArray(value)) {
|
|
171
|
+
merged[key] = [...value];
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
merged[key] = value;
|
|
175
|
+
}
|
|
176
|
+
return normalizeEngineeringContract(merged);
|
|
177
|
+
}
|
|
178
|
+
function readContractFile(filePath) {
|
|
179
|
+
if (!existsSync(filePath)) {
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
let parsed;
|
|
183
|
+
try {
|
|
184
|
+
parsed = JSON.parse(readFileSync(filePath, "utf8"));
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
188
|
+
throw new ContractParseError(filePath, `Failed to parse contract JSON: ${message}`);
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
return normalizeEngineeringContract(parsed);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
195
|
+
throw new ContractParseError(filePath, message);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function writeContractFile(filePath, contract) {
|
|
199
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
200
|
+
writeFileSync(filePath, `${JSON.stringify(contract, null, 2)}\n`, "utf8");
|
|
201
|
+
}
|
|
202
|
+
export class ContractService {
|
|
203
|
+
constructor(options) {
|
|
204
|
+
this.sessionOverlay = {};
|
|
205
|
+
this.cwd = options.cwd;
|
|
206
|
+
}
|
|
207
|
+
getProjectPath() {
|
|
208
|
+
return join(this.cwd, ".iosm", "contract.json");
|
|
209
|
+
}
|
|
210
|
+
getSessionOverlay() {
|
|
211
|
+
return cloneContract(this.sessionOverlay);
|
|
212
|
+
}
|
|
213
|
+
setSessionOverlay(payload) {
|
|
214
|
+
const normalized = normalizeEngineeringContract(payload);
|
|
215
|
+
this.sessionOverlay = normalized;
|
|
216
|
+
return cloneContract(normalized);
|
|
217
|
+
}
|
|
218
|
+
clearSessionOverlay() {
|
|
219
|
+
this.sessionOverlay = {};
|
|
220
|
+
}
|
|
221
|
+
loadProjectContract() {
|
|
222
|
+
return readContractFile(this.getProjectPath());
|
|
223
|
+
}
|
|
224
|
+
saveProjectContract(payload) {
|
|
225
|
+
const normalized = normalizeEngineeringContract(payload);
|
|
226
|
+
writeContractFile(this.getProjectPath(), normalized);
|
|
227
|
+
return cloneContract(normalized);
|
|
228
|
+
}
|
|
229
|
+
clearProjectContract() {
|
|
230
|
+
const projectPath = this.getProjectPath();
|
|
231
|
+
if (!existsSync(projectPath))
|
|
232
|
+
return false;
|
|
233
|
+
rmSync(projectPath, { force: true });
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
save(scope, payload) {
|
|
237
|
+
if (scope === "project") {
|
|
238
|
+
return this.saveProjectContract(payload);
|
|
239
|
+
}
|
|
240
|
+
return this.setSessionOverlay(payload);
|
|
241
|
+
}
|
|
242
|
+
clear(scope) {
|
|
243
|
+
if (scope === "project") {
|
|
244
|
+
return this.clearProjectContract();
|
|
245
|
+
}
|
|
246
|
+
this.clearSessionOverlay();
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
getState() {
|
|
250
|
+
const projectPath = this.getProjectPath();
|
|
251
|
+
const hasProjectFile = existsSync(projectPath);
|
|
252
|
+
const project = this.loadProjectContract();
|
|
253
|
+
const sessionOverlay = this.getSessionOverlay();
|
|
254
|
+
const effective = deepMergeContracts(project, sessionOverlay);
|
|
255
|
+
return {
|
|
256
|
+
projectPath,
|
|
257
|
+
hasProjectFile,
|
|
258
|
+
project,
|
|
259
|
+
sessionOverlay,
|
|
260
|
+
effective,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
buildPromptContext(maxItemsPerList = 4) {
|
|
264
|
+
const state = this.getState();
|
|
265
|
+
const contract = state.effective;
|
|
266
|
+
if (Object.keys(contract).length === 0) {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
const lines = ["Active engineering contract (effective):"];
|
|
270
|
+
if (contract.goal)
|
|
271
|
+
lines.push(`- goal: ${contract.goal}`);
|
|
272
|
+
const pushList = (label, values) => {
|
|
273
|
+
if (!values || values.length === 0)
|
|
274
|
+
return;
|
|
275
|
+
const preview = values.slice(0, Math.max(1, maxItemsPerList));
|
|
276
|
+
const suffix = values.length > preview.length ? ` (+${values.length - preview.length} more)` : "";
|
|
277
|
+
lines.push(`- ${label}: ${preview.join("; ")}${suffix}`);
|
|
278
|
+
};
|
|
279
|
+
pushList("scope_include", contract.scope_include);
|
|
280
|
+
pushList("scope_exclude", contract.scope_exclude);
|
|
281
|
+
pushList("constraints", contract.constraints);
|
|
282
|
+
pushList("quality_gates", contract.quality_gates);
|
|
283
|
+
pushList("definition_of_done", contract.definition_of_done);
|
|
284
|
+
pushList("assumptions", contract.assumptions);
|
|
285
|
+
pushList("non_goals", contract.non_goals);
|
|
286
|
+
pushList("risks", contract.risks);
|
|
287
|
+
pushList("deliverables", contract.deliverables);
|
|
288
|
+
pushList("success_metrics", contract.success_metrics);
|
|
289
|
+
pushList("stakeholders", contract.stakeholders);
|
|
290
|
+
if (contract.owner)
|
|
291
|
+
lines.push(`- owner: ${contract.owner}`);
|
|
292
|
+
if (contract.timebox)
|
|
293
|
+
lines.push(`- timebox: ${contract.timebox}`);
|
|
294
|
+
if (contract.notes)
|
|
295
|
+
lines.push(`- notes: ${contract.notes}`);
|
|
296
|
+
lines.push("Treat this contract as execution constraints unless user explicitly overrides it.");
|
|
297
|
+
return lines.join("\n");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/core/contract.ts"],"names":[],"mappings":"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","sourcesContent":["import AjvModule from \"ajv\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst Ajv = (AjvModule as any).default || AjvModule;\nconst ajv = new Ajv({ allErrors: true, allowUnionTypes: true });\n\nexport type ContractScope = \"project\" | \"session\";\n\nexport interface EngineeringContract {\n\tgoal?: string;\n\tscope_include?: string[];\n\tscope_exclude?: string[];\n\tconstraints?: string[];\n\tquality_gates?: string[];\n\tdefinition_of_done?: string[];\n\tassumptions?: string[];\n\tnon_goals?: string[];\n\trisks?: string[];\n\tdeliverables?: string[];\n\tsuccess_metrics?: string[];\n\tstakeholders?: string[];\n\towner?: string;\n\ttimebox?: string;\n\tnotes?: string;\n}\n\nexport interface ContractState {\n\tprojectPath: string;\n\thasProjectFile: boolean;\n\tproject: EngineeringContract;\n\tsessionOverlay: EngineeringContract;\n\teffective: EngineeringContract;\n}\n\nexport class ContractValidationError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ContractValidationError\";\n\t}\n}\n\nexport class ContractParseError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ContractParseError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\ntype ContractSchemaPayload = {\n\tgoal?: string;\n\tscope_include?: string[];\n\tscope_exclude?: string[];\n\tconstraints?: string[];\n\tquality_gates?: string[];\n\tdefinition_of_done?: string[];\n\tassumptions?: string[];\n\tnon_goals?: string[];\n\trisks?: string[];\n\tdeliverables?: string[];\n\tsuccess_metrics?: string[];\n\tstakeholders?: string[];\n\towner?: string;\n\ttimebox?: string;\n\tnotes?: string;\n};\n\nconst CONTRACT_SCHEMA = {\n\ttype: \"object\",\n\tadditionalProperties: false,\n\tproperties: {\n\t\tgoal: { type: \"string\" },\n\t\tscope_include: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tscope_exclude: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tconstraints: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tquality_gates: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tdefinition_of_done: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tassumptions: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tnon_goals: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\trisks: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tdeliverables: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tsuccess_metrics: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\tstakeholders: {\n\t\t\ttype: \"array\",\n\t\t\titems: { type: \"string\" },\n\t\t},\n\t\towner: { type: \"string\" },\n\t\ttimebox: { type: \"string\" },\n\t\tnotes: { type: \"string\" },\n\t},\n\trequired: [],\n} as const;\n\nconst validateContract = ajv.compile(CONTRACT_SCHEMA as any) as {\n\t(payload: unknown): boolean;\n\terrors?: Array<{ instancePath?: string; message?: string }>;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction normalizeString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst normalized = value\n\t\t.filter((item): item is string => typeof item === \"string\")\n\t\t.map((item) => item.trim())\n\t\t.filter((item) => item.length > 0);\n\treturn normalized.length > 0 ? normalized : undefined;\n}\n\nfunction cloneContract(contract: EngineeringContract): EngineeringContract {\n\treturn {\n\t\t...(contract.goal ? { goal: contract.goal } : {}),\n\t\t...(contract.scope_include ? { scope_include: [...contract.scope_include] } : {}),\n\t\t...(contract.scope_exclude ? { scope_exclude: [...contract.scope_exclude] } : {}),\n\t\t...(contract.constraints ? { constraints: [...contract.constraints] } : {}),\n\t\t...(contract.quality_gates ? { quality_gates: [...contract.quality_gates] } : {}),\n\t\t...(contract.definition_of_done ? { definition_of_done: [...contract.definition_of_done] } : {}),\n\t\t...(contract.assumptions ? { assumptions: [...contract.assumptions] } : {}),\n\t\t...(contract.non_goals ? { non_goals: [...contract.non_goals] } : {}),\n\t\t...(contract.risks ? { risks: [...contract.risks] } : {}),\n\t\t...(contract.deliverables ? { deliverables: [...contract.deliverables] } : {}),\n\t\t...(contract.success_metrics ? { success_metrics: [...contract.success_metrics] } : {}),\n\t\t...(contract.stakeholders ? { stakeholders: [...contract.stakeholders] } : {}),\n\t\t...(contract.owner ? { owner: contract.owner } : {}),\n\t\t...(contract.timebox ? { timebox: contract.timebox } : {}),\n\t\t...(contract.notes ? { notes: contract.notes } : {}),\n\t};\n}\n\nfunction formatValidationError(payload: unknown): string {\n\tconst errors = validateContract.errors ?? [];\n\tif (errors.length === 0) {\n\t\treturn `Invalid contract payload: ${JSON.stringify(payload)}`;\n\t}\n\tconst details = errors\n\t\t.map((error: { instancePath?: string; message?: string }) => {\n\t\t\tconst path = error.instancePath || \"/\";\n\t\t\treturn `${path} ${error.message ?? \"is invalid\"}`;\n\t\t})\n\t\t.join(\"; \");\n\treturn `Invalid contract payload: ${details}`;\n}\n\nexport function normalizeEngineeringContract(payload: unknown): EngineeringContract {\n\tif (!isRecord(payload)) {\n\t\tthrow new ContractValidationError(\"Contract payload must be a JSON object.\");\n\t}\n\tif (!validateContract(payload)) {\n\t\tthrow new ContractValidationError(formatValidationError(payload));\n\t}\n\n\tconst goal = normalizeString(payload.goal);\n\tconst scopeInclude = normalizeStringArray(payload.scope_include);\n\tconst scopeExclude = normalizeStringArray(payload.scope_exclude);\n\tconst constraints = normalizeStringArray(payload.constraints);\n\tconst qualityGates = normalizeStringArray(payload.quality_gates);\n\tconst definitionOfDone = normalizeStringArray(payload.definition_of_done);\n\tconst assumptions = normalizeStringArray(payload.assumptions);\n\tconst nonGoals = normalizeStringArray(payload.non_goals);\n\tconst risks = normalizeStringArray(payload.risks);\n\tconst deliverables = normalizeStringArray(payload.deliverables);\n\tconst successMetrics = normalizeStringArray(payload.success_metrics);\n\tconst stakeholders = normalizeStringArray(payload.stakeholders);\n\tconst owner = normalizeString(payload.owner);\n\tconst timebox = normalizeString(payload.timebox);\n\tconst notes = normalizeString(payload.notes);\n\n\treturn {\n\t\t...(goal ? { goal } : {}),\n\t\t...(scopeInclude ? { scope_include: scopeInclude } : {}),\n\t\t...(scopeExclude ? { scope_exclude: scopeExclude } : {}),\n\t\t...(constraints ? { constraints } : {}),\n\t\t...(qualityGates ? { quality_gates: qualityGates } : {}),\n\t\t...(definitionOfDone ? { definition_of_done: definitionOfDone } : {}),\n\t\t...(assumptions ? { assumptions } : {}),\n\t\t...(nonGoals ? { non_goals: nonGoals } : {}),\n\t\t...(risks ? { risks } : {}),\n\t\t...(deliverables ? { deliverables } : {}),\n\t\t...(successMetrics ? { success_metrics: successMetrics } : {}),\n\t\t...(stakeholders ? { stakeholders } : {}),\n\t\t...(owner ? { owner } : {}),\n\t\t...(timebox ? { timebox } : {}),\n\t\t...(notes ? { notes } : {}),\n\t};\n}\n\nexport function deepMergeContracts(base: EngineeringContract, override: EngineeringContract): EngineeringContract {\n\tconst merged: EngineeringContract = cloneContract(base);\n\tfor (const [key, value] of Object.entries(override) as Array<[keyof EngineeringContract, unknown]>) {\n\t\tif (value === undefined) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\t(merged as Record<string, unknown>)[key] = [...value];\n\t\t\tcontinue;\n\t\t}\n\t\t(merged as Record<string, unknown>)[key] = value;\n\t}\n\treturn normalizeEngineeringContract(merged);\n}\n\nfunction readContractFile(filePath: string): EngineeringContract {\n\tif (!existsSync(filePath)) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(filePath, \"utf8\"));\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new ContractParseError(filePath, `Failed to parse contract JSON: ${message}`);\n\t}\n\n\ttry {\n\t\treturn normalizeEngineeringContract(parsed);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new ContractParseError(filePath, message);\n\t}\n}\n\nfunction writeContractFile(filePath: string, contract: EngineeringContract): void {\n\tmkdirSync(dirname(filePath), { recursive: true });\n\twriteFileSync(filePath, `${JSON.stringify(contract, null, 2)}\\n`, \"utf8\");\n}\n\nexport interface ContractServiceOptions {\n\tcwd: string;\n}\n\nexport class ContractService {\n\tprivate readonly cwd: string;\n\tprivate sessionOverlay: EngineeringContract = {};\n\n\tconstructor(options: ContractServiceOptions) {\n\t\tthis.cwd = options.cwd;\n\t}\n\n\tgetProjectPath(): string {\n\t\treturn join(this.cwd, \".iosm\", \"contract.json\");\n\t}\n\n\tgetSessionOverlay(): EngineeringContract {\n\t\treturn cloneContract(this.sessionOverlay);\n\t}\n\n\tsetSessionOverlay(payload: unknown): EngineeringContract {\n\t\tconst normalized = normalizeEngineeringContract(payload);\n\t\tthis.sessionOverlay = normalized;\n\t\treturn cloneContract(normalized);\n\t}\n\n\tclearSessionOverlay(): void {\n\t\tthis.sessionOverlay = {};\n\t}\n\n\tloadProjectContract(): EngineeringContract {\n\t\treturn readContractFile(this.getProjectPath());\n\t}\n\n\tsaveProjectContract(payload: unknown): EngineeringContract {\n\t\tconst normalized = normalizeEngineeringContract(payload);\n\t\twriteContractFile(this.getProjectPath(), normalized);\n\t\treturn cloneContract(normalized);\n\t}\n\n\tclearProjectContract(): boolean {\n\t\tconst projectPath = this.getProjectPath();\n\t\tif (!existsSync(projectPath)) return false;\n\t\trmSync(projectPath, { force: true });\n\t\treturn true;\n\t}\n\n\tsave(scope: ContractScope, payload: unknown): EngineeringContract {\n\t\tif (scope === \"project\") {\n\t\t\treturn this.saveProjectContract(payload);\n\t\t}\n\t\treturn this.setSessionOverlay(payload);\n\t}\n\n\tclear(scope: ContractScope): boolean {\n\t\tif (scope === \"project\") {\n\t\t\treturn this.clearProjectContract();\n\t\t}\n\t\tthis.clearSessionOverlay();\n\t\treturn true;\n\t}\n\n\tgetState(): ContractState {\n\t\tconst projectPath = this.getProjectPath();\n\t\tconst hasProjectFile = existsSync(projectPath);\n\t\tconst project = this.loadProjectContract();\n\t\tconst sessionOverlay = this.getSessionOverlay();\n\t\tconst effective = deepMergeContracts(project, sessionOverlay);\n\t\treturn {\n\t\t\tprojectPath,\n\t\t\thasProjectFile,\n\t\t\tproject,\n\t\t\tsessionOverlay,\n\t\t\teffective,\n\t\t};\n\t}\n\n\tbuildPromptContext(maxItemsPerList = 4): string | undefined {\n\t\tconst state = this.getState();\n\t\tconst contract = state.effective;\n\t\tif (Object.keys(contract).length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst lines: string[] = [\"Active engineering contract (effective):\"];\n\t\tif (contract.goal) lines.push(`- goal: ${contract.goal}`);\n\n\t\tconst pushList = (label: string, values: string[] | undefined): void => {\n\t\t\tif (!values || values.length === 0) return;\n\t\t\tconst preview = values.slice(0, Math.max(1, maxItemsPerList));\n\t\t\tconst suffix = values.length > preview.length ? ` (+${values.length - preview.length} more)` : \"\";\n\t\t\tlines.push(`- ${label}: ${preview.join(\"; \")}${suffix}`);\n\t\t};\n\n\t\tpushList(\"scope_include\", contract.scope_include);\n\t\tpushList(\"scope_exclude\", contract.scope_exclude);\n\t\tpushList(\"constraints\", contract.constraints);\n\t\tpushList(\"quality_gates\", contract.quality_gates);\n\t\tpushList(\"definition_of_done\", contract.definition_of_done);\n\t\tpushList(\"assumptions\", contract.assumptions);\n\t\tpushList(\"non_goals\", contract.non_goals);\n\t\tpushList(\"risks\", contract.risks);\n\t\tpushList(\"deliverables\", contract.deliverables);\n\t\tpushList(\"success_metrics\", contract.success_metrics);\n\t\tpushList(\"stakeholders\", contract.stakeholders);\n\t\tif (contract.owner) lines.push(`- owner: ${contract.owner}`);\n\t\tif (contract.timebox) lines.push(`- timebox: ${contract.timebox}`);\n\t\tif (contract.notes) lines.push(`- notes: ${contract.notes}`);\n\t\tlines.push(\"Treat this contract as execution constraints unless user explicitly overrides it.\");\n\t\treturn lines.join(\"\\n\");\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/semantic/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EAEpB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/semantic/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EAEpB,MAAM,YAAY,CAAC;AAoLpB,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjG;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,wBAAwB,CAgBtH;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAyB5F;AAED,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACd,MAAM,CAQR;AAED,wBAAgB,gCAAgC,CAC/C,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACd,MAAM,CA8BR;AAED,wBAAgB,8BAA8B,IAAI,oBAAoB,CAcrE"}
|
|
@@ -5,6 +5,7 @@ const DEFAULT_INCLUDE_GLOBS = ["**/*.{ts,tsx,js,jsx,py,go,rs,java,md,json,yaml,y
|
|
|
5
5
|
const DEFAULT_EXCLUDE_GLOBS = ["**/.git/**", "**/node_modules/**", "**/dist/**", "**/build/**", "**/.iosm/**"];
|
|
6
6
|
const DEFAULT_CONFIG = {
|
|
7
7
|
enabled: true,
|
|
8
|
+
autoIndex: true,
|
|
8
9
|
provider: {
|
|
9
10
|
type: "openrouter",
|
|
10
11
|
model: "openai/text-embedding-3-small",
|
|
@@ -110,6 +111,7 @@ function parseSemanticConfigFile(path) {
|
|
|
110
111
|
: undefined;
|
|
111
112
|
result.semanticSearch = {
|
|
112
113
|
enabled: asBoolean(rawSemantic.enabled),
|
|
114
|
+
autoIndex: asBoolean(rawSemantic.autoIndex),
|
|
113
115
|
provider,
|
|
114
116
|
index,
|
|
115
117
|
};
|
|
@@ -141,6 +143,7 @@ function resolveSemanticSearchConfig(partial) {
|
|
|
141
143
|
}
|
|
142
144
|
return {
|
|
143
145
|
enabled: partial.enabled ?? DEFAULT_CONFIG.enabled,
|
|
146
|
+
autoIndex: partial.autoIndex ?? DEFAULT_CONFIG.autoIndex,
|
|
144
147
|
provider: {
|
|
145
148
|
type: providerType,
|
|
146
149
|
model,
|
|
@@ -223,6 +226,7 @@ export function upsertScopedSemanticSearchConfig(scope, config, cwd, agentDir) {
|
|
|
223
226
|
...current.file,
|
|
224
227
|
semanticSearch: {
|
|
225
228
|
enabled: config.enabled,
|
|
229
|
+
autoIndex: config.autoIndex,
|
|
226
230
|
provider: {
|
|
227
231
|
type: config.provider.type,
|
|
228
232
|
model: config.provider.model,
|
|
@@ -247,6 +251,7 @@ export function upsertScopedSemanticSearchConfig(scope, config, cwd, agentDir) {
|
|
|
247
251
|
export function getDefaultSemanticSearchConfig() {
|
|
248
252
|
return {
|
|
249
253
|
enabled: DEFAULT_CONFIG.enabled,
|
|
254
|
+
autoIndex: DEFAULT_CONFIG.autoIndex,
|
|
250
255
|
provider: { ...DEFAULT_CONFIG.provider },
|
|
251
256
|
index: {
|
|
252
257
|
includeGlobs: [...DEFAULT_CONFIG.index.includeGlobs],
|