hunter-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/dist/bin.js +3356 -0
  4. package/package.json +34 -0
  5. package/resources/bootstrap-ir/manifest.json +19 -0
  6. package/resources/bootstrap-ir/skills/harness-apidoc.yaml +24 -0
  7. package/resources/bootstrap-ir/skills/harness-archive.yaml +24 -0
  8. package/resources/bootstrap-ir/skills/harness-codebase-map.yaml +24 -0
  9. package/resources/bootstrap-ir/skills/harness-knowledge-ingest.yaml +24 -0
  10. package/resources/bootstrap-ir/skills/harness-package.yaml +24 -0
  11. package/resources/bootstrap-ir/skills/harness-plan.yaml +24 -0
  12. package/resources/bootstrap-ir/skills/harness-review.yaml +24 -0
  13. package/resources/bootstrap-ir/skills/harness-run.yaml +24 -0
  14. package/resources/bootstrap-ir/skills/harness-skill-optimizer.yaml +28 -0
  15. package/resources/bootstrap-ir/skills/harness-submit.yaml +24 -0
  16. package/resources/bootstrap-ir/skills/harness-sync.yaml +24 -0
  17. package/resources/bootstrap-ir/skills/harness-test.yaml +24 -0
  18. package/resources/bootstrap-ir/templates/claude-code-skill.md +12 -0
  19. package/resources/harness/general/.harness-build.json +5 -0
  20. package/resources/harness/general/CONTEXT.md +65 -0
  21. package/resources/harness/general/README.md +478 -0
  22. package/resources/harness/general/agents/harness-evaluator.md +96 -0
  23. package/resources/harness/general/agents/harness-explorer.md +72 -0
  24. package/resources/harness/general/agents/harness-reviewer.md +69 -0
  25. package/resources/harness/general/harness-archive/SKILL.md +215 -0
  26. package/resources/harness/general/harness-archive/checklist.md +52 -0
  27. package/resources/harness/general/harness-archive/reference.md +103 -0
  28. package/resources/harness/general/harness-archive/scripts/gen-manifest.ps1 +31 -0
  29. package/resources/harness/general/harness-archive/templates/render-summary.mjs +171 -0
  30. package/resources/harness/general/harness-archive/templates/summary-data-template.json +128 -0
  31. package/resources/harness/general/harness-codebase-map/SKILL.md +112 -0
  32. package/resources/harness/general/harness-codebase-map/checklist.md +126 -0
  33. package/resources/harness/general/harness-codebase-map/reference.md +364 -0
  34. package/resources/harness/general/harness-codebase-map/templates/ARCHITECTURE.md +57 -0
  35. package/resources/harness/general/harness-codebase-map/templates/CONCERNS.md +49 -0
  36. package/resources/harness/general/harness-codebase-map/templates/CONVENTIONS.md +57 -0
  37. package/resources/harness/general/harness-codebase-map/templates/INTEGRATIONS.md +52 -0
  38. package/resources/harness/general/harness-codebase-map/templates/STACK.md +55 -0
  39. package/resources/harness/general/harness-codebase-map/templates/STRUCTURE.md +69 -0
  40. package/resources/harness/general/harness-codebase-map/templates/TESTING.md +64 -0
  41. package/resources/harness/general/harness-codebase-map/templates/map-manifest.schema.json +73 -0
  42. package/resources/harness/general/harness-codebase-map/templates/map-summary.md +64 -0
  43. package/resources/harness/general/harness-knowledge-ingest/SKILL.md +246 -0
  44. package/resources/harness/general/harness-knowledge-ingest/design.md +842 -0
  45. package/resources/harness/general/harness-knowledge-ingest/evaluations/harness_knowledge_evaluation.xml +42 -0
  46. package/resources/harness/general/harness-knowledge-ingest/mcp-config.example.json +10 -0
  47. package/resources/harness/general/harness-knowledge-ingest/reference.md +309 -0
  48. package/resources/harness/general/harness-knowledge-ingest/scripts/harness_knowledge.py +4082 -0
  49. package/resources/harness/general/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +273 -0
  50. package/resources/harness/general/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-01-10-ledger-reconciliation/reports/final/summary-data.json +43 -0
  51. package/resources/harness/general/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-02-14-ledger-snapshot-followup/reports/final/summary-data.json +38 -0
  52. package/resources/harness/general/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-03-05-webhook-contract/reports/final/summary-data.json +36 -0
  53. package/resources/harness/general/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/project.yaml +1 -0
  54. package/resources/harness/general/harness-knowledge-ingest/tests/test_harness_knowledge.py +1792 -0
  55. package/resources/harness/general/harness-knowledge-query/SKILL.md +164 -0
  56. package/resources/harness/general/harness-plan/SKILL.md +127 -0
  57. package/resources/harness/general/harness-plan/checklist.md +243 -0
  58. package/resources/harness/general/harness-plan/protocols.md +124 -0
  59. package/resources/harness/general/harness-plan/reference.md +376 -0
  60. package/resources/harness/general/harness-review/SKILL.md +156 -0
  61. package/resources/harness/general/harness-review/checklist.md +124 -0
  62. package/resources/harness/general/harness-review/protocols.md +68 -0
  63. package/resources/harness/general/harness-review/reference.md +86 -0
  64. package/resources/harness/general/harness-run/SKILL.md +132 -0
  65. package/resources/harness/general/harness-run/checklist.md +259 -0
  66. package/resources/harness/general/harness-run/protocols.md +78 -0
  67. package/resources/harness/general/harness-run/reference.md +834 -0
  68. package/resources/harness/general/harness-submit/SKILL.md +159 -0
  69. package/resources/harness/general/harness-submit/checklist.md +407 -0
  70. package/resources/harness/general/harness-submit/reference.md +152 -0
  71. package/resources/harness/general/harness-sync/SKILL.md +82 -0
  72. package/resources/harness/general/harness-sync/reference.md +153 -0
  73. package/resources/harness/general/harness-test/SKILL.md +180 -0
  74. package/resources/harness/general/harness-test/checklist.md +319 -0
  75. package/resources/harness/general/harness-test/pitfalls.md +260 -0
  76. package/resources/harness/general/harness-test/reference.md +791 -0
  77. package/resources/harness/general/protocols/archive-report-protocol.md +175 -0
  78. package/resources/harness/general/protocols/evidence-based-reporting-protocol.md +134 -0
  79. package/resources/harness/general/protocols/ledger-protocol.md +270 -0
  80. package/resources/harness/general/protocols/powershell-protocol.md +181 -0
  81. package/resources/harness/general/protocols/report-pipeline-protocol.md +150 -0
  82. package/resources/harness/general/protocols/sensitive-info-protocol.md +92 -0
  83. package/resources/harness/general/protocols/state-layout-protocol.md +131 -0
  84. package/resources/harness/general/protocols/submit-protocol.md +78 -0
  85. package/resources/harness/general/scripts/harness_archive.py +2319 -0
  86. package/resources/harness/general/scripts/harness_deploy.py +613 -0
  87. package/resources/harness/general/scripts/harness_events.py +680 -0
  88. package/resources/harness/general/scripts/harness_ledger.py +671 -0
  89. package/resources/harness/general/scripts/harness_preflight.py +780 -0
  90. package/resources/harness/general/scripts/harness_service.py +1331 -0
  91. package/resources/harness/java/.harness-build.json +5 -0
  92. package/resources/harness/java/CONTEXT.md +65 -0
  93. package/resources/harness/java/README.md +478 -0
  94. package/resources/harness/java/agents/harness-evaluator.md +96 -0
  95. package/resources/harness/java/agents/harness-explorer.md +72 -0
  96. package/resources/harness/java/agents/harness-reviewer.md +69 -0
  97. package/resources/harness/java/harness-apidoc/SKILL.md +86 -0
  98. package/resources/harness/java/harness-apidoc/checklist.md +142 -0
  99. package/resources/harness/java/harness-apidoc/reference.md +233 -0
  100. package/resources/harness/java/harness-archive/SKILL.md +215 -0
  101. package/resources/harness/java/harness-archive/checklist.md +52 -0
  102. package/resources/harness/java/harness-archive/reference.md +103 -0
  103. package/resources/harness/java/harness-archive/scripts/gen-manifest.ps1 +31 -0
  104. package/resources/harness/java/harness-archive/templates/render-summary.mjs +171 -0
  105. package/resources/harness/java/harness-archive/templates/summary-data-template.json +128 -0
  106. package/resources/harness/java/harness-codebase-map/SKILL.md +112 -0
  107. package/resources/harness/java/harness-codebase-map/checklist.md +126 -0
  108. package/resources/harness/java/harness-codebase-map/reference.md +364 -0
  109. package/resources/harness/java/harness-codebase-map/templates/ARCHITECTURE.md +57 -0
  110. package/resources/harness/java/harness-codebase-map/templates/CONCERNS.md +49 -0
  111. package/resources/harness/java/harness-codebase-map/templates/CONVENTIONS.md +57 -0
  112. package/resources/harness/java/harness-codebase-map/templates/INTEGRATIONS.md +52 -0
  113. package/resources/harness/java/harness-codebase-map/templates/STACK.md +55 -0
  114. package/resources/harness/java/harness-codebase-map/templates/STRUCTURE.md +69 -0
  115. package/resources/harness/java/harness-codebase-map/templates/TESTING.md +64 -0
  116. package/resources/harness/java/harness-codebase-map/templates/map-manifest.schema.json +73 -0
  117. package/resources/harness/java/harness-codebase-map/templates/map-summary.md +64 -0
  118. package/resources/harness/java/harness-knowledge-ingest/SKILL.md +246 -0
  119. package/resources/harness/java/harness-knowledge-ingest/design.md +842 -0
  120. package/resources/harness/java/harness-knowledge-ingest/evaluations/harness_knowledge_evaluation.xml +42 -0
  121. package/resources/harness/java/harness-knowledge-ingest/mcp-config.example.json +10 -0
  122. package/resources/harness/java/harness-knowledge-ingest/reference.md +309 -0
  123. package/resources/harness/java/harness-knowledge-ingest/scripts/harness_knowledge.py +4082 -0
  124. package/resources/harness/java/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +273 -0
  125. package/resources/harness/java/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-01-10-ledger-reconciliation/reports/final/summary-data.json +43 -0
  126. package/resources/harness/java/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-02-14-ledger-snapshot-followup/reports/final/summary-data.json +38 -0
  127. package/resources/harness/java/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/archive/2026-03-05-webhook-contract/reports/final/summary-data.json +36 -0
  128. package/resources/harness/java/harness-knowledge-ingest/tests/fixtures/mcp-eval-project/.harness/project.yaml +1 -0
  129. package/resources/harness/java/harness-knowledge-ingest/tests/test_harness_knowledge.py +1792 -0
  130. package/resources/harness/java/harness-knowledge-query/SKILL.md +164 -0
  131. package/resources/harness/java/harness-package/SKILL.md +87 -0
  132. package/resources/harness/java/harness-package/checklist.md +322 -0
  133. package/resources/harness/java/harness-package/reference.md +210 -0
  134. package/resources/harness/java/harness-plan/SKILL.md +127 -0
  135. package/resources/harness/java/harness-plan/checklist.md +243 -0
  136. package/resources/harness/java/harness-plan/protocols.md +124 -0
  137. package/resources/harness/java/harness-plan/reference.md +376 -0
  138. package/resources/harness/java/harness-review/SKILL.md +156 -0
  139. package/resources/harness/java/harness-review/checklist.md +124 -0
  140. package/resources/harness/java/harness-review/protocols.md +68 -0
  141. package/resources/harness/java/harness-review/reference.md +86 -0
  142. package/resources/harness/java/harness-run/SKILL.md +148 -0
  143. package/resources/harness/java/harness-run/checklist.md +250 -0
  144. package/resources/harness/java/harness-run/protocols.md +78 -0
  145. package/resources/harness/java/harness-run/reference.md +814 -0
  146. package/resources/harness/java/harness-submit/SKILL.md +166 -0
  147. package/resources/harness/java/harness-submit/checklist.md +407 -0
  148. package/resources/harness/java/harness-submit/reference.md +152 -0
  149. package/resources/harness/java/harness-sync/SKILL.md +82 -0
  150. package/resources/harness/java/harness-sync/reference.md +153 -0
  151. package/resources/harness/java/harness-test/SKILL.md +192 -0
  152. package/resources/harness/java/harness-test/checklist.md +317 -0
  153. package/resources/harness/java/harness-test/pitfalls-java.md +16 -0
  154. package/resources/harness/java/harness-test/pitfalls.md +260 -0
  155. package/resources/harness/java/harness-test/reference.md +788 -0
  156. package/resources/harness/java/protocols/archive-report-protocol.md +175 -0
  157. package/resources/harness/java/protocols/evidence-based-reporting-protocol.md +134 -0
  158. package/resources/harness/java/protocols/ledger-protocol.md +270 -0
  159. package/resources/harness/java/protocols/powershell-protocol.md +181 -0
  160. package/resources/harness/java/protocols/report-pipeline-protocol.md +150 -0
  161. package/resources/harness/java/protocols/sensitive-info-protocol.md +92 -0
  162. package/resources/harness/java/protocols/state-layout-protocol.md +131 -0
  163. package/resources/harness/java/protocols/submit-protocol.md +78 -0
  164. package/resources/harness/java/scripts/harness_archive.py +2319 -0
  165. package/resources/harness/java/scripts/harness_deploy.py +613 -0
  166. package/resources/harness/java/scripts/harness_events.py +680 -0
  167. package/resources/harness/java/scripts/harness_ledger.py +671 -0
  168. package/resources/harness/java/scripts/harness_preflight.py +780 -0
  169. package/resources/harness/java/scripts/harness_service.py +1331 -0
  170. package/resources/harness/manifests/general.json +296 -0
  171. package/resources/harness/manifests/java.json +324 -0
  172. package/resources/manifest.json +19 -0
  173. package/resources/skills/harness-apidoc/SKILL.md +50 -0
  174. package/resources/skills/harness-archive/SKILL.md +48 -0
  175. package/resources/skills/harness-codebase-map/SKILL.md +53 -0
  176. package/resources/skills/harness-knowledge-ingest/SKILL.md +48 -0
  177. package/resources/skills/harness-package/SKILL.md +48 -0
  178. package/resources/skills/harness-plan/SKILL.md +51 -0
  179. package/resources/skills/harness-review/SKILL.md +50 -0
  180. package/resources/skills/harness-run/SKILL.md +48 -0
  181. package/resources/skills/harness-skill-optimizer/SKILL.md +54 -0
  182. package/resources/skills/harness-submit/SKILL.md +47 -0
  183. package/resources/skills/harness-sync/SKILL.md +48 -0
  184. package/resources/skills/harness-test/SKILL.md +50 -0
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env python3
2
+ """MCP entry point for Harness knowledge operations."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+
13
+ SCRIPT_DIR = Path(__file__).resolve().parent
14
+ if str(SCRIPT_DIR) not in sys.path:
15
+ sys.path.insert(0, str(SCRIPT_DIR))
16
+
17
+ import harness_knowledge as hk # noqa: E402
18
+
19
+
20
+ TOOL_DESCRIPTIONS: list[dict[str, Any]] = [
21
+ {
22
+ "name": "harness_knowledge_ingest",
23
+ "description": "Build or refresh a project-local .harness/knowledge index from .harness/archive.",
24
+ "inputSchema": {
25
+ "type": "object",
26
+ "properties": {
27
+ "project": {"type": "string", "description": "Project root containing .harness/archive."},
28
+ "incremental": {"type": "boolean", "default": True, "description": "Reuse cached archive extraction results when valid."},
29
+ },
30
+ "required": ["project"],
31
+ },
32
+ },
33
+ {
34
+ "name": "harness_knowledge_sync",
35
+ "description": "Check whether .harness/knowledge is current, optionally refreshing stale indexes.",
36
+ "inputSchema": {
37
+ "type": "object",
38
+ "properties": {
39
+ "project": {"type": "string", "description": "Project root containing .harness/archive."},
40
+ "update": {"type": "boolean", "default": False, "description": "Refresh the index when it is out of date."},
41
+ "incremental": {"type": "boolean", "default": True, "description": "Use incremental extraction when update is true."},
42
+ },
43
+ "required": ["project"],
44
+ },
45
+ },
46
+ {
47
+ "name": "harness_knowledge_auto",
48
+ "description": "Run the default automated knowledge maintenance workflow: create config when missing, sync, suggest validators, verify, and audit.",
49
+ "inputSchema": {
50
+ "type": "object",
51
+ "properties": {
52
+ "project": {"type": "string", "description": "Project root containing .harness/archive."},
53
+ "limit": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100},
54
+ "suggest_statuses": {"type": "array", "items": {"type": "string"}, "default": []},
55
+ "apply_suggestions": {"type": "boolean", "default": False, "description": "Write validator suggestions into entry JSON files."},
56
+ "incremental": {"type": "boolean", "default": True, "description": "Reuse cached archive extraction results when refreshing."},
57
+ "audit_limit": {"type": "integer", "default": 10, "minimum": 1, "maximum": 100},
58
+ },
59
+ "required": ["project"],
60
+ },
61
+ },
62
+ {
63
+ "name": "harness_knowledge_audit",
64
+ "description": "Generate review lists for candidate, stale, superseded, and conflicted knowledge.",
65
+ "inputSchema": {
66
+ "type": "object",
67
+ "properties": {
68
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
69
+ "limit": {"type": "integer", "default": 10, "minimum": 1, "maximum": 100},
70
+ },
71
+ "required": ["project"],
72
+ },
73
+ },
74
+ {
75
+ "name": "harness_knowledge_verify",
76
+ "description": "Run configured validators against knowledge entries and refresh verification reports.",
77
+ "inputSchema": {
78
+ "type": "object",
79
+ "properties": {
80
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
81
+ },
82
+ "required": ["project"],
83
+ },
84
+ },
85
+ {
86
+ "name": "harness_knowledge_suggest_validators",
87
+ "description": "Suggest deterministic validators for knowledge entries, optionally applying them.",
88
+ "inputSchema": {
89
+ "type": "object",
90
+ "properties": {
91
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
92
+ "limit": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100},
93
+ "statuses": {"type": "array", "items": {"type": "string"}, "default": []},
94
+ "apply": {"type": "boolean", "default": False, "description": "Write suggestions into entry JSON files."},
95
+ },
96
+ "required": ["project"],
97
+ },
98
+ },
99
+ {
100
+ "name": "harness_knowledge_query",
101
+ "description": "Search .harness/knowledge and generate a context pack for planning or implementation.",
102
+ "inputSchema": {
103
+ "type": "object",
104
+ "properties": {
105
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
106
+ "query": {"type": "string", "description": "Need, question, keyword, or file path to search."},
107
+ "limit": {"type": "integer", "default": 10, "minimum": 1, "maximum": 100},
108
+ "files": {"type": "array", "items": {"type": "string"}, "default": []},
109
+ "statuses": {"type": "array", "items": {"type": "string"}, "default": []},
110
+ "types": {"type": "array", "items": {"type": "string"}, "default": []},
111
+ },
112
+ "required": ["project", "query"],
113
+ },
114
+ },
115
+ {
116
+ "name": "harness_knowledge_promote",
117
+ "description": "Promote a candidate knowledge entry to active after manual confirmation.",
118
+ "inputSchema": {
119
+ "type": "object",
120
+ "properties": {
121
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
122
+ "entry_id": {"type": "string", "description": "Knowledge entry id to promote."},
123
+ "note": {"type": "string", "default": "", "description": "Manual verification note."},
124
+ "allow_stale": {"type": "boolean", "default": False, "description": "Allow promoting a stale entry after manual verification."},
125
+ },
126
+ "required": ["project", "entry_id"],
127
+ },
128
+ },
129
+ {
130
+ "name": "harness_knowledge_demote",
131
+ "description": "Demote an active knowledge entry to stale or candidate after manual review.",
132
+ "inputSchema": {
133
+ "type": "object",
134
+ "properties": {
135
+ "project": {"type": "string", "description": "Project root containing .harness/knowledge."},
136
+ "entry_id": {"type": "string", "description": "Active knowledge entry id to demote."},
137
+ "status": {"type": "string", "enum": ["candidate", "stale"], "description": "Target lifecycle status."},
138
+ "reason": {"type": "string", "description": "Manual demotion reason."},
139
+ },
140
+ "required": ["project", "entry_id", "status", "reason"],
141
+ },
142
+ },
143
+ ]
144
+
145
+
146
+ def describe_tools() -> dict[str, Any]:
147
+ return {
148
+ "server": "harness-knowledge",
149
+ "transport": "stdio",
150
+ "tools": TOOL_DESCRIPTIONS,
151
+ }
152
+
153
+
154
+ def create_server() -> Any:
155
+ try:
156
+ from mcp.server.fastmcp import FastMCP
157
+ except Exception as exc: # pragma: no cover - exercised when SDK is absent
158
+ raise RuntimeError(
159
+ "Python package 'mcp' with FastMCP support is required to run the MCP server. "
160
+ "Use --describe-tools for static tool metadata."
161
+ ) from exc
162
+
163
+ server = FastMCP(
164
+ "harness-knowledge",
165
+ instructions=(
166
+ "Use these tools to maintain and query project-local Harness knowledge. "
167
+ "Treat candidate and stale entries as historical context until verified."
168
+ ),
169
+ )
170
+
171
+ @server.tool(description=TOOL_DESCRIPTIONS[0]["description"])
172
+ def harness_knowledge_ingest(project: str, incremental: bool = True) -> dict[str, Any]:
173
+ return hk.summarize_index(hk.build_index(Path(project), incremental=incremental))
174
+
175
+ @server.tool(description=TOOL_DESCRIPTIONS[1]["description"])
176
+ def harness_knowledge_sync(project: str, update: bool = False, incremental: bool = True) -> dict[str, Any]:
177
+ return hk.sync_status(Path(project), update=update, incremental=incremental)
178
+
179
+ @server.tool(description=TOOL_DESCRIPTIONS[2]["description"])
180
+ def harness_knowledge_auto(
181
+ project: str,
182
+ limit: int = 20,
183
+ suggest_statuses: list[str] | None = None,
184
+ apply_suggestions: bool = False,
185
+ incremental: bool = True,
186
+ audit_limit: int = 10,
187
+ ) -> dict[str, Any]:
188
+ return hk.auto_knowledge(
189
+ Path(project),
190
+ limit=limit,
191
+ suggest_statuses=suggest_statuses or [],
192
+ apply_suggestions=apply_suggestions,
193
+ incremental=incremental,
194
+ audit_limit=audit_limit,
195
+ )
196
+
197
+ @server.tool(description=TOOL_DESCRIPTIONS[3]["description"])
198
+ def harness_knowledge_audit(project: str, limit: int = 10) -> dict[str, Any]:
199
+ return hk.audit_entries(Path(project), limit=limit)
200
+
201
+ @server.tool(description=TOOL_DESCRIPTIONS[4]["description"])
202
+ def harness_knowledge_verify(project: str) -> dict[str, Any]:
203
+ return hk.verify_knowledge(Path(project))
204
+
205
+ @server.tool(description=TOOL_DESCRIPTIONS[5]["description"])
206
+ def harness_knowledge_suggest_validators(
207
+ project: str,
208
+ limit: int = 20,
209
+ statuses: list[str] | None = None,
210
+ apply: bool = False,
211
+ ) -> dict[str, Any]:
212
+ return hk.suggest_validators(Path(project), limit=limit, statuses=statuses or [], apply=apply)
213
+
214
+ @server.tool(description=TOOL_DESCRIPTIONS[6]["description"])
215
+ def harness_knowledge_query(
216
+ project: str,
217
+ query: str,
218
+ limit: int = 10,
219
+ files: list[str] | None = None,
220
+ statuses: list[str] | None = None,
221
+ types: list[str] | None = None,
222
+ ) -> dict[str, Any]:
223
+ return hk.query_index(
224
+ Path(project),
225
+ query,
226
+ limit=limit,
227
+ file_filters=files or [],
228
+ statuses=statuses or [],
229
+ types=types or [],
230
+ )
231
+
232
+ @server.tool(description=TOOL_DESCRIPTIONS[7]["description"])
233
+ def harness_knowledge_promote(
234
+ project: str,
235
+ entry_id: str,
236
+ note: str = "",
237
+ allow_stale: bool = False,
238
+ ) -> dict[str, Any]:
239
+ return hk.promote_entry(Path(project), entry_id, note, allow_stale=allow_stale)
240
+
241
+ @server.tool(description=TOOL_DESCRIPTIONS[8]["description"])
242
+ def harness_knowledge_demote(
243
+ project: str,
244
+ entry_id: str,
245
+ status: str,
246
+ reason: str,
247
+ ) -> dict[str, Any]:
248
+ return hk.demote_entry(Path(project), entry_id, status, reason)
249
+
250
+ return server
251
+
252
+
253
+ def main(argv: list[str] | None = None) -> int:
254
+ parser = argparse.ArgumentParser(description="Run the Harness knowledge MCP server.")
255
+ parser.add_argument("--describe-tools", action="store_true", help="Print static MCP tool metadata as JSON and exit.")
256
+ parser.add_argument("--transport", choices=["stdio", "sse", "streamable-http"], default="stdio")
257
+ args = parser.parse_args(argv)
258
+
259
+ if args.describe_tools:
260
+ print(json.dumps(describe_tools(), ensure_ascii=False, indent=2))
261
+ return 0
262
+
263
+ try:
264
+ server = create_server()
265
+ except RuntimeError as exc:
266
+ print(str(exc), file=sys.stderr)
267
+ return 1
268
+ server.run(transport=args.transport)
269
+ return 0
270
+
271
+
272
+ if __name__ == "__main__":
273
+ raise SystemExit(main())
@@ -0,0 +1,43 @@
1
+ {
2
+ "schemaVersion": "2.1",
3
+ "changeName": "ledger-reconciliation",
4
+ "businessGoal": "Create LedgerReconciler as the single source of truth for billing reconciliation and monthly close variance checks.",
5
+ "finalStatus": "OK",
6
+ "finalCommit": "1111111111111111111111111111111111111111",
7
+ "baseCommit": "0000000000000000000000000000000000000000",
8
+ "changedFiles": [
9
+ {
10
+ "path": "src/billing/ledger_reconciler.py",
11
+ "summary": "Introduced LedgerReconciler for billing reconciliation matching."
12
+ },
13
+ {
14
+ "path": "tests/test_ledger_reconciler.py",
15
+ "summary": "Added unit tests for LedgerReconciler variance handling."
16
+ }
17
+ ],
18
+ "verification": {
19
+ "unitTests": {
20
+ "run": 8,
21
+ "failures": 0,
22
+ "errors": 0,
23
+ "passRate": "8/8"
24
+ },
25
+ "apiTests": {
26
+ "status": "OK",
27
+ "total": 2,
28
+ "passed": 2,
29
+ "failed": 0,
30
+ "passRate": "2/2"
31
+ }
32
+ },
33
+ "maintenanceNotes": [
34
+ "LedgerReconciler is the only source of truth for billing reconciliation totals.",
35
+ "Billing reconciliation jobs must read tenant timezone before grouping ledger rows."
36
+ ],
37
+ "knownRisks": [
38
+ "CSV imports missing account IDs must be quarantined before reconciliation."
39
+ ],
40
+ "manualActions": [
41
+ "Run migration 2026-01-ledger-baseline before release."
42
+ ]
43
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "schemaVersion": "2.1",
3
+ "changeName": "ledger-snapshot-followup",
4
+ "businessGoal": "Move final reconciliation output to SettlementSnapshot and replace the old LedgerReconciler source-of-truth assumption.",
5
+ "finalStatus": "OK",
6
+ "finalCommit": "2222222222222222222222222222222222222222",
7
+ "baseCommit": "1111111111111111111111111111111111111111",
8
+ "changedFiles": [
9
+ {
10
+ "path": "src/billing/ledger_reconciler.py",
11
+ "summary": "Kept LedgerReconciler as an internal calculator."
12
+ },
13
+ {
14
+ "path": "src/billing/settlement_snapshot.py",
15
+ "summary": "Introduced SettlementSnapshot as the final published reconciliation output."
16
+ },
17
+ {
18
+ "path": "tests/test_settlement_snapshot.py",
19
+ "summary": "Added snapshot publication tests."
20
+ }
21
+ ],
22
+ "verification": {
23
+ "unitTests": {
24
+ "run": 11,
25
+ "failures": 0,
26
+ "errors": 0,
27
+ "passRate": "11/11"
28
+ }
29
+ },
30
+ "maintenanceNotes": [
31
+ "SettlementSnapshot now replaces LedgerReconciler as final published reconciliation output.",
32
+ "LedgerReconciler remains an internal calculator for settlement snapshot generation."
33
+ ],
34
+ "knownRisks": [
35
+ "Historical reports generated before February 2026 may still reference LedgerReconciler labels."
36
+ ],
37
+ "manualActions": []
38
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "schemaVersion": "2.1",
3
+ "changeName": "webhook-contract",
4
+ "businessGoal": "Add signed webhook delivery contract for partner payout notifications.",
5
+ "finalStatus": "OK",
6
+ "finalCommit": "3333333333333333333333333333333333333333",
7
+ "baseCommit": "2222222222222222222222222222222222222222",
8
+ "changedFiles": [
9
+ {
10
+ "path": "src/api/webhooks.py",
11
+ "summary": "Added partner payout webhook delivery endpoint."
12
+ },
13
+ {
14
+ "path": "src/contracts/webhook_schema.py",
15
+ "summary": "Defined webhook payload and signature contract."
16
+ }
17
+ ],
18
+ "verification": {
19
+ "unitTests": {
20
+ "run": 5,
21
+ "failures": 0,
22
+ "errors": 0,
23
+ "passRate": "5/5"
24
+ }
25
+ },
26
+ "maintenanceNotes": [
27
+ "Webhook signature header is X-Harness-Signature.",
28
+ "Webhook retry backoff is capped at 30 minutes for partner payout notifications."
29
+ ],
30
+ "knownRisks": [
31
+ "Partner sandbox clock skew may break signature timestamp validation."
32
+ ],
33
+ "manualActions": [
34
+ "Share the webhook schema with partner integrators before enabling production delivery."
35
+ ]
36
+ }