@harness-engineering/cli 1.25.5 → 1.25.7

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.
Files changed (54) hide show
  1. package/dist/{agents-md-COWXFHR5.js → agents-md-QPO3H5HX.js} +3 -3
  2. package/dist/{architecture-EYPG4ZMC.js → architecture-IJLXRHZA.js} +4 -4
  3. package/dist/{assess-project-JQPEVJIA.js → assess-project-QU6XIVJK.js} +1 -1
  4. package/dist/bin/harness-mcp.js +16 -15
  5. package/dist/bin/harness.js +26 -25
  6. package/dist/business-knowledge-6RHYJOB3.js +7 -0
  7. package/dist/{check-phase-gate-AJRMDGYW.js → check-phase-gate-TNY64AOS.js} +4 -4
  8. package/dist/{chunk-HWLHJSJQ.js → chunk-2DF6OZLG.js} +2 -2
  9. package/dist/{chunk-2OIPQMU5.js → chunk-AS5DQT4S.js} +9 -9
  10. package/dist/{chunk-YFIALHGI.js → chunk-D3XL2FLX.js} +5 -5
  11. package/dist/{chunk-4NK7Z3BP.js → chunk-E5Z6NTTQ.js} +1 -1
  12. package/dist/{chunk-KWQTMJ3B.js → chunk-FRDS4XGD.js} +1 -1
  13. package/dist/{chunk-KXUCIAM4.js → chunk-G5SNXUIK.js} +1 -1
  14. package/dist/{chunk-2TFT7XRX.js → chunk-GVNT2YC7.js} +9 -9
  15. package/dist/{chunk-UI6NWJJK.js → chunk-IQO7IINR.js} +1 -1
  16. package/dist/{chunk-ZYYVDA5K.js → chunk-IT2KORSK.js} +1 -1
  17. package/dist/{chunk-2X42NMPD.js → chunk-JJQ3TW2E.js} +227 -109
  18. package/dist/{chunk-BOQRTARD.js → chunk-JPZY7ZQX.js} +1 -1
  19. package/dist/{chunk-24ZGGCIW.js → chunk-K35D7HF3.js} +1 -1
  20. package/dist/{chunk-KDHZAL4B.js → chunk-K533WNZG.js} +38 -2
  21. package/dist/{chunk-WN6YIQ66.js → chunk-KVJZQ2MV.js} +1 -1
  22. package/dist/{chunk-Q6ZEUMOF.js → chunk-LTCEV7VF.js} +3 -3
  23. package/dist/{chunk-BVRWLK5U.js → chunk-LXPRO2FH.js} +2 -2
  24. package/dist/{chunk-2X336Q7J.js → chunk-MCDCZMKN.js} +1 -1
  25. package/dist/{chunk-UB6NZNJJ.js → chunk-MLOGYWLY.js} +2 -2
  26. package/dist/{chunk-K2SON7TI.js → chunk-NKQEMWGT.js} +333 -121
  27. package/dist/{chunk-PVRKHUTA.js → chunk-PCOU2UXU.js} +8 -8
  28. package/dist/chunk-RC5ZY3EV.js +82 -0
  29. package/dist/{chunk-2OM5TA56.js → chunk-SZ3Q4XEO.js} +212 -183
  30. package/dist/{chunk-5R2LFUU3.js → chunk-TQRCODRJ.js} +1 -1
  31. package/dist/{chunk-KVK3KAFQ.js → chunk-XVJRFP7W.js} +6 -6
  32. package/dist/{chunk-JD4FGVHH.js → chunk-YRBNAHH4.js} +4 -4
  33. package/dist/{chunk-KHMKAC6E.js → chunk-ZIYLIYN4.js} +115 -103
  34. package/dist/{ci-workflow-35KBJC2U.js → ci-workflow-FJYRFZYQ.js} +3 -3
  35. package/dist/{dist-RADHOOXG.js → dist-HPWNWCT6.js} +3 -1
  36. package/dist/{dist-UMONICND.js → dist-ZV6GO6FA.js} +2 -2
  37. package/dist/{docs-T5J2AJH6.js → docs-7DW3DI4Z.js} +4 -4
  38. package/dist/{engine-KWHV2LUX.js → engine-P7EE2IWO.js} +3 -3
  39. package/dist/{entropy-GEBHWBPR.js → entropy-HCXRTDFU.js} +3 -3
  40. package/dist/{feedback-I4QPE3RI.js → feedback-Y4FYN3NR.js} +1 -1
  41. package/dist/{generate-agent-definitions-3XNR77ET.js → generate-agent-definitions-3EHPIWBO.js} +4 -4
  42. package/dist/{graph-loader-JHQVQRUS.js → graph-loader-KXVS3YK3.js} +1 -1
  43. package/dist/index.d.ts +14 -8
  44. package/dist/index.js +26 -25
  45. package/dist/{loader-MN2CZXPG.js → loader-SKHF3JVV.js} +3 -3
  46. package/dist/{mcp-XSU77BZY.js → mcp-MWYIPDQU.js} +16 -15
  47. package/dist/{performance-7I5MCEFP.js → performance-ADWH5NJY.js} +4 -4
  48. package/dist/{review-pipeline-PWPKJXSN.js → review-pipeline-TLKE5OQD.js} +3 -3
  49. package/dist/{runtime-ZYEFJSGS.js → runtime-7LYAW7GU.js} +3 -3
  50. package/dist/{scan-MPJ6JHUY.js → scan-BGJ7TLLV.js} +1 -1
  51. package/dist/{security-OVTGS7DL.js → security-5XWINYVB.js} +1 -1
  52. package/dist/{validate-ACIP5BUO.js → validate-BFFHYHY7.js} +4 -4
  53. package/dist/{validate-cross-check-OWITNCHN.js → validate-cross-check-GQX7OVCR.js} +3 -3
  54. package/package.json +5 -5
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ArchConfigSchema,
3
3
  init_dist
