persona-harness 0.3.0-alpha.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.
Files changed (176) hide show
  1. package/.persona/harness.jsonc +9 -0
  2. package/.persona/rules/backend/gradle-bootstrap.md +27 -0
  3. package/.persona/rules/backend/java-backend-bootstrap.md +28 -0
  4. package/.persona/rules/backend/java-common.md +22 -0
  5. package/.persona/rules/backend/layered-architecture.md +19 -0
  6. package/.persona/rules/backend/package-structure.md +21 -0
  7. package/.persona/rules/backend/spring-controller.md +19 -0
  8. package/.persona/rules/backend/spring-dto.md +21 -0
  9. package/.persona/rules/backend/spring-entity.md +22 -0
  10. package/.persona/rules/backend/spring-repository.md +22 -0
  11. package/.persona/rules/backend/spring-service.md +23 -0
  12. package/.persona/rules/backend/spring-test.md +32 -0
  13. package/.persona/rules/backend/step1-api-contract.md +29 -0
  14. package/.persona/rules/backend/step2-3-api-contract.md +24 -0
  15. package/.persona/rules/backend/validation-exception.md +18 -0
  16. package/.persona/rules/clean-code/abstraction.md +18 -0
  17. package/.persona/rules/clean-code/common.md +21 -0
  18. package/.persona/rules/clean-code/method-design.md +20 -0
  19. package/.persona/rules/clean-code/naming.md +19 -0
  20. package/.persona/rules/clean-code/oop.md +18 -0
  21. package/.persona/rules/clean-code/testability.md +19 -0
  22. package/CHANGELOG.md +40 -0
  23. package/LICENSE +201 -0
  24. package/README.ja.md +95 -0
  25. package/README.ko.md +95 -0
  26. package/README.md +125 -0
  27. package/README.zh-cn.md +95 -0
  28. package/dist/cli/bearshell.d.ts +12 -0
  29. package/dist/cli/bearshell.js +189 -0
  30. package/dist/cli/bearshell.js.map +1 -0
  31. package/dist/cli/history.d.ts +15 -0
  32. package/dist/cli/history.js +156 -0
  33. package/dist/cli/history.js.map +1 -0
  34. package/dist/cli/index.d.ts +10 -0
  35. package/dist/cli/index.js +117 -0
  36. package/dist/cli/index.js.map +1 -0
  37. package/dist/cli/init.d.ts +21 -0
  38. package/dist/cli/init.js +194 -0
  39. package/dist/cli/init.js.map +1 -0
  40. package/dist/cli/intake-profile.d.ts +52 -0
  41. package/dist/cli/intake-profile.js +167 -0
  42. package/dist/cli/intake-profile.js.map +1 -0
  43. package/dist/cli/intake.d.ts +14 -0
  44. package/dist/cli/intake.js +209 -0
  45. package/dist/cli/intake.js.map +1 -0
  46. package/dist/cli/plan-command.d.ts +4 -0
  47. package/dist/cli/plan-command.js +130 -0
  48. package/dist/cli/plan-command.js.map +1 -0
  49. package/dist/cli/plan-status.d.ts +11 -0
  50. package/dist/cli/plan-status.js +41 -0
  51. package/dist/cli/plan-status.js.map +1 -0
  52. package/dist/cli/plan.d.ts +10 -0
  53. package/dist/cli/plan.js +199 -0
  54. package/dist/cli/plan.js.map +1 -0
  55. package/dist/cli/policy.d.ts +7 -0
  56. package/dist/cli/policy.js +139 -0
  57. package/dist/cli/policy.js.map +1 -0
  58. package/dist/cli/report-status.d.ts +13 -0
  59. package/dist/cli/report-status.js +40 -0
  60. package/dist/cli/report-status.js.map +1 -0
  61. package/dist/index.d.ts +5 -0
  62. package/dist/index.js +9 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/phase0/drift-detector.d.ts +24 -0
  65. package/dist/phase0/drift-detector.js +334 -0
  66. package/dist/phase0/drift-detector.js.map +1 -0
  67. package/dist/phase0/evidence.d.ts +9 -0
  68. package/dist/phase0/evidence.js +36 -0
  69. package/dist/phase0/evidence.js.map +1 -0
  70. package/dist/phase0/file-role.d.ts +5 -0
  71. package/dist/phase0/file-role.js +55 -0
  72. package/dist/phase0/file-role.js.map +1 -0
  73. package/dist/phase0/harness-config.d.ts +12 -0
  74. package/dist/phase0/harness-config.js +115 -0
  75. package/dist/phase0/harness-config.js.map +1 -0
  76. package/dist/phase0/hooks.d.ts +8 -0
  77. package/dist/phase0/hooks.js +127 -0
  78. package/dist/phase0/hooks.js.map +1 -0
  79. package/dist/phase0/injection.d.ts +2 -0
  80. package/dist/phase0/injection.js +77 -0
  81. package/dist/phase0/injection.js.map +1 -0
  82. package/dist/phase0/java-role-discovery.d.ts +6 -0
  83. package/dist/phase0/java-role-discovery.js +90 -0
  84. package/dist/phase0/java-role-discovery.js.map +1 -0
  85. package/dist/phase0/messages.d.ts +2 -0
  86. package/dist/phase0/messages.js +30 -0
  87. package/dist/phase0/messages.js.map +1 -0
  88. package/dist/phase0/policy-overlay.d.ts +12 -0
  89. package/dist/phase0/policy-overlay.js +171 -0
  90. package/dist/phase0/policy-overlay.js.map +1 -0
  91. package/dist/phase0/project-profile.d.ts +1 -0
  92. package/dist/phase0/project-profile.js +148 -0
  93. package/dist/phase0/project-profile.js.map +1 -0
  94. package/dist/phase0/rule-catalog.d.ts +14 -0
  95. package/dist/phase0/rule-catalog.js +77 -0
  96. package/dist/phase0/rule-catalog.js.map +1 -0
  97. package/dist/phase0/rule-diagnostics-report.d.ts +17 -0
  98. package/dist/phase0/rule-diagnostics-report.js +51 -0
  99. package/dist/phase0/rule-diagnostics-report.js.map +1 -0
  100. package/dist/phase0/rule-frontmatter-diagnostics.d.ts +19 -0
  101. package/dist/phase0/rule-frontmatter-diagnostics.js +65 -0
  102. package/dist/phase0/rule-frontmatter-diagnostics.js.map +1 -0
  103. package/dist/phase0/rule-frontmatter.d.ts +23 -0
  104. package/dist/phase0/rule-frontmatter.js +172 -0
  105. package/dist/phase0/rule-frontmatter.js.map +1 -0
  106. package/dist/phase0/rule-glob.d.ts +2 -0
  107. package/dist/phase0/rule-glob.js +38 -0
  108. package/dist/phase0/rule-glob.js.map +1 -0
  109. package/dist/phase0/rule-loader.d.ts +13 -0
  110. package/dist/phase0/rule-loader.js +143 -0
  111. package/dist/phase0/rule-loader.js.map +1 -0
  112. package/dist/phase0/shared-skill-router.d.ts +14 -0
  113. package/dist/phase0/shared-skill-router.js +85 -0
  114. package/dist/phase0/shared-skill-router.js.map +1 -0
  115. package/dist/phase0/store.d.ts +6 -0
  116. package/dist/phase0/store.js +14 -0
  117. package/dist/phase0/store.js.map +1 -0
  118. package/dist/phase0/target-file.d.ts +2 -0
  119. package/dist/phase0/target-file.js +41 -0
  120. package/dist/phase0/target-file.js.map +1 -0
  121. package/dist/phase0/types.d.ts +38 -0
  122. package/dist/phase0/types.js +2 -0
  123. package/dist/phase0/types.js.map +1 -0
  124. package/dist/phase1/observer/controller-repository-observer.d.ts +17 -0
  125. package/dist/phase1/observer/controller-repository-observer.js +210 -0
  126. package/dist/phase1/observer/controller-repository-observer.js.map +1 -0
  127. package/dist/phase1/observer/controller-sql-observer.d.ts +20 -0
  128. package/dist/phase1/observer/controller-sql-observer.js +148 -0
  129. package/dist/phase1/observer/controller-sql-observer.js.map +1 -0
  130. package/dist/phase1/observer/java-source.d.ts +9 -0
  131. package/dist/phase1/observer/java-source.js +88 -0
  132. package/dist/phase1/observer/java-source.js.map +1 -0
  133. package/dist/phase1/observer/report.d.ts +52 -0
  134. package/dist/phase1/observer/report.js +173 -0
  135. package/dist/phase1/observer/report.js.map +1 -0
  136. package/dist/phase1/observer/service-storage-observer.d.ts +20 -0
  137. package/dist/phase1/observer/service-storage-observer.js +155 -0
  138. package/dist/phase1/observer/service-storage-observer.js.map +1 -0
  139. package/dist/phase1/observer/test-contract-anchor-matchers.d.ts +10 -0
  140. package/dist/phase1/observer/test-contract-anchor-matchers.js +198 -0
  141. package/dist/phase1/observer/test-contract-anchor-matchers.js.map +1 -0
  142. package/dist/phase1/observer/test-contract-observer.d.ts +21 -0
  143. package/dist/phase1/observer/test-contract-observer.js +70 -0
  144. package/dist/phase1/observer/test-contract-observer.js.map +1 -0
  145. package/docs/README.md +34 -0
  146. package/docs/current/README.md +35 -0
  147. package/docs/current/java-backend-mvp-install-guide.md +160 -0
  148. package/docs/current/persona-harness-detailed-usage.md +782 -0
  149. package/docs/current/release/README.md +6 -0
  150. package/docs/current/release/release-checklist.md +113 -0
  151. package/docs/current/release/release-notes-template.md +68 -0
  152. package/docs/current/v0.3.0-alpha-publish-readiness.md +185 -0
  153. package/docs/current/v0.3.0-external-tester-feedback-template.md +214 -0
  154. package/docs/current/v0.3.0-external-tester-guide.md +217 -0
  155. package/docs/current/v0.3.0-gradle-spring-build-guidance.md +100 -0
  156. package/package.json +87 -0
  157. package/packages/shared-skills/skills/programming/SKILL.md +490 -0
  158. package/packages/shared-skills/skills/programming/references/java/README.md +193 -0
  159. package/packages/shared-skills/skills/programming/references/java/anti-patterns.md +85 -0
  160. package/packages/shared-skills/skills/programming/references/java/application-layer.md +200 -0
  161. package/packages/shared-skills/skills/programming/references/java/architecture.md +152 -0
  162. package/packages/shared-skills/skills/programming/references/java/backend.md +152 -0
  163. package/packages/shared-skills/skills/programming/references/java/code-quality-refactoring.md +146 -0
  164. package/packages/shared-skills/skills/programming/references/java/concurrency-discipline.md +98 -0
  165. package/packages/shared-skills/skills/programming/references/java/domain-model.md +214 -0
  166. package/packages/shared-skills/skills/programming/references/java/error-handling.md +179 -0
  167. package/packages/shared-skills/skills/programming/references/java/foundations.md +49 -0
  168. package/packages/shared-skills/skills/programming/references/java/java-idioms.md +108 -0
  169. package/packages/shared-skills/skills/programming/references/java/language-core.md +96 -0
  170. package/packages/shared-skills/skills/programming/references/java/method-and-naming.md +164 -0
  171. package/packages/shared-skills/skills/programming/references/java/object-collaboration.md +140 -0
  172. package/packages/shared-skills/skills/programming/references/java/performance-discipline.md +115 -0
  173. package/packages/shared-skills/skills/programming/references/java/repository-pattern.md +181 -0
  174. package/packages/shared-skills/skills/programming/references/java/technology-seams.md +92 -0
  175. package/packages/shared-skills/skills/programming/references/java/test-design.md +149 -0
  176. package/packages/shared-skills/skills/programming/references/java/testing.md +188 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-status.js","sourceRoot":"","sources":["../../src/cli/report-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,OAAO,EAAE,0BAA0B,EAAE,kBAAkB,EAAoB,MAAM,WAAW,CAAA;AAW5F,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACzC,CAAC;CACF;AAED,SAAS,iBAAiB,CAAC,IAAwB;IACjD,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC9B,OAAO,0BAA0B,CAAA;IACnC,CAAC;IACD,OAAO,kBAAkB,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAyB;IAC/D,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,IAAwB,EACxB,MAA4B,EAC5B,UAAuB,EAAE;IAEzB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC/D,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IACjD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,yBAAyB,CAAC,MAAM,IAAI,mCAAmC,CAAC,CAAA;IACpF,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IACnD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,yBAAyB,CAAC,2BAA2B,YAAY,GAAG,CAAC,CAAA;IACjF,CAAC;IAED,aAAa,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,WAAW,MAAM,EAAE,CAAC,CAAC,CAAA;IACzF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,CAAA;AAC7C,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { PluginModule } from "@opencode-ai/plugin";
