pi-harness-runtime 1.1.150 → 1.1.152

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 (158) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/harness/key-loader.ts +84 -0
  3. package/harness/langchain/agents.ts +65 -15
  4. package/harness/langchain/daemon.ts +58 -30
  5. package/harness/langchain/graph.ts +55 -7
  6. package/harness/langchain/jev-logger.ts +274 -0
  7. package/harness/langchain/run.ts +64 -161
  8. package/harness/langchain/surge.test.ts +42 -0
  9. package/harness/langchain/surge.ts +22 -1
  10. package/index.ts +24 -0
  11. package/package.json +1 -1
  12. package/packages/a2a-adapter/package.json +1 -1
  13. package/packages/agent-policy/dist/extension.d.ts +19 -0
  14. package/packages/agent-policy/dist/extension.d.ts.map +1 -0
  15. package/packages/agent-policy/dist/extension.js +322 -0
  16. package/packages/agent-policy/dist/extension.js.map +1 -0
  17. package/packages/agent-policy/dist/index.d.ts +25 -0
  18. package/packages/agent-policy/dist/index.d.ts.map +1 -0
  19. package/packages/agent-policy/dist/index.js +27 -0
  20. package/packages/agent-policy/dist/index.js.map +1 -0
  21. package/packages/agent-policy/dist/policy-loader.d.ts +90 -0
  22. package/packages/agent-policy/dist/policy-loader.d.ts.map +1 -0
  23. package/packages/agent-policy/dist/policy-loader.js +331 -0
  24. package/packages/agent-policy/dist/policy-loader.js.map +1 -0
  25. package/packages/agent-policy/dist/policy-renderer.d.ts +42 -0
  26. package/packages/agent-policy/dist/policy-renderer.d.ts.map +1 -0
  27. package/packages/agent-policy/dist/policy-renderer.js +295 -0
  28. package/packages/agent-policy/dist/policy-renderer.js.map +1 -0
  29. package/packages/agent-policy/dist/policy-store.d.ts +99 -0
  30. package/packages/agent-policy/dist/policy-store.d.ts.map +1 -0
  31. package/packages/agent-policy/dist/policy-store.js +244 -0
  32. package/packages/agent-policy/dist/policy-store.js.map +1 -0
  33. package/packages/agent-policy/dist/types.d.ts +237 -0
  34. package/packages/agent-policy/dist/types.d.ts.map +1 -0
  35. package/packages/agent-policy/dist/types.js +130 -0
  36. package/packages/agent-policy/dist/types.js.map +1 -0
  37. package/packages/agent-policy/package.json +45 -0
  38. package/packages/agent-policy/src/extension.ts +413 -0
  39. package/packages/agent-policy/src/index.ts +52 -0
  40. package/packages/agent-policy/src/policy-loader.ts +398 -0
  41. package/packages/agent-policy/src/policy-renderer.ts +362 -0
  42. package/packages/agent-policy/src/policy-store.ts +319 -0
  43. package/packages/agent-policy/src/types.ts +385 -0
  44. package/packages/agent-policy/test/policy.test.ts +383 -0
  45. package/packages/architecture-generator/package.json +1 -1
  46. package/packages/auth/package.json +1 -1
  47. package/packages/autonomous-refactor/package.json +1 -1
  48. package/packages/autonomous-runtime/package.json +1 -1
  49. package/packages/cache-strategy/package.json +1 -1
  50. package/packages/capability-registry/package.json +1 -1
  51. package/packages/checkpoint/package.json +1 -1
  52. package/packages/cli-plugin-sdk/package.json +1 -1
  53. package/packages/clipboard/package.json +1 -1
  54. package/packages/clipboard-plugin/package.json +1 -1
  55. package/packages/code-generation/package.json +1 -1
  56. package/packages/code-review/package.json +1 -1
  57. package/packages/codex-adapter/package.json +1 -1
  58. package/packages/codex-watcher/dist/src/parser.d.ts.map +1 -1
  59. package/packages/codex-watcher/dist/src/parser.js +35 -0
  60. package/packages/codex-watcher/dist/src/parser.js.map +1 -1
  61. package/packages/codex-watcher/package.json +1 -1
  62. package/packages/codex-watcher/src/parser.ts +41 -0
  63. package/packages/config-capture/package.json +1 -1
  64. package/packages/context-compiler/package.json +1 -1
  65. package/packages/context-discovery/package.json +1 -1
  66. package/packages/context-manager/package.json +1 -1
  67. package/packages/cookie-sanitizer/package.json +1 -1
  68. package/packages/cost-optimizer/package.json +1 -1
  69. package/packages/dependency-analyzer/package.json +1 -1
  70. package/packages/django-plugin/package.json +1 -1
  71. package/packages/doc-generator/package.json +1 -1
  72. package/packages/evaluation-engine/package.json +1 -1
  73. package/packages/evaluation-runner/package.json +1 -1
  74. package/packages/event-bus/package.json +1 -1
  75. package/packages/event-store/package.json +1 -1
  76. package/packages/experience-replay/package.json +1 -1
  77. package/packages/feedback-collector/package.json +1 -1
  78. package/packages/file-copy-helper/package.json +1 -1
  79. package/packages/framework-detector/package.json +1 -1
  80. package/packages/framework-plugin-sdk/package.json +1 -1
  81. package/packages/frappe-plugin/package.json +1 -1
  82. package/packages/generic-web-plugin/package.json +1 -1
  83. package/packages/health-monitor/package.json +1 -1
  84. package/packages/intent-analyzer/package.json +1 -1
  85. package/packages/jev-judge/package.json +1 -1
  86. package/packages/knowledge-graph/package.json +1 -1
  87. package/packages/knowledge-retrieval/package.json +1 -1
  88. package/packages/laravel-plugin/package.json +1 -1
  89. package/packages/learning-engine/package.json +1 -1
  90. package/packages/mcp-adapter/package.json +1 -1
  91. package/packages/memory-engine/package.json +1 -1
  92. package/packages/milestone-manager/package.json +1 -1
  93. package/packages/model-registry/package.json +1 -1
  94. package/packages/nextjs-plugin/package.json +1 -1
  95. package/packages/notification/dist/adapters/telegram-adapter.d.ts +5 -0
  96. package/packages/notification/dist/adapters/telegram-adapter.d.ts.map +1 -1
  97. package/packages/notification/dist/adapters/telegram-adapter.js +54 -0
  98. package/packages/notification/dist/adapters/telegram-adapter.js.map +1 -1
  99. package/packages/notification/dist/notification-center.d.ts +13 -0
  100. package/packages/notification/dist/notification-center.d.ts.map +1 -1
  101. package/packages/notification/dist/notification-center.js +36 -0
  102. package/packages/notification/dist/notification-center.js.map +1 -1
  103. package/packages/notification/package.json +1 -1
  104. package/packages/notification/src/adapters/telegram-adapter.ts +71 -0
  105. package/packages/notification/src/notification-center.ts +53 -0
  106. package/packages/observability/package.json +1 -1
  107. package/packages/okf-indexer/package.json +1 -1
  108. package/packages/paperclip-integration/package.json +1 -1
  109. package/packages/performance-optimizer/package.json +1 -1
  110. package/packages/privilege-broker/package.json +1 -1
  111. package/packages/project-analyzer/package.json +1 -1
  112. package/packages/project-bootstrap/package.json +1 -1
  113. package/packages/projection-engine/package.json +1 -1
  114. package/packages/prompt-compiler/package.json +1 -1
  115. package/packages/prompt-versioning/package.json +1 -1
  116. package/packages/provider-adapter-sdk/package.json +1 -1
  117. package/packages/provider-router/package.json +1 -1
  118. package/packages/provider-selector/package.json +1 -1
  119. package/packages/providers/package.json +1 -1
  120. package/packages/qdrant-skills/package.json +1 -1
  121. package/packages/quota-manager/package.json +1 -1
  122. package/packages/rate-limiter/package.json +1 -1
  123. package/packages/react-vite-plugin/package.json +1 -1
  124. package/packages/release-manager/package.json +1 -1
  125. package/packages/requirement-compiler/package.json +1 -1
  126. package/packages/runtime/package.json +1 -1
  127. package/packages/scheduler/package.json +1 -1
  128. package/packages/scheduler-adapter/package.json +1 -1
  129. package/packages/session/package.json +1 -1
  130. package/packages/session-api/package.json +1 -1
  131. package/packages/session-export/package.json +1 -1
  132. package/packages/shared-context/package.json +1 -1
  133. package/packages/skill-mcp-client/package.json +1 -1
  134. package/packages/skill-registry/package.json +1 -1
  135. package/packages/skills/package.json +1 -1
  136. package/packages/sprint-planner/package.json +1 -1
  137. package/packages/subscription-engine/package.json +1 -1
  138. package/packages/task-compiler/package.json +1 -1
  139. package/packages/tencentdb-memory/package.json +1 -1
  140. package/packages/tencentdb-sync/package.json +1 -1
  141. package/packages/test-data-generator/package.json +1 -1
  142. package/packages/test-generator/package.json +1 -1
  143. package/packages/todo-bd-sync/package.json +1 -1
  144. package/packages/token-estimation/package.json +1 -1
  145. package/packages/token-optimizer/package.json +1 -1
  146. package/packages/trajectory/package.json +1 -1
  147. package/packages/tui/package.json +1 -1
  148. package/packages/types/package.json +1 -1
  149. package/packages/workflow-events/package.json +1 -1
  150. package/packages/workspace-scanner/package.json +1 -1
  151. package/packages/worktree/package.json +1 -1
  152. package/packages/write-review/package.json +1 -1
  153. package/proactive-compact.ts +2 -2
  154. package/scripts/debug-codex-integration.ts +203 -0
  155. package/scripts/sync-keys-from-pi.ts +188 -0
  156. package/scripts/test-codex-session.ts +23 -0
  157. package/scripts/test-openai.ts +14 -0
  158. package/scripts/test-telegram.ts +34 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * PolicyLoader - Loads and hashes harness and scoped project rules.