4
- } from "./chunk-KHMKAC6E.js";
4
+ } from "./chunk-ZIYLIYN4.js";
5
5
  import {
6
6
  Err,
7
7
  Ok
@@ -50,7 +50,7 @@ async function handleAssessProject(input) {
50
50
  let validateResult = null;
51
51
  if (checksToRun.has("validate")) {
52
52
  try {
53
- const { handleValidateProject } = await import("./validate-ACIP5BUO.js");
53
+ const { handleValidateProject } = await import("./validate-BFFHYHY7.js");
54
54
  const result = await handleValidateProject({ path: projectPath });
55
55
  const first = result.content[0];
56
56
  const parsed = first ? JSON.parse(first.text) : {};
@@ -75,7 +75,7 @@ async function handleAssessProject(input) {
75
75
  parallelChecks.push(
76
76
  (async () => {
77
77
  try {
78
- const { handleCheckDependencies } = await import("./architecture-EYPG4ZMC.js");
78
+ const { handleCheckDependencies } = await import("./architecture-IJLXRHZA.js");
79
79
  const result = await handleCheckDependencies({ path: projectPath });
80
80
  const first = result.content[0];
81
81
  const parsed = first ? JSON.parse(first.text) : {};
@@ -102,7 +102,7 @@ async function handleAssessProject(input) {
102
102
  parallelChecks.push(
103
103
  (async () => {
104
104
  try {
105
- const { handleCheckDocs } = await import("./docs-T5J2AJH6.js");
105
+ const { handleCheckDocs } = await import("./docs-7DW3DI4Z.js");
106
106
  const result = await handleCheckDocs({ path: projectPath, scope: "coverage" });
107
107
  const first = result.content[0];
108
108
  const parsed = first ? JSON.parse(first.text) : {};
@@ -129,7 +129,7 @@ async function handleAssessProject(input) {
129
129
  parallelChecks.push(
130
130
  (async () => {
131
131
  try {
132
- const { handleDetectEntropy } = await import("./entropy-GEBHWBPR.js");
132
+ const { handleDetectEntropy } = await import("./entropy-HCXRTDFU.js");
133
133
  const result = await handleDetectEntropy({ path: projectPath, type: "all" });
134
134
  const first = result.content[0];
135
135
  const parsed = first ? JSON.parse(first.text) : {};
@@ -156,7 +156,7 @@ async function handleAssessProject(input) {
156
156
  parallelChecks.push(
157
157
  (async () => {
158
158
  try {
159
- const { handleRunSecurityScan } = await import("./security-OVTGS7DL.js");
159
+ const { handleRunSecurityScan } = await import("./security-5XWINYVB.js");
160
160
  const result = await handleRunSecurityScan({ path: projectPath });
161
161
  const first = result.content[0];
162
162
  const parsed = first ? JSON.parse(first.text) : {};
@@ -188,7 +188,7 @@ async function handleAssessProject(input) {
188
188
  parallelChecks.push(
189
189
  (async () => {
190
190
  try {
191
- const { handleCheckPerformance } = await import("./performance-7I5MCEFP.js");
191
+ const { handleCheckPerformance } = await import("./performance-ADWH5NJY.js");
192
192
  const result = await handleCheckPerformance({ path: projectPath });
193
193
  if ("isError" in result && result.isError) {
194
194
  const msg = result.content[0]?.text ?? "Performance check failed";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveProjectConfig
3
- } from "./chunk-UI6NWJJK.js";
3
+ } from "./chunk-IQO7IINR.js";
4
4
  import {
5
5
  resultToMcpResponse
6
6
  } from "./chunk-EPUKTTJZ.js";
@@ -38,7 +38,7 @@ async function handleCheckDependencies(input) {
38
38
  const configResult = resolveProjectConfig(projectPath);
39
39
  if (!configResult.ok) return resultToMcpResponse(configResult);
40
40
  try {
41
- const { validateDependencies, TypeScriptParser } = await import("./dist-UMONICND.js");
41
+ const { validateDependencies, TypeScriptParser } = await import("./dist-ZV6GO6FA.js");
42
42
  const config = configResult.value;
43
43
  const rawLayers = Array.isArray(config.layers) ? config.layers : [];
44
44
  const layers = rawLayers.map((l) => ({
@@ -47,11 +47,11 @@ async function handleCheckDependencies(input) {
47
47
  allowedDependencies: l.allowedDependencies
48
48
  }));
49
49
  const parser = new TypeScriptParser();
50
- const { loadGraphStore } = await import("./graph-loader-JHQVQRUS.js");
50
+ const { loadGraphStore } = await import("./graph-loader-KXVS3YK3.js");
51
51
  const store = await loadGraphStore(projectPath);
52
52
  let graphDependencyData;
53
53
  if (store) {
54
- const { GraphConstraintAdapter } = await import("./dist-RADHOOXG.js");
54
+ const { GraphConstraintAdapter } = await import("./dist-HPWNWCT6.js");
55
55
  const adapter = new GraphConstraintAdapter(store);
56
56
  const graphData = adapter.computeDependencyGraph();
57
57
  graphDependencyData = {
@@ -13,13 +13,13 @@ import {
13
13
  NODE_STABILITY,
14
14
  init_dist as init_dist2,
15
15
  queryTraceability
16
- } from "./chunk-K2SON7TI.js";
16
+ } from "./chunk-NKQEMWGT.js";
17
17
  import {
18
18
  __esm,
19
19
  __export
20
20
  } from "./chunk-KFQGP6VL.js";
21
21
 
22
- // ../core/dist/chunk-QLTIBLN5.mjs
22
+ // ../core/dist/chunk-UWAI34RR.mjs
23
23
  import { z } from "zod";
24
24
  import { createHash } from "crypto";
25
25
  import { minimatch } from "minimatch";
@@ -1734,8 +1734,8 @@ async function toHaveMaxDepDepth(received, maxDepth) {
1734
1734
  };
1735
1735
  }
1736
1736
  var ArchMetricCategorySchema, ViolationSchema, MetricResultSchema, CategoryBaselineSchema, ArchBaselineSchema, CategoryRegressionSchema, ArchDiffResultSchema, ThresholdConfigSchema, ArchConfigSchema, ConstraintRuleSchema, ViolationSnapshotSchema, ViolationHistorySchema, EmergenceConfidenceSchema, EmergentConstraintSuggestionSchema, EmergenceResultSchema, accessAsync, readFileAsync, EXTENSION_BY_LANG, CircularDepsCollector, TypeScriptParser, EXTENSION_MAP, parserCache, initialized, GRAMMAR_MAP, TOP_LEVEL_TYPES, METHOD_TYPES, IDENTIFIER_TYPES, NAME_EXTRACTORS, pythonStrategy, goStrategy, RUST_USE_ARG_TYPES, RUST_PUB_ITEM_TYPES, rustStrategy, JAVA_IMPORT_TYPES, JAVA_EXPORT_TYPES, javaStrategy, STRATEGIES, TreeSitterParser, ParserRegistry, defaultRegistry, LayerViolationCollector, ArchBaselineManager, DEFAULT_THRESHOLDS, FUNCTION_PATTERNS, DECISION_PATTERNS, ComplexityCollector, DEFAULT_THRESHOLDS2, CouplingCollector, ForbiddenImportCollector, ModuleSizeCollector, DepDepthCollector, defaultCollectors, archMatchers;
1737
- var init_chunk_QLTIBLN5 = __esm({
1738
- "../core/dist/chunk-QLTIBLN5.mjs"() {
1737
+ var init_chunk_UWAI34RR = __esm({
1738
+ "../core/dist/chunk-UWAI34RR.mjs"() {
1739
1739
  "use strict";
1740
1740
  init_dist();
1741
1741
  ArchMetricCategorySchema = z.enum([
@@ -8820,6 +8820,27 @@ async function loadBudgetedLearnings(projectPath, options) {
8820
8820
  }
8821
8821
  return Ok(budgeted);
8822
8822
  }
8823
+ function buildEntryFromFrontmatter(line, fm) {
8824
+ const rootCauseMatch = line.match(/\[root_cause:([^\]]+)\]/);
8825
+ const triedMatch = line.match(/\[tried:([^\]]+)\]/);
8826
+ return {
8827
+ hash: fm.hash,
8828
+ tags: fm.tags,
8829
+ summary: line,
8830
+ fullText: "",
8831
+ ...rootCauseMatch?.[1] ? { rootCause: rootCauseMatch[1] } : {},
8832
+ ...triedMatch?.[1] ? { triedAndFailed: triedMatch[1].split(",").map((s) => s.trim()) } : {}
8833
+ };
8834
+ }
8835
+ function buildEntryFromLine(line) {
8836
+ const idx = extractIndexEntry(line);
8837
+ return {
8838
+ hash: idx.hash,
8839
+ tags: idx.tags,
8840
+ summary: line,
8841
+ fullText: ""
8842
+ };
8843
+ }
8823
8844
  async function loadIndexEntries(projectPath, skillName, stream, session) {
8824
8845
  try {
8825
8846
  const dirResult = await getStateDir(projectPath, stream, session);
@@ -8841,31 +8862,11 @@ async function loadIndexEntries(projectPath, skillName, stream, session) {
8841
8862
  pendingFrontmatter = fm;
8842
8863
  continue;
8843
8864
  }
8844
- const isDatedBullet = /^- \*\*\d{4}-\d{2}-\d{2}/.test(line);
8845
- const isHeading = /^## \d{4}-\d{2}-\d{2}/.test(line);
8846
- if (isDatedBullet || isHeading) {
8847
- if (pendingFrontmatter) {
8848
- const rootCauseMatch = line.match(/\[root_cause:([^\]]+)\]/);
8849
- const triedMatch = line.match(/\[tried:([^\]]+)\]/);
8850
- indexEntries.push({
8851
- hash: pendingFrontmatter.hash,
8852
- tags: pendingFrontmatter.tags,
8853
- summary: line,
8854
- fullText: "",
8855
- // Placeholder — full text not loaded in index mode
8856
- ...rootCauseMatch?.[1] ? { rootCause: rootCauseMatch[1] } : {},
8857
- ...triedMatch?.[1] ? { triedAndFailed: triedMatch[1].split(",").map((s) => s.trim()) } : {}
8858
- });
8859
- pendingFrontmatter = null;
8860
- } else {
8861
- const idx = extractIndexEntry(line);
8862
- indexEntries.push({
8863
- hash: idx.hash,
8864
- tags: idx.tags,
8865
- summary: line,
8866
- fullText: ""
8867
- });
8868
- }
8865
+ const isEntryStart = /^- \*\*\d{4}-\d{2}-\d{2}/.test(line) || /^## \d{4}-\d{2}-\d{2}/.test(line);
8866
+ if (isEntryStart) {
8867
+ const entry = pendingFrontmatter ? buildEntryFromFrontmatter(line, pendingFrontmatter) : buildEntryFromLine(line);
8868
+ indexEntries.push(entry);
8869
+ pendingFrontmatter = null;
8869
8870
  currentBlock = [line];
8870
8871
  } else if (line.trim() !== "" && currentBlock.length > 0) {
8871
8872
  currentBlock.push(line);
@@ -11622,50 +11623,48 @@ function buildMergedTitle(a, b, domains) {
11622
11623
  const cleanTitle = primaryFinding.title.replace(/^\[.*?\]\s*/, "");
11623
11624
  return { title: `[${domainList}] ${cleanTitle}`, primaryFinding };
11624
11625
  }
11626
+ function setIfDefined(target, key, value) {
11627
+ if (value !== void 0) target[key] = value;
11628
+ }
11625
11629
  function mergeSecurityFields(merged, primary, a, b) {
11626
- const cweId = primary.cweId ?? a.cweId ?? b.cweId;
11627
- const owaspCategory = primary.owaspCategory ?? a.owaspCategory ?? b.owaspCategory;
11628
- const confidence = primary.confidence ?? a.confidence ?? b.confidence;
11629
- const remediation = pickLongest(a.remediation, b.remediation);
11630
+ setIfDefined(merged, "cweId", primary.cweId ?? a.cweId ?? b.cweId);
11631
+ setIfDefined(
11632
+ merged,
11633
+ "owaspCategory",
11634
+ primary.owaspCategory ?? a.owaspCategory ?? b.owaspCategory
11635
+ );
11636
+ setIfDefined(merged, "confidence", primary.confidence ?? a.confidence ?? b.confidence);
11637
+ setIfDefined(merged, "remediation", pickLongest(a.remediation, b.remediation));
11630
11638
  const mergedRefs = [.../* @__PURE__ */ new Set([...a.references ?? [], ...b.references ?? []])];
11631
- if (cweId !== void 0) merged.cweId = cweId;
11632
- if (owaspCategory !== void 0) merged.owaspCategory = owaspCategory;
11633
- if (confidence !== void 0) merged.confidence = confidence;
11634
- if (remediation !== void 0) merged.remediation = remediation;
11635
11639
  if (mergedRefs.length > 0) merged.references = mergedRefs;
11636
11640
  }
11641
+ function pickHigherRank(aVal, bVal, rankMap) {
11642
+ return (rankMap[aVal] ?? 0) >= (rankMap[bVal] ?? 0) ? aVal : bVal;
11643
+ }
11644
+ function mergedLineRange(a, b) {
11645
+ return [Math.min(a[0], b[0]), Math.max(a[1], b[1])];
11646
+ }
11647
+ function mergeTrustScore(a, b) {
11648
+ const max = Math.max(a.trustScore ?? 0, b.trustScore ?? 0);
11649
+ return max > 0 ? max : void 0;
11650
+ }
11637
11651
  function mergeFindings(a, b) {
11638
- const highestSeverity = SEVERITY_RANK[a.severity] >= SEVERITY_RANK[b.severity] ? a.severity : b.severity;
11639
- const highestValidatedBy = (VALIDATED_BY_RANK[a.validatedBy] ?? 0) >= (VALIDATED_BY_RANK[b.validatedBy] ?? 0) ? a.validatedBy : b.validatedBy;
11640
- const longestRationale = a.rationale.length >= b.rationale.length ? a.rationale : b.rationale;
11641
- const evidenceSet = /* @__PURE__ */ new Set([...a.evidence, ...b.evidence]);
11642
- const lineRange = [
11643
- Math.min(a.lineRange[0], b.lineRange[0]),
11644
- Math.max(a.lineRange[1], b.lineRange[1])
11645
- ];
11646
11652
  const domains = /* @__PURE__ */ new Set([a.domain, b.domain]);
11647
- const suggestion = pickLongest(a.suggestion, b.suggestion);
11648
11653
  const { title, primaryFinding } = buildMergedTitle(a, b, domains);
11649
11654
  const merged = {
11650
11655
  id: primaryFinding.id,
11651
11656
  file: a.file,
11652
- lineRange,
11657
+ lineRange: mergedLineRange(a.lineRange, b.lineRange),
11653
11658
  domain: primaryFinding.domain,
11654
- severity: highestSeverity,
11659
+ severity: pickHigherRank(a.severity, b.severity, SEVERITY_RANK),
11655
11660
  title,
11656
- rationale: longestRationale,
11657
- evidence: [...evidenceSet],
11658
- validatedBy: highestValidatedBy
11661
+ rationale: a.rationale.length >= b.rationale.length ? a.rationale : b.rationale,
11662
+ evidence: [.../* @__PURE__ */ new Set([...a.evidence, ...b.evidence])],
11663
+ validatedBy: pickHigherRank(a.validatedBy, b.validatedBy, VALIDATED_BY_RANK)
11659
11664
  };
11660
- if (suggestion !== void 0) {
11661
- merged.suggestion = suggestion;
11662
- }
11665
+ setIfDefined(merged, "suggestion", pickLongest(a.suggestion, b.suggestion));
11666
+ setIfDefined(merged, "trustScore", mergeTrustScore(a, b));
11663
11667
  mergeSecurityFields(merged, primaryFinding, a, b);
11664
- const trustA = a.trustScore ?? 0;
11665
- const trustB = b.trustScore ?? 0;
11666
- if (trustA > 0 || trustB > 0) {
11667
- merged.trustScore = Math.max(trustA, trustB);
11668
- }
11669
11668
  return merged;
11670
11669
  }
11671
11670
  function deduplicateFindings(options) {
@@ -13862,40 +13861,52 @@ function getOrCreateInstallId(projectRoot) {
13862
13861
  fs36.writeFileSync(installIdFile, id, { encoding: "utf-8", mode: 384 });
13863
13862
  return id;
13864
13863
  }
13865
- function readIdentity(projectRoot) {
13864
+ function parseIdentityFromTelemetryFile(filePath) {
13866
13865
  const identity = {};
13867
- const filePath = path36.join(projectRoot, ".harness", "telemetry.json");
13868
13866
  try {
13869
13867
  const raw = fs37.readFileSync(filePath, "utf-8");
13870
13868
  const parsed = JSON.parse(raw);
13871
- if (parsed && typeof parsed === "object" && parsed.identity) {
13872
- const { project, team, alias } = parsed.identity;
13873
- if (typeof project === "string") identity.project = project;
13874
- if (typeof team === "string") identity.team = team;
13875
- if (typeof alias === "string") identity.alias = alias;
13876
- }
13869
+ const src = parsed?.identity;
13870
+ if (!src || typeof src !== "object") return identity;
13871
+ if (typeof src.project === "string") identity.project = src.project;
13872
+ if (typeof src.team === "string") identity.team = src.team;
13873
+ if (typeof src.alias === "string") identity.alias = src.alias;
13874
+ } catch {
13875
+ }
13876
+ return identity;
13877
+ }
13878
+ function readProjectNameFallback(configPath) {
13879
+ try {
13880
+ const raw = fs37.readFileSync(configPath, "utf-8");
13881
+ const config = JSON.parse(raw);
13882
+ return typeof config?.name === "string" ? config.name : void 0;
13883
+ } catch {
13884
+ return void 0;
13885
+ }
13886
+ }
13887
+ function readGitAliasFallback(cwd) {
13888
+ try {
13889
+ const gitName = execFileSync2("git", ["config", "user.name"], {
13890
+ cwd,
13891
+ encoding: "utf-8",
13892
+ timeout: 2e3,
13893
+ stdio: ["pipe", "pipe", "pipe"]
13894
+ }).trim();
13895
+ return gitName || void 0;
13877
13896
  } catch {
13897
+ return void 0;
13878
13898
  }
13899
+ }
13900
+ function readIdentity(projectRoot) {
13901
+ const filePath = path36.join(projectRoot, ".harness", "telemetry.json");
13902
+ const identity = parseIdentityFromTelemetryFile(filePath);
13879
13903
  if (!identity.project) {
13880
- try {
13881
- const configPath = path36.join(projectRoot, "harness.config.json");
13882
- const raw = fs37.readFileSync(configPath, "utf-8");
13883
- const config = JSON.parse(raw);
13884
- if (typeof config?.name === "string") identity.project = config.name;
13885
- } catch {
13886
- }
13904
+ const fallbackProject = readProjectNameFallback(path36.join(projectRoot, "harness.config.json"));
13905
+ if (fallbackProject) identity.project = fallbackProject;
13887
13906
  }
13888
13907
  if (!identity.alias) {
13889
- try {
13890
- const gitName = execFileSync2("git", ["config", "user.name"], {
13891
- cwd: projectRoot,
13892
- encoding: "utf-8",
13893
- timeout: 2e3,
13894
- stdio: ["pipe", "pipe", "pipe"]
13895
- }).trim();
13896
- if (gitName) identity.alias = gitName;
13897
- } catch {
13898
- }
13908
+ const fallbackAlias = readGitAliasFallback(projectRoot);
13909
+ if (fallbackAlias) identity.alias = fallbackAlias;
13899
13910
  }
13900
13911
  return identity;
13901
13912
  }
@@ -13963,7 +13974,7 @@ async function send(events, apiKey) {
13963
13974
  var VALID_TYPES, CONVENTIONAL_PATTERN, DEFAULT_AGNIX_TIMEOUT_MS, HARNESS_AGNIX_DISABLE, HARNESS_AGNIX_BIN, CLAUDE_MD_WARN_BYTES, CLAUDE_MD_ERROR_BYTES, CONTEXT_FILES, MIN_DESCRIPTION_LENGTH, SETTINGS_PATHS, KNOWN_HOOK_EVENTS, MCP_SETTINGS_FILES, REQUIRED_SECTIONS, SETTINGS_FILES, KNOWN_AGNIX_TOOLS, DEFAULT_SECTIONS, DEFAULT_RATIOS, NODE_TYPE_TO_CATEGORY, SECTION_LEVEL_MAP, DEFAULT_LEVEL, DEFAULT_BUDGET, DEFAULT_LOADER_CONFIG, LEVEL_FRACTIONS, PHASE_PRIORITIES, ManifestSchema, BundleConstraintsSchema, BundleSchema, ContributionsSchema, LockfilePackageSchema, LockfileSchema, SharableLayerSchema, SharableForbiddenImportSchema, SharableBoundaryConfigSchema, SharableSecurityRulesSchema, VALID_SCOPES, LINE_PATTERN, START_PATTERN, END_PATTERN, CODE_BLOCK_LANGUAGES, DEFAULT_DRIFT_CONFIG, FILE_TYPES, EXPORT_TYPES, CONVENTION_DESCRIPTIONS, RULE_CHECKERS, EntropyAnalyzer, readFile42, writeFile32, unlink22, mkdir22, copyFile2, DEFAULT_FIX_CONFIG, EXPORT_TYPE_KEYWORD, ALWAYS_UNSAFE_TYPES, idCounter, DEAD_CODE_FIX_ACTIONS, MustExportRuleSchema, MustExportDefaultRuleSchema, NoExportRuleSchema, MustImportRuleSchema, NoImportRuleSchema, NamingRuleSchema, MaxExportsRuleSchema, MaxLinesRuleSchema, RequireJSDocRuleSchema, RuleSchema, ConfigPatternSchema, PatternConfigSchema, DriftConfigSchema, DeadCodeConfigSchema, EntropyConfigSchema, BaselineManager, BenchmarkRunner, RegressionDetector, SKIP_DIRS, SOURCE_EXTENSIONS, FUNCTION_DECL_RE, CONST_DECL_RE, CriticalPathResolver, NoOpTelemetryAdapter, NoOpExecutor, ConsoleSink, feedbackConfig, ChecklistBuilder, AgentActionEmitter, globalEmitter, FileSink, NoOpSink, CategorySnapshotSchema, TimelineSnapshotSchema, TimelineFileSchema, TrendLineSchema, TrendResultSchema, DEFAULT_STABILITY_THRESHOLDS, ALL_CATEGORIES, TimelineManager, ConfidenceTierSchema, RegressionResultSchema, DirectionSchema, CategoryForecastSchema, SpecImpactSignalsSchema, SpecImpactEstimateSchema, ContributingFeatureSchema, AdjustedForecastSchema, PredictionWarningSchema, StabilityForecastSchema, PredictionResultSchema, PredictionOptionsSchema, VALID_STATUSES, EM_DASH, VALID_PRIORITIES, ALL_CATEGORIES2, DIRECTION_THRESHOLD, PredictionEngine, DEFAULT_COEFFICIENTS, SpecImpactEstimator, EMPTY_HISTORY, ViolationHistoryManager, NORMALIZERS, MAX_SAMPLES, DEFAULT_WINDOW_WEEKS, DEFAULT_MIN_OCCURRENCES, FailureEntrySchema, HandoffSchema, GateCheckSchema, GateResultSchema, GateConfigSchema, HarnessStateSchema, DEFAULT_STATE, StreamInfoSchema, StreamIndexSchema, DEFAULT_STREAM_INDEX, HARNESS_DIR, STATE_FILE, LEARNINGS_FILE, FAILURES_FILE, HANDOFF_FILE, GATE_CONFIG_FILE, INDEX_FILE, SESSIONS_DIR, SESSION_INDEX_FILE, SUMMARY_FILE, SESSION_STATE_FILE, ARCHIVE_DIR, CONTENT_HASHES_FILE, EVENTS_FILE, STREAMS_DIR, STREAM_NAME_REGEX, branchCache, BRANCH_CACHE_TTL_MS, STATE_FILES, MAX_CACHE_ENTRIES, learningsCacheMap, WEIGHTS, PROMOTABLE_OUTCOMES, failuresCacheMap, FAILURE_LINE_REGEX, SAFE_GATE_COMMAND, SkillEventSchema, knownHashesCache, EVENT_FORMATTERS, RuleRegistry, DEFAULT_SECURITY_CONFIG, RuleOverrideSchema, SecurityConfigSchema, secretRules, injectionRules, xssRules, cryptoRules, pathTraversalRules, networkRules, deserializationRules, agentConfigRules, mcpRules, insecureDefaultsRules, sharpEdgesRules, nodeRules, expressRules, reactRules, goRules, SecurityScanner, hiddenUnicodePatterns, reRolingPatterns, permissionEscalationPatterns, encodedPayloadPatterns, indirectInjectionPatterns, contextManipulationPatterns, socialEngineeringPatterns, suspiciousPatterns, ALL_PATTERNS, DESTRUCTIVE_BASH, TAINT_DURATION_MS, DEFAULT_SESSION_ID, SecurityCategorySnapshotSchema, SupplyChainSnapshotSchema, SecurityTimelineSnapshotSchema, FindingLifecycleSchema, SecurityTimelineFileSchema, DirectionSchema2, SecurityTrendLineSchema, TrendAttributionSchema, SecurityTrendResultSchema, TimeToFixStatsSchema, TimeToFixResultSchema, EMPTY_SUPPLY_CHAIN, SecurityTimelineManager, ALL_CHECKS, STATUS_ICONS, CINotifier, ExclusionSet, PREFIX_PATTERNS, TEST_FILE_PATTERN, MD_FILE_PATTERN, ALL_DOMAINS, SECURITY_PATTERNS, SEVERITY_RANK, SEVERITY_ORDER, SEVERITY_LABELS, VALIDATED_BY_RANK, VALIDATION_SCORES, DOMAIN_BASELINES, FACTOR_WEIGHTS, EVIDENCE_SATURATION, CORROBORATED_AGREEMENT, STANDALONE_AGREEMENT, AGREEMENT_LINE_GAP, COMPLIANCE_DESCRIPTOR, EXPORT_RE, BUG_DETECTION_DESCRIPTOR, SECURITY_DESCRIPTOR, EVAL_PATTERN, SECRET_PATTERNS, SQL_CONCAT_PATTERN, SHELL_EXEC_PATTERN, ARCHITECTURE_DESCRIPTOR, LARGE_FILE_THRESHOLD, VIOLATION_FILE_RE, LEARNINGS_DESCRIPTOR, RELEVANCE_THRESHOLD, AGENT_DESCRIPTORS, AGENT_RUNNERS, DOWNGRADE_MAP, DEFAULT_PROVIDER_TIERS, SMALL_SUGGESTION_LINE_LIMIT, FILE_LINE_RANGE_PATTERN, FILE_LINE_PATTERN, FILE_ONLY_PATTERN, SECURITY_SENSITIVE_PATH, MIGRATION_PATH, TEST_PATH, CONFIG_PATH, STAGE_DOMAINS, EM_DASH2, STATUS_RANK, RETRY_DEFAULTS, GitHubIssuesSyncAdapter, syncMutex, PRIORITY_RANK, POSITION_WEIGHT, DEPENDENTS_WEIGHT, AFFINITY_WEIGHT, InteractionTypeSchema, QuestionSchema, ConfirmationSchema, TransitionSchema, EmitInteractionInputSchema, ProjectScanner, SHELL_TEMPLATE, STYLES, SCRIPTS, MockLLMService, llmService, ContentPipeline, BlueprintGenerator, TOKENS_PER_MILLION, fallback_default, LITELLM_PRICING_URL, CACHE_TTL_MS, STALENESS_WARNING_DAYS, MICRODOLLARS_PER_DOLLAR, TOKENS_PER_MILLION2, StructuralStrategy, DEFAULT_TOKEN_BUDGET, CHARS_PER_TOKEN, TRUNCATION_MARKER, TruncationStrategy, CompactionPipeline, STABILITY_LOOKUP, TIER_ORDER, AnthropicCacheAdapter, TIER_ORDER2, OpenAICacheAdapter, TIER_ORDER3, CACHED_CONTENT_MARKER, GeminiCacheAdapter, VERSION, POSTHOG_BATCH_URL, MAX_ATTEMPTS, TIMEOUT_MS;
13964
13975
  var init_dist3 = __esm({
13965
13976
  "../core/dist/index.mjs"() {
13966
- init_chunk_QLTIBLN5();
13977
+ init_chunk_UWAI34RR();
13967
13978
  init_dist();
13968
13979
  init_dist();
13969
13980
  init_dist();
@@ -17559,7 +17570,7 @@ var init_dist3 = __esm({
17559
17570
  info: 0,
17560
17571
  total: 0
17561
17572
  };
17562
- SecurityTimelineManager = class {
17573
+ SecurityTimelineManager = class _SecurityTimelineManager {
17563
17574
  rootDir;
17564
17575
  timelinePath;
17565
17576
  constructor(rootDir) {
@@ -17831,6 +17842,11 @@ var init_dist3 = __esm({
17831
17842
  }
17832
17843
  }
17833
17844
  }
17845
+ static SEVERITY_COUNT_KEY = {
17846
+ error: "errorCount",
17847
+ warning: "warningCount",
17848
+ info: "infoCount"
17849
+ };
17834
17850
  aggregateByCategory(findings) {
17835
17851
  const result = {};
17836
17852
  for (const finding of findings) {
@@ -17844,9 +17860,8 @@ var init_dist3 = __esm({
17844
17860
  }
17845
17861
  const cat = result[finding.category];
17846
17862
  cat.findingCount++;
17847
- if (finding.severity === "error") cat.errorCount++;
17848
- else if (finding.severity === "warning") cat.warningCount++;
17849
- else cat.infoCount++;
17863
+ const key = _SecurityTimelineManager.SEVERITY_COUNT_KEY[finding.severity] ?? "infoCount";
17864
+ cat[key]++;
17850
17865
  }
17851
17866
  return result;
17852
17867
  }
@@ -17874,26 +17889,23 @@ var init_dist3 = __esm({
17874
17889
  return { current, previous, delta, direction };
17875
17890
  }
17876
17891
  computeAttribution(first, last) {
17877
- const attribution = [];
17878
17892
  const allCategories = /* @__PURE__ */ new Set([
17879
17893
  ...Object.keys(first.byCategory),
17880
17894
  ...Object.keys(last.byCategory)
17881
17895
  ]);
17896
+ const results = [];
17882
17897
  for (const category of allCategories) {
17883
- const prevCount = first.byCategory[category]?.findingCount ?? 0;
17884
- const currCount = last.byCategory[category]?.findingCount ?? 0;
17885
- const delta = currCount - prevCount;
17886
- if (delta === 0) continue;
17887
- const direction = delta < 0 ? "improving" : "declining";
17888
- const sign = delta > 0 ? "+" : "";
17889
- attribution.push({
17890
- category,
17891
- delta,
17892
- direction,
17893
- description: `${sign}${delta} ${category} findings`
17894
- });
17898
+ const attr = this.categoryAttribution(category, first.byCategory, last.byCategory);
17899
+ if (attr) results.push(attr);
17895
17900
  }
17896
- return attribution;
17901
+ return results;
17902
+ }
17903
+ categoryAttribution(category, prev, curr) {
17904
+ const delta = (curr[category]?.findingCount ?? 0) - (prev[category]?.findingCount ?? 0);
17905
+ if (delta === 0) return null;
17906
+ const direction = delta < 0 ? "improving" : "declining";
17907
+ const sign = delta > 0 ? "+" : "";
17908
+ return { category, delta, direction, description: `${sign}${delta} ${category} findings` };
17897
17909
  }
17898
17910
  computeStats(values) {
17899
17911
  if (values.length === 0) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  generateCIWorkflow
3
- } from "./chunk-WN6YIQ66.js";
4
- import "./chunk-KHMKAC6E.js";
3
+ } from "./chunk-KVJZQ2MV.js";
4
+ import "./chunk-ZIYLIYN4.js";
5
5
  import "./chunk-RL4VMEXL.js";
6
- import "./chunk-K2SON7TI.js";
6
+ import "./chunk-NKQEMWGT.js";
7
7
  import "./chunk-KFQGP6VL.js";
8
8
  export {
9
9
  generateCIWorkflow
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  Assembler,
3
+ BusinessKnowledgeIngestor,
3
4
  CIConnector,
4
5
  CURRENT_SCHEMA_VERSION,
5
6
  CascadeSimulator,
@@ -50,11 +51,12 @@ import {
50
51
  project,
51
52
  queryTraceability,
52
53
  saveGraph
53
- } from "./chunk-K2SON7TI.js";
54
+ } from "./chunk-NKQEMWGT.js";
54
55
  import "./chunk-KFQGP6VL.js";
55
56
  init_dist();
56
57
  export {
57
58
  Assembler,
59
+ BusinessKnowledgeIngestor,
58
60
  CIConnector,
59
61
  CURRENT_SCHEMA_VERSION,
60
62
  CascadeSimulator,
@@ -395,7 +395,7 @@ import {
395
395
  writeSessionSummary,
396
396
  writeTaint,
397
397
  xssRules
398
- } from "./chunk-KHMKAC6E.js";
398
+ } from "./chunk-ZIYLIYN4.js";
399
399
  import {
400
400
  DEFAULT_SKILL_CONTEXT_BUDGET,
401
401
  Err,
@@ -405,7 +405,7 @@ import {
405
405
  isErr,
406
406
  isOk
407
407
  } from "./chunk-RL4VMEXL.js";
408
- import "./chunk-K2SON7TI.js";
408
+ import "./chunk-NKQEMWGT.js";
409
409
  import "./chunk-KFQGP6VL.js";
410
410
  init_dist();
411
411
  export {
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  checkDocsDefinition,
3
3
  handleCheckDocs
4
- } from "./chunk-2OIPQMU5.js";
4
+ } from "./chunk-AS5DQT4S.js";
5
5
  import "./chunk-EPUKTTJZ.js";
6
6
  import "./chunk-W6Y7ZW3Y.js";
7
- import "./chunk-5R2LFUU3.js";
8
- import "./chunk-KHMKAC6E.js";
7
+ import "./chunk-TQRCODRJ.js";
8
+ import "./chunk-ZIYLIYN4.js";
9
9
  import "./chunk-RL4VMEXL.js";
10
- import "./chunk-K2SON7TI.js";
10
+ import "./chunk-NKQEMWGT.js";
11
11
  import "./chunk-3WGJMBKH.js";
12
12
  import "./chunk-KFQGP6VL.js";
13
13
  export {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  TemplateEngine
3
- } from "./chunk-KDHZAL4B.js";
4
- import "./chunk-KHMKAC6E.js";
3
+ } from "./chunk-K533WNZG.js";
4
+ import "./chunk-ZIYLIYN4.js";
5
5
  import "./chunk-RL4VMEXL.js";
6
- import "./chunk-K2SON7TI.js";
6
+ import "./chunk-NKQEMWGT.js";
7
7
  import "./chunk-KFQGP6VL.js";
8
8
  export {
9
9
  TemplateEngine
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  detectEntropyDefinition,
3
3
  handleDetectEntropy
4
- } from "./chunk-YFIALHGI.js";
4
+ } from "./chunk-D3XL2FLX.js";
5
5
  import "./chunk-EPUKTTJZ.js";
6
6
  import "./chunk-W6Y7ZW3Y.js";
7
- import "./chunk-KHMKAC6E.js";
7
+ import "./chunk-ZIYLIYN4.js";
8
8
  import "./chunk-RL4VMEXL.js";
9
- import "./chunk-K2SON7TI.js";
9
+ import "./chunk-NKQEMWGT.js";
10
10
  import "./chunk-KFQGP6VL.js";
11
11
  export {
12
12
  detectEntropyDefinition,
@@ -5,7 +5,7 @@ import {
5
5
  handleCreateSelfReview,
6
6
  handleRequestPeerReview,
7
7
  requestPeerReviewDefinition
8
- } from "./chunk-2TFT7XRX.js";
8
+ } from "./chunk-GVNT2YC7.js";
9
9
  import "./chunk-EPUKTTJZ.js";
10
10
  import "./chunk-W6Y7ZW3Y.js";
11
11
  import "./chunk-KFQGP6VL.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  createGenerateAgentDefinitionsCommand,
3
3
  generateAgentDefinitions
4
- } from "./chunk-2X336Q7J.js";
4
+ } from "./chunk-MCDCZMKN.js";
5
5
  import "./chunk-KET4QQZB.js";
6
- import "./chunk-KWQTMJ3B.js";
6
+ import "./chunk-FRDS4XGD.js";
7
7
  import "./chunk-3ISINLYT.js";
8
8
  import "./chunk-6B6UN6SG.js";
9
- import "./chunk-KHMKAC6E.js";
9
+ import "./chunk-ZIYLIYN4.js";
10
10
  import "./chunk-RL4VMEXL.js";
11
- import "./chunk-K2SON7TI.js";
11
+ import "./chunk-NKQEMWGT.js";
12
12
  import "./chunk-3WGJMBKH.js";
13
13
  import "./chunk-KFQGP6VL.js";
14
14
  export {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  clearGraphStoreCache,
3
3
  loadGraphStore
4
- } from "./chunk-BOQRTARD.js";
4
+ } from "./chunk-JPZY7ZQX.js";
5
5
  import "./chunk-KFQGP6VL.js";
6
6
  export {
7
7
  clearGraphStoreCache,
package/dist/index.d.ts CHANGED
@@ -732,15 +732,15 @@ declare const HarnessConfigSchema: z.ZodObject<{
732
732
  thresholds: z.ZodDefault<z.ZodRecord<z.ZodEnum<["circular-deps", "layer-violations", "complexity", "coupling", "forbidden-imports", "module-size", "dependency-depth"]>, z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>>;
733
733
  modules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodEnum<["circular-deps", "layer-violations", "complexity", "coupling", "forbidden-imports", "module-size", "dependency-depth"]>, z.ZodUnion<[z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodNumber>]>>>>;
734
734
  }, "strip", z.ZodTypeAny, {
735
- thresholds: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
736
- modules: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
737
735
  enabled: boolean;
738
736
  baselinePath: string;
737
+ thresholds: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
738
+ modules: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
739
739
  }, {
740
- thresholds?: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
741
- modules?: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
742
740
  enabled?: boolean | undefined;
743
741
  baselinePath?: string | undefined;
742
+ thresholds?: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
743
+ modules?: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
744
744
  }>>;
745
745
  /** Skill loading, suggestion, and tier override settings */
746
746
  skills: z.ZodOptional<z.ZodObject<{
@@ -964,10 +964,10 @@ declare const HarnessConfigSchema: z.ZodObject<{
964
964
  dismissed: string[];
965
965
  } | undefined;
966
966
  architecture?: {
967
- thresholds: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
968
- modules: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
969
967
  enabled: boolean;
970
968
  baselinePath: string;
969
+ thresholds: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>;
970
+ modules: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>>;
971
971
  } | undefined;
972
972
  traceability?: {
973
973
  enabled: boolean;
@@ -1108,10 +1108,10 @@ declare const HarnessConfigSchema: z.ZodObject<{
1108
1108
  dismissed?: string[] | undefined;
1109
1109
  } | undefined;
1110
1110
  architecture?: {
1111
- thresholds?: Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
1112
- modules?: Record<string, Partial<Record<"complexity" | "coupling" | "circular-deps" | "layer-violations" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
1113
1111
  enabled?: boolean | undefined;
1114
1112
  baselinePath?: string | undefined;
1113
+ thresholds?: Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>> | undefined;
1114
+ modules?: Record<string, Partial<Record<"circular-deps" | "layer-violations" | "complexity" | "coupling" | "forbidden-imports" | "module-size" | "dependency-depth", number | Record<string, number>>>> | undefined;
1115
1115
  } | undefined;
1116
1116
  traceability?: {
1117
1117
  enabled?: boolean | undefined;
@@ -1304,6 +1304,7 @@ interface DetectedFramework {
1304
1304
  interface WriteOptions {
1305
1305
  overwrite: boolean;
1306
1306
  language?: string;
1307
+ existingProject?: boolean;
1307
1308
  }
1308
1309
  interface WriteResult {
1309
1310
  written: string[];
@@ -1317,6 +1318,11 @@ declare class TemplateEngine {
1317
1318
  render(template: ResolvedTemplate, context: TemplateContext): Result<RenderedFiles, Error>;
1318
1319
  private renderFile;
1319
1320
  write(files: RenderedFiles, targetDir: string, options: WriteOptions): Result<WriteResult, Error>;
1321
+ /**
1322
+ * Check whether the target directory already contains a project by looking for
1323
+ * common build/package configuration files. Returns true if any marker is found.
1324
+ */
1325
+ isExistingProject(targetDir: string): boolean;
1320
1326
  detectFramework(targetDir: string): Result<DetectedFramework[], Error>;
1321
1327
  private resolveLanguageTemplate;
1322
1328
  private findTemplateDir;