2
+ declare const pluginModule: PluginModule;
3
+ export default pluginModule;
4
+ export { createPhase0Hooks } from "./phase0/hooks.js";
5
+ export type { FileRole, PendingInjection, SelectedPolicyOverlay, SelectedSharedSkill } from "./phase0/types.js";
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { createPhase0Hooks } from "./phase0/hooks.js";
2
+ const serverPlugin = async (input) => createPhase0Hooks({ projectDir: input.directory });
3
+ const pluginModule = {
4
+ id: "persona-harness",
5
+ server: serverPlugin,
6
+ };
7
+ export default pluginModule;
8
+ export { createPhase0Hooks } from "./phase0/hooks.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,MAAM,YAAY,GAAW,KAAK,EAAE,KAAK,EAAkB,EAAE,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;AAEhH,MAAM,YAAY,GAAiB;IACjC,EAAE,EAAE,iBAAiB;IACrB,MAAM,EAAE,YAAY;CACrB,CAAA;AAED,eAAe,YAAY,CAAA;AAE3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,24 @@
1
+ export type DriftKind = "Service nextId" | "HTTP DELETE reset" | "Repository clear id reset missing" | "Spring bean missing" | "Response DTO storage usage" | "Controller repository access" | "API status drift" | "Test contract drift" | "Timeout" | "Unknown";
2
+ export type DriftSeverity = "fail" | "warn";
3
+ export type DriftFinding = {
4
+ kind: DriftKind;
5
+ severity: DriftSeverity;
6
+ file?: string;
7
+ evidence: string;
8
+ };
9
+ export type BackendDriftReport = {
10
+ inspectedFiles: string[];
11
+ findings: DriftFinding[];
12
+ falsePositiveRisk: string[];
13
+ hasFail: boolean;
14
+ hasWarning: boolean;
15
+ };
16
+ export type DetectBackendDriftInput = {
17
+ sandboxDir: string;
18
+ runOutput: string;
19
+ timedOut: boolean;
20
+ buildSuccessDetected: boolean;
21
+ testFailureDetected: boolean;
22
+ };
23
+ export declare function detectBackendDrift(input: DetectBackendDriftInput): BackendDriftReport;
24
+ export declare function formatDriftReport(report: BackendDriftReport): string;
@@ -0,0 +1,334 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ function listFiles(dir, predicate = (_path) => true) {
4
+ const result = [];
5
+ const visit = (current) => {
6
+ if (!existsSync(current))
7
+ return;
8
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
9
+ const fullPath = join(current, entry.name);
10
+ if (entry.isDirectory()) {
11
+ if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "target")
12
+ continue;
13
+ visit(fullPath);
14
+ }
15
+ else if (predicate(fullPath)) {
16
+ result.push(fullPath);
17
+ }
18
+ }
19
+ };
20
+ visit(dir);
21
+ return result.sort();
22
+ }
23
+ function readJavaFiles(sandboxDir) {
24
+ return listFiles(join(sandboxDir, "src"), (file) => file.endsWith(".java")).map((path) => {
25
+ const fileName = path.replace(/\\/g, "/").split("/").at(-1) ?? path;
26
+ return {
27
+ path,
28
+ relativePath: relative(sandboxDir, path),
29
+ content: readFileSync(path, "utf8"),
30
+ fileName,
31
+ className: fileName.replace(/\.java$/, ""),
32
+ };
33
+ });
34
+ }
35
+ function addFinding(findings, finding) {
36
+ if (findings.some((existing) => existing.kind === finding.kind &&
37
+ existing.file === finding.file &&
38
+ existing.evidence === finding.evidence)) {
39
+ return;
40
+ }
41
+ findings.push(finding);
42
+ }
43
+ function hasBeanAnnotation(content) {
44
+ return /@(Service|Repository|Component)\b/.test(content);
45
+ }
46
+ function hasBeanFactory(javaFiles, className) {
47
+ return javaFiles.some((file) => /@Bean\b/.test(file.content) && new RegExp(`\\b${className}\\b`).test(file.content));
48
+ }
49
+ function extractMethodBody(content, methodName) {
50
+ const methodIndex = content.search(new RegExp(`\\b${methodName}\\s*\\(`));
51
+ if (methodIndex < 0)
52
+ return undefined;
53
+ const openBraceIndex = content.indexOf("{", methodIndex);
54
+ if (openBraceIndex < 0)
55
+ return undefined;
56
+ let depth = 0;
57
+ for (let index = openBraceIndex; index < content.length; index += 1) {
58
+ const char = content[index];
59
+ if (char === "{")
60
+ depth += 1;
61
+ if (char === "}") {
62
+ depth -= 1;
63
+ if (depth === 0) {
64
+ return content.slice(openBraceIndex + 1, index);
65
+ }
66
+ }
67
+ }
68
+ return undefined;
69
+ }
70
+ function firstMatch(content, pattern) {
71
+ return content.match(pattern)?.[0];
72
+ }
73
+ function detectServiceNextId(javaFiles, findings) {
74
+ const serviceFiles = javaFiles.filter((file) => file.fileName.endsWith("Service.java"));
75
+ for (const file of serviceFiles) {
76
+ const match = firstMatch(file.content, /\b(AtomicLong|nextId|sequence|idCounter)\b/i);
77
+ if (match) {
78
+ addFinding(findings, {
79
+ kind: "Service nextId",
80
+ severity: "fail",
81
+ file: file.relativePath,
82
+ evidence: `Service contains id sequence state token: ${match}`,
83
+ });
84
+ }
85
+ }
86
+ }
87
+ function detectHttpDeleteReset(javaFiles, findings) {
88
+ const controllerAndTestFiles = javaFiles.filter((file) => file.fileName.endsWith("Controller.java") || file.fileName.endsWith("Test.java"));
89
+ for (const file of controllerAndTestFiles) {
90
+ if (/@DeleteMapping\s*(?:\(\s*\)|\(\s*"\/?"\s*\))/.test(file.content)) {
91
+ addFinding(findings, {
92
+ kind: "HTTP DELETE reset",
93
+ severity: "fail",
94
+ file: file.relativePath,
95
+ evidence: "DELETE mapping targets the collection rather than /{id}.",
96
+ });
97
+ }
98
+ if (/restTemplate\.delete\(\s*"\/reservations"\s*\)/.test(file.content)) {
99
+ addFinding(findings, {
100
+ kind: "HTTP DELETE reset",
101
+ severity: "fail",
102
+ file: file.relativePath,
103
+ evidence: 'Test reset uses restTemplate.delete("/reservations").',
104
+ });
105
+ }
106
+ if (/HttpMethod\.DELETE[\s\S]{0,240}"\/reservations"[\s\S]{0,240}(clear|reset)/i.test(file.content)) {
107
+ addFinding(findings, {
108
+ kind: "HTTP DELETE reset",
109
+ severity: "warn",
110
+ file: file.relativePath,
111
+ evidence: "DELETE /reservations appears near clear/reset behavior.",
112
+ });
113
+ }
114
+ }
115
+ }
116
+ function detectRepositoryClearReset(javaFiles, findings) {
117
+ const repositoryFiles = javaFiles.filter((file) => file.fileName.endsWith("Repository.java") || file.fileName.includes("Repository"));
118
+ for (const file of repositoryFiles) {
119
+ const hasIdState = /\b(AtomicLong|nextId|sequence|idCounter)\b/i.test(file.content);
120
+ if (!hasIdState)
121
+ continue;
122
+ const clearBody = extractMethodBody(file.content, "clear") ?? extractMethodBody(file.content, "reset");
123
+ if (!clearBody) {
124
+ addFinding(findings, {
125
+ kind: "Repository clear id reset missing",
126
+ severity: "fail",
127
+ file: file.relativePath,
128
+ evidence: "Repository has id sequence state but no clear/reset method.",
129
+ });
130
+ continue;
131
+ }
132
+ const resetsToFirstId = /(set\s*\(\s*1[L]?\s*\)|=\s*1[L]?\b)/.test(clearBody);
133
+ const resetsBeforeIncrement = /(set\s*\(\s*0[L]?\s*\)|=\s*0[L]?\b)/.test(clearBody) &&
134
+ /\bincrementAndGet\s*\(\s*\)/.test(file.content);
135
+ if (!resetsToFirstId && !resetsBeforeIncrement) {
136
+ addFinding(findings, {
137
+ kind: "Repository clear id reset missing",
138
+ severity: "fail",
139
+ file: file.relativePath,
140
+ evidence: "clear/reset method does not reset id sequence so the next created id is 1.",
141
+ });
142
+ }
143
+ }
144
+ }
145
+ function detectSpringBeanMissing(javaFiles, findings, runOutput) {
146
+ const serviceFiles = javaFiles.filter((file) => file.fileName.endsWith("Service.java"));
147
+ const repositoryImplementationFiles = javaFiles.filter((file) => file.fileName.includes("Repository") &&
148
+ !/\binterface\s+\w+Repository\b/.test(file.content) &&
149
+ /\bclass\s+\w+/.test(file.content));
150
+ for (const file of [...serviceFiles, ...repositoryImplementationFiles]) {
151
+ if (hasBeanAnnotation(file.content) || hasBeanFactory(javaFiles, file.className)) {
152
+ continue;
153
+ }
154
+ addFinding(findings, {
155
+ kind: "Spring bean missing",
156
+ severity: "fail",
157
+ file: file.relativePath,
158
+ evidence: `${file.className} has no @Service/@Repository/@Component annotation and no @Bean factory reference.`,
159
+ });
160
+ }
161
+ const missingBeanMatch = runOutput.match(/No qualifying bean of type '([^']+)' available/);
162
+ if (missingBeanMatch) {
163
+ addFinding(findings, {
164
+ kind: "Spring bean missing",
165
+ severity: "fail",
166
+ evidence: `Spring log reports missing bean: ${missingBeanMatch[1]}`,
167
+ });
168
+ }
169
+ }
170
+ function detectResponseDtoStorageUsage(javaFiles, findings) {
171
+ const responseDtoFiles = javaFiles.filter((file) => /(?:Response|ResponseDto)\.java$/.test(file.fileName));
172
+ for (const file of responseDtoFiles) {
173
+ const match = firstMatch(file.content, /\b(Map|List|ArrayList|HashMap|ConcurrentHashMap|AtomicLong|Repository|nextId|sequence|idCounter)\b/);
174
+ if (match) {
175
+ addFinding(findings, {
176
+ kind: "Response DTO storage usage",
177
+ severity: "fail",
178
+ file: file.relativePath,
179
+ evidence: `Response DTO contains storage/repository token: ${match}`,
180
+ });
181
+ }
182
+ }
183
+ const repositoryFiles = javaFiles.filter((file) => file.fileName.includes("Repository"));
184
+ for (const file of repositoryFiles) {
185
+ const match = firstMatch(file.content, /\b(?:private|protected|public)\s+(?:final\s+)?(?:Map|List|ArrayList|HashMap|ConcurrentHashMap)\s*<[^;]*Response(?:Dto)?[^;]*>\s+\w+\s*(?:=|;)/);
186
+ if (match) {
187
+ addFinding(findings, {
188
+ kind: "Response DTO storage usage",
189
+ severity: "warn",
190
+ file: file.relativePath,
191
+ evidence: `Repository stores response DTO type: ${match}`,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ function detectControllerRepositoryAccess(javaFiles, findings) {
197
+ const controllerFiles = javaFiles.filter((file) => file.fileName.endsWith("Controller.java"));
198
+ for (const file of controllerFiles) {
199
+ const repositoryMatch = firstMatch(file.content, /\b\w*Repository\b/);
200
+ const fieldMatch = firstMatch(file.content, /\b(?:private|protected|public)\s+(?:final\s+)?(?:Map|List|ArrayList|HashMap|ConcurrentHashMap|AtomicLong)(?:\s*<[^;]+>)?\s+\w+\s*(?:=|;)/);
201
+ const idStateMatch = firstMatch(file.content, /\b(nextId|sequence|idCounter)\b/i);
202
+ const match = repositoryMatch ?? fieldMatch ?? idStateMatch;
203
+ if (match) {
204
+ addFinding(findings, {
205
+ kind: "Controller repository access",
206
+ severity: "fail",
207
+ file: file.relativePath,
208
+ evidence: `Controller directly references repository/storage/id state: ${match}`,
209
+ });
210
+ }
211
+ }
212
+ }
213
+ function detectApiStatusDrift(javaFiles, findings) {
214
+ const targetFiles = javaFiles.filter((file) => file.fileName.endsWith("Controller.java") || file.fileName.endsWith("Test.java"));
215
+ for (const file of targetFiles) {
216
+ const createdMatch = firstMatch(file.content, /\b(HttpStatus\.CREATED|status\(\)\.isCreated\(\)|isCreated\(\)|created\s*\()/);
217
+ if (createdMatch) {
218
+ addFinding(findings, {
219
+ kind: "API status drift",
220
+ severity: "fail",
221
+ file: file.relativePath,
222
+ evidence: `POST may drift to 201 Created: ${createdMatch}`,
223
+ });
224
+ }
225
+ const noContentMatch = firstMatch(file.content, /\b(HttpStatus\.NO_CONTENT|status\(\)\.isNoContent\(\)|isNoContent\(\)|noContent\s*\()/);
226
+ if (noContentMatch) {
227
+ addFinding(findings, {
228
+ kind: "API status drift",
229
+ severity: "fail",
230
+ file: file.relativePath,
231
+ evidence: `DELETE may drift to 204 No Content: ${noContentMatch}`,
232
+ });
233
+ }
234
+ }
235
+ }
236
+ function detectTestContractDrift(javaFiles, findings) {
237
+ const testFiles = javaFiles.filter((file) => file.fileName.endsWith("Test.java"));
238
+ if (testFiles.length === 0) {
239
+ addFinding(findings, {
240
+ kind: "Test contract drift",
241
+ severity: "fail",
242
+ evidence: "No generated test file was found.",
243
+ });
244
+ return;
245
+ }
246
+ const testContent = testFiles.map((file) => file.content).join("\n");
247
+ const checksOk = /(HttpStatus\.OK|status\(\)\.isOk\(\)|status\(\)\.is\(200\)|getStatusCode\(\)\.value\(\)\s*[,)]\s*200|assertEquals\(\s*200\s*,)/.test(testContent);
248
+ const checksIdOne = /(jsonPath\([^;\n]*id[^;\n]*(?:is|value)\(\s*1\s*\)|jsonPath\([^)]*id[^)]*\)[\s\S]{0,120}(is\(\s*1\s*\)|value\(\s*1\s*\))|assertEquals\(\s*1\s*,[\s\S]{0,80}(id|getId\(\)))/.test(testContent);
249
+ const checksBodyFields = /\b(name|getName\(\)|jsonPath\([^)]*name)/.test(testContent) &&
250
+ /\b(date|getDate\(\)|jsonPath\([^)]*date)/.test(testContent) &&
251
+ /\b(time|getTime\(\)|jsonPath\([^)]*time)/.test(testContent);
252
+ const hasListSizeAssertion = (expectedSize) => new RegExp([
253
+ `hasSize\\(\\s*${expectedSize}\\s*\\)`,
254
+ `size\\(\\)\\s*[,)]\\s*${expectedSize}`,
255
+ `assertEquals\\(\\s*${expectedSize}\\s*,[\\s\\S]{0,80}size\\(\\)`,
256
+ `jsonPath\\([^;\\n]*(?:length\\(\\)|size\\(\\))[^;\\n]*value\\(\\s*${expectedSize}\\s*\\)`,
257
+ expectedSize === 0 ? `jsonPath\\([^;\\n]*\\$[^;\\n]*\\)\\.isEmpty\\(\\)` : "",
258
+ ].filter(Boolean).join("|")).test(testContent);
259
+ const checksListSizes = hasListSizeAssertion(0) && hasListSizeAssertion(1);
260
+ const missing = [
261
+ checksOk ? undefined : "200 OK status assertions",
262
+ checksIdOne ? undefined : "first id=1 assertion",
263
+ checksBodyFields ? undefined : "id/name/date/time body field assertions",
264
+ checksListSizes ? undefined : "list size 0/1 assertions",
265
+ ].filter((value) => Boolean(value));
266
+ if (missing.length > 0) {
267
+ addFinding(findings, {
268
+ kind: "Test contract drift",
269
+ severity: "fail",
270
+ evidence: `Generated tests miss contract checks: ${missing.join(", ")}.`,
271
+ });
272
+ }
273
+ }
274
+ export function detectBackendDrift(input) {
275
+ const javaFiles = readJavaFiles(input.sandboxDir);
276
+ const findings = [];
277
+ if (input.timedOut) {
278
+ addFinding(findings, {
279
+ kind: "Timeout",
280
+ severity: "fail",
281
+ evidence: "OpenCode execution timed out or was terminated.",
282
+ });
283
+ }
284
+ detectServiceNextId(javaFiles, findings);
285
+ detectHttpDeleteReset(javaFiles, findings);
286
+ detectRepositoryClearReset(javaFiles, findings);
287
+ detectSpringBeanMissing(javaFiles, findings, input.runOutput);
288
+ detectResponseDtoStorageUsage(javaFiles, findings);
289
+ detectControllerRepositoryAccess(javaFiles, findings);
290
+ detectApiStatusDrift(javaFiles, findings);
291
+ detectTestContractDrift(javaFiles, findings);
292
+ if (input.testFailureDetected && findings.length === 0) {
293
+ addFinding(findings, {
294
+ kind: "Unknown",
295
+ severity: "warn",
296
+ evidence: "Build/test failure was detected, but no minimal drift pattern matched.",
297
+ });
298
+ }
299
+ const hasFail = findings.some((finding) => finding.severity === "fail");
300
+ return {
301
+ inspectedFiles: javaFiles.map((file) => file.relativePath),
302
+ findings,
303
+ falsePositiveRisk: [
304
+ "This detector uses string patterns, not a Java AST.",
305
+ "Bean detection treats @Bean methods as evidence when the class name appears near @Bean.",
306
+ "Test contract detection checks representative assertions and may miss equivalent custom helpers.",
307
+ ],
308
+ hasFail,
309
+ hasWarning: findings.some((finding) => finding.severity === "warn"),
310
+ };
311
+ }
312
+ export function formatDriftReport(report) {
313
+ const findingLines = report.findings.length > 0
314
+ ? report.findings.map((finding) => {
315
+ const file = finding.file ? ` (${finding.file})` : "";
316
+ return `- [${finding.severity.toUpperCase()}] ${finding.kind}${file}: ${finding.evidence}`;
317
+ })
318
+ : ["- 없음"];
319
+ return `# Drift Report
320
+
321
+ ## Inspected Files
322
+
323
+ ${report.inspectedFiles.map((file) => `- ${file}`).join("\n") || "- none"}
324
+
325
+ ## Findings
326
+
327
+ ${findingLines.join("\n")}
328
+
329
+ ## False Positive Risk
330
+
331
+ ${report.falsePositiveRisk.map((risk) => `- ${risk}`).join("\n")}
332
+ `;
333
+ }
334
+ //# sourceMappingURL=drift-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-detector.js","sourceRoot":"","sources":["../../src/phase0/drift-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { PendingInjection } from "./types.js";
2
+ export type EvidenceEvent = {
3
+ hook: "tool.execute.before" | "tool.execute.after" | "experimental.chat.messages.transform";
4
+ sessionID: string;
5
+ callID?: string;
6
+ injectedInto: "pending-store" | "tool-output" | "model-input" | "role-discovery";
7
+ injection: PendingInjection;
8
+ };
9
+ export declare function writePhase0Evidence(projectDir: string, event: EvidenceEvent): void;
@@ -0,0 +1,36 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadHarnessConfig, resolveConfiguredPath } from "./harness-config.js";
4
+ function safeSlug(value) {
5
+ return value
6
+ .replace(/\\/g, "/")
7
+ .split("/")
8
+ .at(-1)
9
+ ?.replace(/[^a-zA-Z0-9._-]+/g, "-")
10
+ .toLowerCase() || "target";
11
+ }
12
+ export function writePhase0Evidence(projectDir, event) {
13
+ const now = new Date();
14
+ const config = loadHarnessConfig(projectDir);
15
+ const evidenceDir = join(resolveConfiguredPath(projectDir, config.evidenceDir), "phase0");
16
+ const runId = `${now.toISOString().replace(/[:.]/g, "-")}-${safeSlug(event.injection.targetFile)}`;
17
+ const payload = {
18
+ schemaVersion: "phase0.1",
19
+ runId,
20
+ timestamp: now.toISOString(),
21
+ hook: event.hook,
22
+ sessionID: event.sessionID,
23
+ callID: event.callID,
24
+ injectedInto: event.injectedInto,
25
+ targetFile: event.injection.targetFile,
26
+ fileRole: event.injection.fileRole,
27
+ selectedRules: event.injection.selectedRules,
28
+ selectedRuleMetadata: event.injection.selectedRuleMetadata,
29
+ selectedSharedSkills: event.injection.selectedSharedSkills,
30
+ selectedPolicyOverlay: event.injection.selectedPolicyOverlay,
31
+ injectedPolicyCount: event.injection.policies.length,
32
+ };
33
+ mkdirSync(evidenceDir, { recursive: true });
34
+ writeFileSync(join(evidenceDir, `${runId}.json`), `${JSON.stringify(payload, null, 2)}\n`);
35
+ }
36
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/phase0/evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAW9E,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,EAAE,CAAC,CAAC,CAAC,CAAC;QACP,EAAE,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;SAClC,WAAW,EAAE,IAAI,QAAQ,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,KAAoB;IAC1E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,MAAM,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAA;IACzF,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAA;IAClG,MAAM,OAAO,GAAG;QACd,aAAa,EAAE,UAAU;QACzB,KAAK;QACL,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU;QACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ;QAClC,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,aAAa;QAC5C,oBAAoB,EAAE,KAAK,CAAC,SAAS,CAAC,oBAAoB;QAC1D,oBAAoB,EAAE,KAAK,CAAC,SAAS,CAAC,oBAAoB;QAC1D,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAAC,qBAAqB;QAC5D,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM;KACrD,CAAA;IAED,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;AAC5F,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { FileRole } from "./types.js";
2
+ export declare function isJavaTargetFile(targetFile: string): boolean;
3
+ export declare function isBackendBootstrapTargetFile(targetFile: string): boolean;
4
+ export declare function resolveBootstrapFileRole(targetFile: string): FileRole;
5
+ export declare function resolveFileRole(targetFile: string): FileRole;
@@ -0,0 +1,55 @@
1
+ const JAVA_FILE_PATTERN = /\.java$/i;
2
+ const GRADLE_BUILD_FILE_PATTERN = /(^|\/)(build|settings)\.gradle(\.kts)?$/i;
3
+ export function isJavaTargetFile(targetFile) {
4
+ return JAVA_FILE_PATTERN.test(targetFile);
5
+ }
6
+ function normalizePath(targetFile) {
7
+ return targetFile.replace(/\\/g, "/");
8
+ }
9
+ function fileNameFor(targetFile) {
10
+ const normalized = normalizePath(targetFile);
11
+ return normalized.split("/").at(-1) ?? normalized;
12
+ }
13
+ export function isBackendBootstrapTargetFile(targetFile) {
14
+ const normalized = normalizePath(targetFile);
15
+ const fileName = fileNameFor(targetFile).toLowerCase();
16
+ if (normalized.includes("/docs/")) {
17
+ return false;
18
+ }
19
+ return fileName === "readme.md" || fileName === "requirements.md" || GRADLE_BUILD_FILE_PATTERN.test(normalized);
20
+ }
21
+ export function resolveBootstrapFileRole(targetFile) {
22
+ const normalized = normalizePath(targetFile);
23
+ const fileName = fileNameFor(targetFile).toLowerCase();
24
+ if (GRADLE_BUILD_FILE_PATTERN.test(normalized)) {
25
+ return "gradle-bootstrap";
26
+ }
27
+ if (fileName === "requirements.md") {
28
+ return "requirements-bootstrap";
29
+ }
30
+ return "project-bootstrap";
31
+ }
32
+ export function resolveFileRole(targetFile) {
33
+ const normalized = normalizePath(targetFile);
34
+ const fileName = fileNameFor(targetFile);
35
+ if (fileName.endsWith("Controller.java"))
36
+ return "controller";
37
+ if (fileName.endsWith("Service.java"))
38
+ return "service";
39
+ if (fileName.endsWith("Repository.java"))
40
+ return "repository";
41
+ if (fileName.endsWith("Entity.java"))
42
+ return "entity";
43
+ if (normalized.includes("/domain/"))
44
+ return "domain";
45
+ if (fileName.endsWith("Request.java"))
46
+ return "request-dto";
47
+ if (fileName.endsWith("Response.java"))
48
+ return "response-dto";
49
+ if (fileName.endsWith("Exception.java"))
50
+ return "exception";
51
+ if (fileName.endsWith("Test.java"))
52
+ return "test";
53
+ return "java-common";
54
+ }
55
+ //# sourceMappingURL=file-role.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-role.js","sourceRoot":"","sources":["../../src/phase0/file-role.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG,UAAU,CAAA;AACpC,MAAM,yBAAyB,GAAG,0CAA0C,CAAA;AAE5E,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,UAAkB;IACvC,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB;IACrC,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAC5C,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAA;AACnD,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,UAAkB;IAC7D,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;IACtD,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,iBAAiB,IAAI,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;AACjH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,UAAkB;IACzD,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;IACtD,IAAI,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,OAAO,kBAAkB,CAAA;IAC3B,CAAC;IACD,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;QACnC,OAAO,wBAAwB,CAAA;IACjC,CAAC;IACD,OAAO,mBAAmB,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAA;IAExC,IAAI,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,YAAY,CAAA;IAC7D,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAAE,OAAO,YAAY,CAAA;IAC7D,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,QAAQ,CAAA;IACrD,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,QAAQ,CAAA;IACpD,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,aAAa,CAAA;IAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC;QAAE,OAAO,cAAc,CAAA;IAC7D,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,WAAW,CAAA;IAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAA;IAEjD,OAAO,aAAa,CAAA;AACtB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Phase0Scenario } from "./rule-frontmatter.js";
2
+ export type HarnessConfig = {
3
+ readonly enabled: boolean;
4
+ readonly rulesDir: string;
5
+ readonly evidenceDir: string;
6
+ readonly maxRulesPerInjection: number;
7
+ readonly evidenceMode: "metadata_only";
8
+ readonly enabledDomains: readonly string[];
9
+ readonly scenario: Phase0Scenario;
10
+ };
11
+ export declare function resolveConfiguredPath(projectDir: string, configuredPath: string): string;
12
+ export declare function loadHarnessConfig(projectDir: string): HarnessConfig;