3
+ *
4
+ * Responsibilities:
5
+ * - Load the immutable harness policy shipped with the package
6
+ * - Walk from project root toward target file collecting scoped AGENTS.md
7
+ * - Normalize newlines and paths, then hash the ordered mandatory content
8
+ * - Build a PolicyManifest with source paths, scope, priority, and hashes
9
+ */
10
+ import { createHash } from "node:crypto";
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { dirname, join, relative, resolve } from "node:path";
13
+ // ---------------------------------------------------------------------------
14
+ // Constants
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Supported rule file names in priority order.
18
+ * Earlier names have higher priority.
19
+ */
20
+ const RULE_FILE_NAMES = [
21
+ "AGENTS.md", // Mandatory, harness or project
22
+ "RULES.md", // Advisory
23
+ "PROJECT_RULES.md", // Advisory
24
+ "CLAUDE.md", // Advisory
25
+ "CONTRIBUTING.md", // Advisory (only if explicitly trusted)
26
+ ];
27
+ /**
28
+ * Maximum walk depth to prevent infinite loops.
29
+ */
30
+ const MAX_WALK_DEPTH = 20;
31
+ /**
32
+ * Files that indicate project trust.
33
+ */
34
+ const TRUST_INDICATORS = [".git", "package.json", "Cargo.toml", "go.mod"];
35
+ /**
36
+ * Loads and processes agent policies from harness and project sources.
37
+ */
38
+ export class PolicyLoader {
39
+ harnessRulesPath;
40
+ additionalRulesPaths;
41
+ cache = new Map();
42
+ CACHE_TTL_MS = 5000; // 5 second cache for same-cwd loads
43
+ constructor(config) {
44
+ this.harnessRulesPath = config.harnessRulesPath;
45
+ this.additionalRulesPaths = config.additionalRulesPaths ?? [];
46
+ }
47
+ /**
48
+ * Load policy for a given project root.
49
+ */
50
+ async load(projectRoot) {
51
+ const cacheKey = this.getCacheKey(projectRoot);
52
+ const cached = this.cache.get(cacheKey);
53
+ if (cached && Date.now() - cached.cachedAt < this.CACHE_TTL_MS) {
54
+ return cached.manifest;
55
+ }
56
+ const manifest = await this.buildManifest(projectRoot);
57
+ this.cache.set(cacheKey, { manifest, cachedAt: Date.now() });
58
+ return manifest;
59
+ }
60
+ /**
61
+ * Load policy for a specific target file (considers scoped rules).
62
+ */
63
+ async loadForTarget(projectRoot, targetPath) {
64
+ if (!targetPath) {
65
+ return this.load(projectRoot);
66
+ }
67
+ // Check if target is in a specific scope
68
+ const relativePath = relative(projectRoot, targetPath);
69
+ const scope = this.inferScope(relativePath);
70
+ const manifest = await this.load(projectRoot);
71
+ // Filter sources to only those applicable to this scope
72
+ if (scope) {
73
+ manifest.sources = manifest.sources.filter(s => s.scope === "" || scope.startsWith(s.scope) || s.scope.startsWith(scope));
74
+ // Recompute revision if sources changed
75
+ if (manifest.sources.length > 0) {
76
+ manifest.revision = this.computeRevision(manifest.sources);
77
+ }
78
+ }
79
+ return manifest;
80
+ }
81
+ /**
82
+ * Invalidate cache for a project root.
83
+ */
84
+ invalidateCache(projectRoot) {
85
+ if (projectRoot) {
86
+ this.cache.delete(this.getCacheKey(projectRoot));
87
+ }
88
+ else {
89
+ this.cache.clear();
90
+ }
91
+ }
92
+ /**
93
+ * Build manifest for a project root.
94
+ */
95
+ async buildManifest(projectRoot) {
96
+ const sources = [];
97
+ const errors = [];
98
+ // 1. Load harness-owned rules first (highest priority)
99
+ const harnessSources = await this.loadHarnessRules();
100
+ sources.push(...harnessSources);
101
+ // 2. Load project rules (if project is trusted)
102
+ const trust = this.evaluateTrust(projectRoot);
103
+ if (trust !== "unknown") {
104
+ const projectSources = await this.loadProjectRules(projectRoot);
105
+ sources.push(...projectSources);
106
+ }
107
+ else {
108
+ // Project not trusted, but we still try to load AGENTS.md as advisory
109
+ const untrustedSources = await this.loadProjectRules(projectRoot, true);
110
+ sources.push(...untrustedSources);
111
+ }
112
+ // 3. Compute revision from mandatory sources
113
+ const mandatorySources = sources.filter(s => s.priority === "mandatory");
114
+ const revision = this.computeRevision(mandatorySources);
115
+ // 4. Determine coverage
116
+ const coverage = this.determineCoverage(sources, errors);
117
+ return {
118
+ revision,
119
+ projectRoot: resolve(projectRoot),
120
+ trust,
121
+ coverage,
122
+ sources,
123
+ loadedAt: Date.now(),
124
+ loadError: errors.length > 0 ? errors.join("; ") : undefined,
125
+ };
126
+ }
127
+ /**
128
+ * Load harness-owned rule files.
129
+ */
130
+ async loadHarnessRules() {
131
+ const sources = [];
132
+ // Load main harness AGENTS.md
133
+ if (existsSync(this.harnessRulesPath)) {
134
+ try {
135
+ const content = readFileSync(this.harnessRulesPath, "utf8");
136
+ const normalized = this.normalizeContent(content);
137
+ const sha256 = this.hashContent(normalized);
138
+ sources.push({
139
+ path: this.harnessRulesPath.toString(),
140
+ scope: "", // Root scope - applies everywhere
141
+ priority: "mandatory",
142
+ sha256,
143
+ bytes: Buffer.byteLength(content, "utf8"),
144
+ harnessOwned: true,
145
+ });
146
+ }
147
+ catch (err) {
148
+ throw new Error(`Failed to load harness rules from ${this.harnessRulesPath}: ${err}`);
149
+ }
150
+ }
151
+ else {
152
+ throw new Error(`Harness rules not found at ${this.harnessRulesPath}`);
153
+ }
154
+ // Load additional harness rules
155
+ for (const rulesPath of this.additionalRulesPaths) {
156
+ if (existsSync(rulesPath)) {
157
+ try {
158
+ const content = readFileSync(rulesPath, "utf8");
159
+ const normalized = this.normalizeContent(content);
160
+ const sha256 = this.hashContent(normalized);
161
+ sources.push({
162
+ path: rulesPath.toString(),
163
+ scope: "", // Root scope
164
+ priority: "mandatory",
165
+ sha256,
166
+ bytes: Buffer.byteLength(content, "utf8"),
167
+ harnessOwned: true,
168
+ });
169
+ }
170
+ catch (err) {
171
+ console.error(`Failed to load additional rules from ${rulesPath}: ${err}`);
172
+ }
173
+ }
174
+ }
175
+ return sources;
176
+ }
177
+ /**
178
+ * Load project-owned rule files, walking from root toward target.
179
+ */
180
+ async loadProjectRules(projectRoot, forceAdvisory = false) {
181
+ const sources = [];
182
+ let dir = projectRoot;
183
+ let depth = 0;
184
+ while (dir && depth < MAX_WALK_DEPTH) {
185
+ for (const fileName of RULE_FILE_NAMES) {
186
+ const filePath = join(dir, fileName);
187
+ if (existsSync(filePath)) {
188
+ try {
189
+ const content = readFileSync(filePath, "utf8");
190
+ const normalized = this.normalizeContent(content);
191
+ const sha256 = this.hashContent(normalized);
192
+ // Determine priority and scope
193
+ const isMandatory = fileName === "AGENTS.md" && !forceAdvisory;
194
+ const scope = dir === projectRoot ? "" : "/" + relative(projectRoot, dir);
195
+ sources.push({
196
+ path: filePath,
197
+ scope,
198
+ priority: isMandatory ? "mandatory" : "advisory",
199
+ sha256,
200
+ bytes: Buffer.byteLength(content, "utf8"),
201
+ harnessOwned: false,
202
+ });
203
+ }
204
+ catch (err) {
205
+ console.error(`Failed to load project rule ${filePath}: ${err}`);
206
+ }
207
+ }
208
+ }
209
+ // Move to parent directory
210
+ const parent = dirname(dir);
211
+ if (parent === dir)
212
+ break;
213
+ dir = parent;
214
+ depth++;
215
+ }
216
+ return sources;
217
+ }
218
+ /**
219
+ * Evaluate trust level for a project.
220
+ */
221
+ evaluateTrust(projectRoot) {
222
+ let trustIndicatorsFound = 0;
223
+ let untrustIndicatorsFound = 0;
224
+ for (const indicator of TRUST_INDICATORS) {
225
+ if (existsSync(join(projectRoot, indicator))) {
226
+ trustIndicatorsFound++;
227
+ }
228
+ }
229
+ // Check for untrusted indicators (e.g., downloaded zip, unknown origin)
230
+ // For now, presence of .git or package.json means trusted
231
+ if (trustIndicatorsFound > 0) {
232
+ return "trusted";
233
+ }
234
+ return "unknown";
235
+ }
236
+ /**
237
+ * Infer the scope from a relative path.
238
+ */
239
+ inferScope(relativePath) {
240
+ // Extract directory component
241
+ const segments = relativePath.split("/");
242
+ if (segments.length <= 1) {
243
+ return ""; // Root scope
244
+ }
245
+ // If first segment is "src" or "packages", use that as scope
246
+ if (segments[0] === "src" || segments[0] === "packages") {
247
+ return segments[0] + "/";
248
+ }
249
+ // Otherwise, use the directory containing the file
250
+ if (segments.length > 1) {
251
+ return segments.slice(0, -1).join("/") + "/";
252
+ }
253
+ return "";
254
+ }
255
+ /**
256
+ * Normalize content for consistent hashing.
257
+ */
258
+ normalizeContent(content) {
259
+ return content
260
+ .replace(/\r\n/g, "\n") // Normalize line endings
261
+ .replace(/\t/g, " ") // Normalize tabs
262
+ .replace(/[ \t]+$/gm, "") // Trim trailing whitespace
263
+ .replace(/\n{3,}/g, "\n\n"); // Collapse excessive newlines
264
+ }
265
+ /**
266
+ * Compute SHA-256 hash of content.
267
+ */
268
+ hashContent(content) {
269
+ return createHash("sha256").update(content, "utf8").digest("hex").slice(0, 16);
270
+ }
271
+ /**
272
+ * Compute combined revision from sources.
273
+ */
274
+ computeRevision(sources) {
275
+ // Sort by path for deterministic ordering
276
+ const sorted = [...sources].sort((a, b) => a.path.localeCompare(b.path));
277
+ const combined = sorted.map(s => s.sha256).join("|");
278
+ return this.hashContent(combined);
279
+ }
280
+ /**
281
+ * Determine coverage based on loaded sources and errors.
282
+ */
283
+ determineCoverage(sources, errors) {
284
+ if (errors.length > 0) {
285
+ return "degraded";
286
+ }
287
+ const mandatorySources = sources.filter(s => s.priority === "mandatory");
288
+ if (mandatorySources.length === 0) {
289
+ return "degraded"; // No mandatory rules loaded
290
+ }
291
+ // Check if any mandatory sources failed to load (bytes === 0)
292
+ if (mandatorySources.some(s => s.bytes === 0)) {
293
+ return "partial";
294
+ }
295
+ return "complete";
296
+ }
297
+ /**
298
+ * Generate cache key for a project root.
299
+ */
300
+ getCacheKey(projectRoot) {
301
+ return resolve(projectRoot);
302
+ }
303
+ /**
304
+ * Read the raw content of a source file.
305
+ */
306
+ readSourceContent(path) {
307
+ if (existsSync(path)) {
308
+ try {
309
+ return readFileSync(path, "utf8");
310
+ }
311
+ catch {
312
+ return null;
313
+ }
314
+ }
315
+ return null;
316
+ }
317
+ }
318
+ // ---------------------------------------------------------------------------
319
+ // Factory
320
+ // ---------------------------------------------------------------------------
321
+ /**
322
+ * Create a PolicyLoader with the standard harness configuration.
323
+ */
324
+ export function createPolicyLoader() {
325
+ // Resolve harness AGENTS.md relative to the package directory
326
+ const harnessRulesPath = new URL("../../AGENTS.md", import.meta.url);
327
+ return new PolicyLoader({
328
+ harnessRulesPath,
329
+ });
330
+ }
331
+ //# sourceMappingURL=policy-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-loader.js","sourceRoot":"","sources":["../src/policy-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * PolicyRenderer - Renders compact system contract for agent injection.
3
+ *
4
+ * Responsibilities:
5
+ * - Render a compact, deterministic contract for before_agent_start injection
6
+ * - Render full rule text for the harness_rules tool
7
+ * - Render policy status for display
8
+ */
9
+ import type { PolicyManifest, PolicySection, HarnessRulesOutput, MinimaxFindingEnvelope } from "./types.js";
10
+ /**
11
+ * Render the compact mandatory contract for system prompt injection.
12
+ */
13
+ export declare function renderSystemContract(manifest: PolicyManifest): string;
14
+ /**
15
+ * Parse markdown content into sections.
16
+ */
17
+ export declare function parseSections(content: string, source: string, scope: string, priority: "mandatory" | "advisory"): PolicySection[];
18
+ /**
19
+ * Render full rules for the harness_rules tool.
20
+ */
21
+ export declare function renderFullRules(manifest: PolicyManifest, options?: {
22
+ source?: string;
23
+ section?: string;
24
+ maxBytes?: number;
25
+ }): HarnessRulesOutput;
26
+ /**
27
+ * Render a manifest summary.
28
+ */
29
+ export declare function renderManifestSummary(manifest: PolicyManifest): string;
30
+ /**
31
+ * Render a finding envelope for display.
32
+ */
33
+ export declare function renderFindingEnvelope(envelope: MinimaxFindingEnvelope): string;
34
+ /**
35
+ * Create a clean finding envelope.
36
+ */
37
+ export declare function createCleanEnvelope(coverage?: "delta" | "targeted" | "full"): MinimaxFindingEnvelope;
38
+ /**
39
+ * Create a degraded finding envelope.
40
+ */
41
+ export declare function createDegradedEnvelope(reason: string, coverage?: "delta" | "targeted" | "full"): MinimaxFindingEnvelope;
42
+ //# sourceMappingURL=policy-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-renderer.d.ts","sourceRoot":"","sources":["../src/policy-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAM5G;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAiCrE;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,UAAU,GAAG,aAAa,EAAE,CA6EjI;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,kBAAkB,CA0DpB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CA0BtE;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,CAuD9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,OAAO,GAAG,UAAU,GAAG,MAAe,GAAG,sBAAsB,CAS5G;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,OAAO,GAAG,UAAU,GAAG,MAAgB,GAChD,sBAAsB,CASxB"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * PolicyRenderer - Renders compact system contract for agent injection.
3
+ *
4
+ * Responsibilities:
5
+ * - Render a compact, deterministic contract for before_agent_start injection
6
+ * - Render full rule text for the harness_rules tool
7
+ * - Render policy status for display
8
+ */
9
+ import { readFileSync, existsSync } from "node:fs";
10
+ // ---------------------------------------------------------------------------
11
+ // System Contract Rendering
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Render the compact mandatory contract for system prompt injection.
15
+ */
16
+ export function renderSystemContract(manifest) {
17
+ const lines = [];
18
+ // Header
19
+ lines.push(`PI-HARNESS POLICY revision=${manifest.revision} coverage=${manifest.coverage}`);
20
+ lines.push("");
21
+ // Mandatory rules
22
+ lines.push("Mandatory:");
23
+ lines.push("- Read and follow the active harness and scoped project rules.");
24
+ lines.push("- Before mutation, call harness_rules when the current revision is not loaded.");
25
+ lines.push("- Treat [BLOCKING] code findings as completion gates.");
26
+ lines.push("- Treat [DEGRADED] as incomplete evidence, never as clean.");
27
+ lines.push("- Re-read a file after the harness reports an automatic mutation.");
28
+ lines.push("");
29
+ // Tool reference
30
+ lines.push("Use harness_rules for full text and source attribution.");
31
+ lines.push("");
32
+ // Trust indicator
33
+ if (manifest.trust === "untrusted") {
34
+ lines.push("WARNING: Project is not trusted. Project rules are advisory only.");
35
+ lines.push("");
36
+ }
37
+ // Coverage warning
38
+ if (manifest.coverage !== "complete") {
39
+ lines.push(`WARNING: Policy coverage is ${manifest.coverage}. Some rules may be missing.`);
40
+ lines.push("");
41
+ }
42
+ return lines.join("\n");
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Rule Section Parsing
46
+ // ---------------------------------------------------------------------------
47
+ /**
48
+ * Parse markdown content into sections.
49
+ */
50
+ export function parseSections(content, source, scope, priority) {
51
+ const sections = [];
52
+ const lines = content.split("\n");
53
+ let currentSection = null;
54
+ let sectionIndex = 0;
55
+ for (let i = 0; i < lines.length; i++) {
56
+ const line = lines[i];
57
+ const lineOffset = content.split("\n").slice(0, i).join("\n").length;
58
+ // Check for markdown heading
59
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
60
+ if (headingMatch) {
61
+ // Save previous section
62
+ if (currentSection) {
63
+ sections.push({
64
+ id: currentSection.id,
65
+ title: currentSection.title,
66
+ content: currentSection.content.join("\n").trim(),
67
+ source,
68
+ scope,
69
+ priority,
70
+ offset: currentSection.offset,
71
+ truncated: false,
72
+ });
73
+ }
74
+ // Start new section
75
+ const level = headingMatch[1].length;
76
+ const title = headingMatch[2].trim();
77
+ currentSection = {
78
+ id: `section-${sectionIndex++}`,
79
+ title,
80
+ content: [],
81
+ offset: lineOffset,
82
+ };
83
+ }
84
+ else if (currentSection) {
85
+ currentSection.content.push(line);
86
+ }
87
+ }
88
+ // Save last section
89
+ if (currentSection) {
90
+ sections.push({
91
+ id: currentSection.id,
92
+ title: currentSection.title,
93
+ content: currentSection.content.join("\n").trim(),
94
+ source,
95
+ scope,
96
+ priority,
97
+ offset: currentSection.offset,
98
+ truncated: false,
99
+ });
100
+ }
101
+ // If no sections found, create a single section with the whole content
102
+ if (sections.length === 0) {
103
+ sections.push({
104
+ id: "section-0",
105
+ title: "Full Content",
106
+ content: content.trim(),
107
+ source,
108
+ scope,
109
+ priority,
110
+ offset: 0,
111
+ truncated: false,
112
+ });
113
+ }
114
+ return sections;
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // Full Rules Rendering
118
+ // ---------------------------------------------------------------------------
119
+ /**
120
+ * Render full rules for the harness_rules tool.
121
+ */
122
+ export function renderFullRules(manifest, options = {}) {
123
+ const sections = [];
124
+ const maxBytes = options.maxBytes ?? 50 * 1024; // Default 50KB cap
125
+ // Filter sources
126
+ let sources = manifest.sources;
127
+ if (options.source) {
128
+ sources = sources.filter(s => s.path.includes(options.source));
129
+ }
130
+ // Parse sections from each source
131
+ for (const source of sources) {
132
+ const content = readSourceContent(source.path);
133
+ if (!content)
134
+ continue;
135
+ const sourceSections = parseSections(content, source.path, source.scope, source.priority);
136
+ // Filter by section if requested
137
+ const filteredSections = options.section
138
+ ? sourceSections.filter(s => s.title.toLowerCase().includes(options.section.toLowerCase()) ||
139
+ s.id === options.section)
140
+ : sourceSections;
141
+ sections.push(...filteredSections);
142
+ }
143
+ // Truncate if needed
144
+ let totalBytes = 0;
145
+ let truncated = false;
146
+ const truncatedSections = [];
147
+ for (const section of sections) {
148
+ const sectionBytes = Buffer.byteLength(section.content, "utf8");
149
+ if (totalBytes + sectionBytes > maxBytes) {
150
+ // Check if we can fit a partial section
151
+ const remainingBytes = maxBytes - totalBytes;
152
+ if (remainingBytes > 100) {
153
+ // Fit as much as possible
154
+ truncatedSections.push({
155
+ ...section,
156
+ content: section.content.slice(0, remainingBytes),
157
+ truncated: true,
158
+ });
159
+ }
160
+ truncated = true;
161
+ break;
162
+ }
163
+ truncatedSections.push(section);
164
+ totalBytes += sectionBytes;
165
+ }
166
+ return {
167
+ sections: truncatedSections,
168
+ };
169
+ }
170
+ /**
171
+ * Render a manifest summary.
172
+ */
173
+ export function renderManifestSummary(manifest) {
174
+ const lines = [];
175
+ lines.push(`Policy Manifest`);
176
+ lines.push(`================`);
177
+ lines.push(`Revision: ${manifest.revision}`);
178
+ lines.push(`Project: ${manifest.projectRoot}`);
179
+ lines.push(`Trust: ${manifest.trust}`);
180
+ lines.push(`Coverage: ${manifest.coverage}`);
181
+ lines.push(`Loaded: ${new Date(manifest.loadedAt).toISOString()}`);
182
+ lines.push("");
183
+ lines.push("Sources:");
184
+ for (const source of manifest.sources) {
185
+ const scope = source.scope || "(root)";
186
+ const priority = source.priority;
187
+ const owner = source.harnessOwned ? "[harness]" : "[project]";
188
+ lines.push(` ${owner} ${scope} ${priority} ${source.path}`);
189
+ }
190
+ if (manifest.loadError) {
191
+ lines.push("");
192
+ lines.push(`ERROR: ${manifest.loadError}`);
193
+ }
194
+ return lines.join("\n");
195
+ }
196
+ // ---------------------------------------------------------------------------
197
+ // Finding Envelope Rendering
198
+ // ---------------------------------------------------------------------------
199
+ /**
200
+ * Render a finding envelope for display.
201
+ */
202
+ export function renderFindingEnvelope(envelope) {
203
+ const lines = [];
204
+ // Header with verdict
205
+ const verdictPrefix = {
206
+ blocking: "[BLOCKING]",
207
+ advisory: "[ADVISORY]",
208
+ clean: "[CLEAN]",
209
+ degraded: "[DEGRADED]",
210
+ }[envelope.verdict];
211
+ lines.push(`${verdictPrefix} Code Analysis (${envelope.coverage} coverage, ${envelope.freshness})`);
212
+ lines.push("");
213
+ // Summary
214
+ if (envelope.summary) {
215
+ lines.push(envelope.summary);
216
+ lines.push("");
217
+ }
218
+ // Individual findings
219
+ if (envelope.findings.length > 0) {
220
+ for (const finding of envelope.findings) {
221
+ const severity = {
222
+ error: "ERROR",
223
+ warning: "WARN",
224
+ information: "INFO",
225
+ hint: "HINT",
226
+ }[finding.severity];
227
+ const location = finding.line ? `${finding.path}:${finding.line}` : finding.path;
228
+ const blocking = finding.blocking ? " [BLOCKING]" : "";
229
+ lines.push(`${severity} ${location}: ${finding.message}${blocking}`);
230
+ if (finding.fix) {
231
+ lines.push(` Fix: ${finding.fix}`);
232
+ }
233
+ }
234
+ lines.push("");
235
+ }
236
+ // Next action
237
+ if (envelope.nextAction) {
238
+ const actionText = {
239
+ fix: "Required: fix these issues before reporting completion.",
240
+ reread: "Required: re-read affected files to get updated analysis.",
241
+ run_full: "Required: do not report the project clean; run a full analysis.",
242
+ continue: "No blocking issues found.",
243
+ }[envelope.nextAction];
244
+ lines.push(actionText);
245
+ }
246
+ return lines.join("\n");
247
+ }
248
+ /**
249
+ * Create a clean finding envelope.
250
+ */
251
+ export function createCleanEnvelope(coverage = "full") {
252
+ return {
253
+ verdict: "clean",
254
+ coverage,
255
+ freshness: "fresh",
256
+ findings: [],
257
+ nextAction: "continue",
258
+ summary: "No blocking issues found in code analysis.",
259
+ };
260
+ }
261
+ /**
262
+ * Create a degraded finding envelope.
263
+ */
264
+ export function createDegradedEnvelope(reason, coverage = "delta") {
265
+ return {
266
+ verdict: "degraded",
267
+ coverage,
268
+ freshness: "indeterminate",
269
+ findings: [],
270
+ nextAction: "run_full",
271
+ summary: `Analysis degraded: ${reason}. Do not claim the project is clean.`,
272
+ };
273
+ }
274
+ // ---------------------------------------------------------------------------
275
+ // Helpers
276
+ // ---------------------------------------------------------------------------
277
+ /**
278
+ * Read source content from a path.
279
+ */
280
+ function readSourceContent(path) {
281
+ // Handle file:// URLs
282
+ const normalizedPath = path.startsWith("file://")
283
+ ? path.slice(7)
284
+ : path;
285
+ if (existsSync(normalizedPath)) {
286
+ try {
287
+ return readFileSync(normalizedPath, "utf8");
288
+ }
289
+ catch {
290
+ return null;
291
+ }
292
+ }
293
+ return null;
294
+ }
295
+ //# sourceMappingURL=policy-renderer.js.map