@bolloon/bolloon-agent 0.2.2 → 0.2.3

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 (132) hide show
  1. package/bin/ipfs +0 -0
  2. package/dist/agents/parse-tool-call.js +304 -0
  3. package/dist/agents/pi-sdk.js +190 -286
  4. package/dist/agents/react-loop.js +86 -0
  5. package/dist/agents/session-store.js +157 -0
  6. package/dist/agents/tool-registry.js +136 -0
  7. package/dist/agents/workflow-pivot-loop.js +40 -0
  8. package/dist/bollharness/src/index.js +5 -0
  9. package/dist/bollharness/src/scripts/checks/check_adr_plan_numbering.js +6 -0
  10. package/dist/bollharness/src/scripts/checks/check_api_types.js +45 -0
  11. package/dist/bollharness/src/scripts/checks/check_artifact_link.js +146 -0
  12. package/dist/bollharness/src/scripts/checks/check_bridge_deps.js +6 -0
  13. package/dist/bollharness/src/scripts/checks/check_bugfix_binding.js +6 -0
  14. package/dist/bollharness/src/scripts/checks/check_bugfix_binding_ci.js +6 -0
  15. package/dist/bollharness/src/scripts/checks/check_doc_file_references.js +6 -0
  16. package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +135 -0
  17. package/dist/bollharness/src/scripts/checks/check_doc_links.js +31 -0
  18. package/dist/bollharness/src/scripts/checks/check_file_existence_claims.js +6 -0
  19. package/dist/bollharness/src/scripts/checks/check_fragment_integrity.js +34 -0
  20. package/dist/bollharness/src/scripts/checks/check_hook_installed.js +63 -0
  21. package/dist/bollharness/src/scripts/checks/check_issue_closure.js +41 -0
  22. package/dist/bollharness/src/scripts/checks/check_mcp_parity.js +6 -0
  23. package/dist/bollharness/src/scripts/checks/check_security.js +48 -0
  24. package/dist/bollharness/src/scripts/checks/check_skill_parity.js +6 -0
  25. package/dist/bollharness/src/scripts/checks/check_versions.js +6 -0
  26. package/dist/bollharness/src/scripts/checks/finding.js +13 -0
  27. package/dist/bollharness/src/scripts/checks/next_decision_number.js +20 -0
  28. package/dist/bollharness/src/scripts/checks/regenerate_magic_docs.js +6 -0
  29. package/dist/bollharness/src/scripts/ci/detect_rebaseline_triggers.js +8 -0
  30. package/dist/bollharness/src/scripts/ci/scan_subprocess_cfg.js +8 -0
  31. package/dist/bollharness/src/scripts/ci/scan_verify_artifacts.js +8 -0
  32. package/dist/bollharness/src/scripts/ci/scan_yaml_schema.js +8 -0
  33. package/dist/bollharness/src/scripts/context_router.js +67 -0
  34. package/dist/bollharness/src/scripts/deploy-guard.js +157 -0
  35. package/dist/bollharness/src/scripts/guard-feedback.js +192 -0
  36. package/dist/bollharness/src/scripts/guard_router.js +158 -0
  37. package/dist/bollharness/src/scripts/hooks/_hook_output.js +6 -0
  38. package/dist/bollharness/src/scripts/hooks/auto-python3.js +6 -0
  39. package/dist/bollharness/src/scripts/hooks/deploy-progress-on-session-end.js +6 -0
  40. package/dist/bollharness/src/scripts/hooks/failure-analyzer.js +6 -0
  41. package/dist/bollharness/src/scripts/hooks/gate-judgment-inject.js +92 -0
  42. package/dist/bollharness/src/scripts/hooks/gate-transition-judgment.js +63 -0
  43. package/dist/bollharness/src/scripts/hooks/inbox-ack.js +6 -0
  44. package/dist/bollharness/src/scripts/hooks/inbox-inject-on-start.js +6 -0
  45. package/dist/bollharness/src/scripts/hooks/inbox-validate.js +6 -0
  46. package/dist/bollharness/src/scripts/hooks/inbox-write-ledger.js +6 -0
  47. package/dist/bollharness/src/scripts/hooks/initializer-agent.js +6 -0
  48. package/dist/bollharness/src/scripts/hooks/loop-detection.js +73 -0
  49. package/dist/bollharness/src/scripts/hooks/owner-guard.js +6 -0
  50. package/dist/bollharness/src/scripts/hooks/precompact.js +6 -0
  51. package/dist/bollharness/src/scripts/hooks/review-agent-gatekeeper.js +6 -0
  52. package/dist/bollharness/src/scripts/hooks/risk-tracker.js +108 -0
  53. package/dist/bollharness/src/scripts/hooks/sanitize-on-read.js +6 -0
  54. package/dist/bollharness/src/scripts/hooks/session-reflection.js +7 -0
  55. package/dist/bollharness/src/scripts/hooks/session-start-magic-docs.js +7 -0
  56. package/dist/bollharness/src/scripts/hooks/session-start-reset-risk.js +7 -0
  57. package/dist/bollharness/src/scripts/hooks/session-start-toolkit-reminder.js +7 -0
  58. package/dist/bollharness/src/scripts/hooks/stop-evaluator.js +157 -0
  59. package/dist/bollharness/src/scripts/hooks/tool-call-counter.js +6 -0
  60. package/dist/bollharness/src/scripts/hooks/trace-analyzer.js +10 -0
  61. package/dist/bollharness/src/scripts/install/install-trust-token.js +7 -0
  62. package/dist/bollharness/src/scripts/install/multi_project_registry.js +9 -0
  63. package/dist/bollharness/src/scripts/install/phase2_auto.js +21 -0
  64. package/dist/bollharness/src/scripts/install/pre_commit_installer.js +6 -0
  65. package/dist/bollharness/src/scripts/install/tier_selector.js +7 -0
  66. package/dist/bollharness/src/scripts/install/transcript_miner.js +7 -0
  67. package/dist/bollharness/src/scripts/lib/claim_patterns.js +10 -0
  68. package/dist/bollharness/src/scripts/lib/sanitize_patterns.js +12 -0
  69. package/dist/bollharness/src/scripts/sanitize.js +6 -0
  70. package/dist/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +6 -0
  71. package/dist/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +6 -0
  72. package/dist/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +5 -0
  73. package/dist/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +6 -0
  74. package/dist/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +4 -0
  75. package/dist/constraint-runtime/src/tools/SafeSDK/deploySafe.js +6 -0
  76. package/dist/constraint-runtime/src/tools/WalletTools/autoPay.js +29 -0
  77. package/dist/constraint-runtime/src/tools/WalletTools/createWallet.js +10 -0
  78. package/dist/constraint-runtime/src/tools/WalletTools/getBalance.js +13 -0
  79. package/dist/constraint-runtime/src/tools/WalletTools/importWallet.js +22 -0
  80. package/dist/constraint-runtime/src/tools/WalletTools/sendTransaction.js +25 -0
  81. package/dist/constraint-runtime/src/tools/WalletTools/signMessage.js +10 -0
  82. package/dist/constraint-runtime/src/tools/WalletTools/transferToken.js +25 -0
  83. package/dist/electron/config.js.map +1 -0
  84. package/dist/electron/dialogs.js.map +1 -0
  85. package/dist/electron/first-run.js.map +1 -0
  86. package/dist/electron/ipc.js.map +1 -0
  87. package/dist/electron/logger.js.map +1 -0
  88. package/dist/electron/main.js.map +1 -0
  89. package/dist/electron/menu.js.map +1 -0
  90. package/dist/electron/paths.js.map +1 -0
  91. package/dist/electron/server.js.map +1 -0
  92. package/dist/electron/tray.js.map +1 -0
  93. package/dist/electron/window.js.map +1 -0
  94. package/dist/electron-preload.js +29 -0
  95. package/dist/electron-preload.js.map +1 -0
  96. package/dist/electron.js +5 -0
  97. package/dist/electron.js.map +1 -0
  98. package/dist/llm/config-store.js +24 -8
  99. package/dist/llm/pi-ai.js +33 -19
  100. package/dist/workflows/collaboration.js +374 -0
  101. package/dist/workflows/index.js +54 -0
  102. package/package.json +12 -3
  103. package/CLAUDE.md +0 -3
  104. package/build/icon.icns +0 -0
  105. package/build/icon.ico +0 -0
  106. package/build/icon.png +0 -0
  107. package/build/tray.png +0 -0
  108. package/build/trayTemplate.png +0 -0
  109. package/ios/App/App/AppDelegate.swift +0 -49
  110. package/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png +0 -0
  111. package/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -14
  112. package/ios/App/App/Assets.xcassets/Contents.json +0 -6
  113. package/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json +0 -23
  114. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png +0 -0
  115. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png +0 -0
  116. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png +0 -0
  117. package/ios/App/App/Base.lproj/LaunchScreen.storyboard +0 -32
  118. package/ios/App/App/Base.lproj/Main.storyboard +0 -19
  119. package/ios/App/App/Info.plist +0 -88
  120. package/ios/App/App.xcodeproj/project.pbxproj +0 -376
  121. package/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  122. package/ios/App/CapApp-SPM/Package.swift +0 -25
  123. package/ios/App/CapApp-SPM/README.md +0 -5
  124. package/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift +0 -1
  125. package/ios/debug.xcconfig +0 -1
  126. package/scripts/auto-evolve-oneshot.sh +0 -155
  127. package/scripts/auto-evolve-snapshot.sh +0 -136
  128. package/scripts/build-app-bundle.cjs +0 -170
  129. package/scripts/build-cli.js +0 -216
  130. package/scripts/detect-schema-changes.sh +0 -48
  131. package/scripts/lefthook-helper.sh +0 -69
  132. package/scripts/postinstall.js +0 -153
@@ -0,0 +1,135 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ function countRouteDecorators(repoRoot) {
4
+ const routesDir = path.join(repoRoot, "backend", "product", "routes");
5
+ if (!fs.existsSync(routesDir))
6
+ return 0;
7
+ let count = 0;
8
+ try {
9
+ const files = fs.readdirSync(routesDir).filter(f => f.endsWith(".py"));
10
+ for (const file of files) {
11
+ const content = fs.readFileSync(path.join(routesDir, file), "utf-8");
12
+ const matches = content.match(/@router\.(get|post|put|patch|delete|websocket)\(/g);
13
+ if (matches)
14
+ count += matches.length;
15
+ }
16
+ }
17
+ catch { }
18
+ return count;
19
+ }
20
+ function countScenes(repoRoot) {
21
+ const scenesDir = path.join(repoRoot, "scenes");
22
+ if (!fs.existsSync(scenesDir))
23
+ return 0;
24
+ try {
25
+ return fs.readdirSync(scenesDir).filter(f => {
26
+ const fullPath = path.join(scenesDir, f);
27
+ return fs.statSync(fullPath).isDirectory() && !f.startsWith(".");
28
+ }).length;
29
+ }
30
+ catch {
31
+ return 0;
32
+ }
33
+ }
34
+ function countADRs(repoRoot) {
35
+ const decisions = path.join(repoRoot, "docs", "decisions");
36
+ if (!fs.existsSync(decisions))
37
+ return 0;
38
+ try {
39
+ return fs.readdirSync(decisions).filter(f => f.startsWith("ADR-") && f.endsWith(".md")).length;
40
+ }
41
+ catch {
42
+ return 0;
43
+ }
44
+ }
45
+ function countPlans(repoRoot) {
46
+ const decisions = path.join(repoRoot, "docs", "decisions");
47
+ if (!fs.existsSync(decisions))
48
+ return 0;
49
+ try {
50
+ return fs.readdirSync(decisions).filter(f => f.startsWith("PLAN-") && f.endsWith(".md")).length;
51
+ }
52
+ catch {
53
+ return 0;
54
+ }
55
+ }
56
+ function extractRoadmapNumbers(repoRoot) {
57
+ const roadmap = path.join(repoRoot, "docs", "ROADMAP.md");
58
+ if (!fs.existsSync(roadmap))
59
+ return {};
60
+ const content = fs.readFileSync(roadmap, "utf-8");
61
+ const numbers = {};
62
+ const regex = /\|\s*(\S[^|]+?)\s*\|\s*(\S[^|]+?)\s*\|/g;
63
+ let match;
64
+ while ((match = regex.exec(content)) !== null) {
65
+ const key = match[1].trim();
66
+ const val = match[2].trim();
67
+ if (key !== "指标" && key !== "---") {
68
+ numbers[key] = val;
69
+ }
70
+ }
71
+ return numbers;
72
+ }
73
+ export function run(repoRoot, mode = "full") {
74
+ const findings = [];
75
+ const actualRoutes = countRouteDecorators(repoRoot);
76
+ const routesDoc = path.join(repoRoot, ".boll", "rules", "backend-routes.md");
77
+ const claudeMd = path.join(repoRoot, "Bolloon.md");
78
+ if (fs.existsSync(routesDoc)) {
79
+ const routesContent = fs.readFileSync(routesDoc, "utf-8");
80
+ const routeClaims = routesContent.match(/-\s+`(?:GET|POST|PUT|PATCH|DELETE|WS)\s+/g) || [];
81
+ const docRoutes = routeClaims.length;
82
+ if (actualRoutes - docRoutes > 5) {
83
+ findings.push({
84
+ severity: "P1",
85
+ message: `.boll/rules/backend-routes.md documents ${docRoutes} routes but code has ${actualRoutes} decorators (gap: ${actualRoutes - docRoutes})`,
86
+ file: ".boll/rules/backend-routes.md",
87
+ blocking: false,
88
+ category: "doc_integrity",
89
+ problem_class: "unknown",
90
+ required_skills: [],
91
+ required_reads: [],
92
+ });
93
+ }
94
+ }
95
+ const actualADRs = countADRs(repoRoot);
96
+ const actualPlans = countPlans(repoRoot);
97
+ const roadmapNums = extractRoadmapNumbers(repoRoot);
98
+ if ("ADR" in roadmapNums) {
99
+ const match = roadmapNums["ADR"].match(/\d+/);
100
+ if (match) {
101
+ const claimed = parseInt(match[0], 10);
102
+ if (actualADRs - claimed > 2) {
103
+ findings.push({
104
+ severity: "P2",
105
+ message: `ROADMAP claims ${claimed} ADRs but ${actualADRs} exist`,
106
+ file: "docs/ROADMAP.md",
107
+ blocking: false,
108
+ category: "doc_integrity",
109
+ problem_class: "unknown",
110
+ required_skills: [],
111
+ required_reads: [],
112
+ });
113
+ }
114
+ }
115
+ }
116
+ if ("PLAN" in roadmapNums) {
117
+ const match = roadmapNums["PLAN"].match(/\d+/);
118
+ if (match) {
119
+ const claimed = parseInt(match[0], 10);
120
+ if (actualPlans - claimed > 3) {
121
+ findings.push({
122
+ severity: "P2",
123
+ message: `ROADMAP claims ${claimed} PLANs but ${actualPlans} exist`,
124
+ file: "docs/ROADMAP.md",
125
+ blocking: false,
126
+ category: "doc_integrity",
127
+ problem_class: "unknown",
128
+ required_skills: [],
129
+ required_reads: [],
130
+ });
131
+ }
132
+ }
133
+ }
134
+ return findings;
135
+ }
@@ -0,0 +1,31 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export function run(repoRoot, mode = "full") {
4
+ const findings = [];
5
+ const docFiles = ["Bolloon.md", "docs/ROADMAP.md", "README.md"];
6
+ const maxAgeDays = 7;
7
+ for (const docFile of docFiles) {
8
+ const fullPath = path.join(repoRoot, docFile);
9
+ if (!fs.existsSync(fullPath))
10
+ continue;
11
+ try {
12
+ const stats = fs.statSync(fullPath);
13
+ const ageMs = Date.now() - stats.mtimeMs;
14
+ const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));
15
+ if (ageDays > maxAgeDays) {
16
+ findings.push({
17
+ severity: "P2",
18
+ message: `${docFile} has not been updated in ${ageDays} days (threshold: ${maxAgeDays})`,
19
+ file: docFile,
20
+ blocking: false,
21
+ category: "doc_freshness",
22
+ problem_class: "unknown",
23
+ required_skills: [],
24
+ required_reads: [],
25
+ });
26
+ }
27
+ }
28
+ catch { }
29
+ }
30
+ return findings;
31
+ }
@@ -0,0 +1,6 @@
1
+ export function run(repoRoot, mode = "full") {
2
+ const findings = [];
3
+ if (mode !== "full" && mode !== "staged")
4
+ return findings;
5
+ return findings;
6
+ }
@@ -0,0 +1,34 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export function run(repoRoot, mode = "full") {
4
+ const findings = [];
5
+ const fragmentDir = path.join(repoRoot, "scripts", "context-fragments");
6
+ const routerFile = path.join(repoRoot, "src", "scripts", "context_router.ts");
7
+ if (!fs.existsSync(routerFile)) {
8
+ findings.push({
9
+ severity: "P1",
10
+ message: "context_router.ts not found",
11
+ file: "src/scripts/context_router.ts",
12
+ blocking: false,
13
+ category: "governance_bootstrap",
14
+ problem_class: "unknown",
15
+ required_skills: [],
16
+ required_reads: [],
17
+ });
18
+ return findings;
19
+ }
20
+ if (!fs.existsSync(fragmentDir)) {
21
+ findings.push({
22
+ severity: "P2",
23
+ message: "context-fragments directory not found",
24
+ file: "scripts/context-fragments/",
25
+ blocking: false,
26
+ category: "governance_bootstrap",
27
+ problem_class: "unknown",
28
+ required_skills: [],
29
+ required_reads: [],
30
+ });
31
+ return findings;
32
+ }
33
+ return findings;
34
+ }
@@ -0,0 +1,63 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export function run(repoRoot, mode = "full") {
4
+ const findings = [];
5
+ const hookFiles = [
6
+ "src/scripts/hooks/loop-detection.ts",
7
+ "src/scripts/hooks/risk-tracker.ts",
8
+ "src/scripts/hooks/stop-evaluator.ts",
9
+ "src/scripts/hooks/guard-feedback.ts",
10
+ "src/scripts/hooks/deploy-guard.ts",
11
+ ];
12
+ const settingsFile = path.join(repoRoot, ".boll", "settings.json");
13
+ if (!fs.existsSync(settingsFile)) {
14
+ findings.push({
15
+ severity: "P1",
16
+ message: ".boll/settings.json does not exist",
17
+ file: ".boll/settings.json",
18
+ blocking: false,
19
+ category: "general",
20
+ problem_class: "unknown",
21
+ required_skills: [],
22
+ required_reads: [],
23
+ });
24
+ return findings;
25
+ }
26
+ try {
27
+ const settings = JSON.parse(fs.readFileSync(settingsFile, "utf-8"));
28
+ const registeredHooks = settings.hooks || {};
29
+ for (const [stage, hooks] of Object.entries(registeredHooks)) {
30
+ const hookList = hooks;
31
+ for (const hookGroup of hookList) {
32
+ for (const hook of hookGroup.hooks || []) {
33
+ const cmd = hook.command || "";
34
+ if (cmd.includes("python3") && cmd.includes(".py")) {
35
+ findings.push({
36
+ severity: "P1",
37
+ message: `Hook in ${stage} still references Python script: ${cmd}`,
38
+ file: ".boll/settings.json",
39
+ blocking: false,
40
+ category: "governance_bootstrap",
41
+ problem_class: "unknown",
42
+ required_skills: [],
43
+ required_reads: [],
44
+ });
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ catch (exc) {
51
+ findings.push({
52
+ severity: "P1",
53
+ message: `Failed to parse settings.json: ${exc}`,
54
+ file: ".boll/settings.json",
55
+ blocking: false,
56
+ category: "governance_bootstrap",
57
+ problem_class: "unknown",
58
+ required_skills: [],
59
+ required_reads: [],
60
+ });
61
+ }
62
+ return findings;
63
+ }
@@ -0,0 +1,41 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export function run(repoRoot, mode = "full") {
4
+ const findings = [];
5
+ const docsIssuesDir = path.join(repoRoot, "docs", "issues");
6
+ if (!fs.existsSync(docsIssuesDir)) {
7
+ return findings;
8
+ }
9
+ const issueFiles = fs.readdirSync(docsIssuesDir).filter(f => f.endsWith(".md"));
10
+ for (const issueFile of issueFiles) {
11
+ const issuePath = path.join(docsIssuesDir, issueFile);
12
+ const content = fs.readFileSync(issuePath, "utf-8");
13
+ const hasStatus = /^(status|State):\s*/im.test(content);
14
+ const hasResolution = /^(resolution|Closed):\s*/im.test(content);
15
+ if (!hasStatus) {
16
+ findings.push({
17
+ severity: "P2",
18
+ message: `Issue ${issueFile} missing status field`,
19
+ file: `docs/issues/${issueFile}`,
20
+ blocking: false,
21
+ category: "doc_integrity",
22
+ problem_class: "unknown",
23
+ required_skills: [],
24
+ required_reads: [],
25
+ });
26
+ }
27
+ if (!hasResolution) {
28
+ findings.push({
29
+ severity: "P2",
30
+ message: `Issue ${issueFile} missing resolution/closed field`,
31
+ file: `docs/issues/${issueFile}`,
32
+ blocking: false,
33
+ category: "doc_integrity",
34
+ problem_class: "unknown",
35
+ required_skills: [],
36
+ required_reads: [],
37
+ });
38
+ }
39
+ }
40
+ return findings;
41
+ }
@@ -0,0 +1,6 @@
1
+ export function run(repoRoot, mode = "full") {
2
+ const findings = [];
3
+ if (mode !== "full" && mode !== "ci")
4
+ return findings;
5
+ return findings;
6
+ }
@@ -0,0 +1,48 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ const SENSITIVE_PATTERNS = [
4
+ { pattern: /api[_-]?key["\s:=]+["'][a-zA-Z0-9]{20,}["']/gi, severity: "P0" },
5
+ { pattern: /password["\s:=]+["'][^"']{8,}["']/gi, severity: "P0" },
6
+ { pattern: /secret["\s:=]+["'][a-zA-Z0-9]{16,}["']/gi, severity: "P0" },
7
+ { pattern: /token["\s:=]+["'][a-zA-Z0-9]{20,}["']/gi, severity: "P1" },
8
+ { pattern: /bearer\s+[a-zA-Z0-9]{20,}/gi, severity: "P1" },
9
+ ];
10
+ export function run(repoRoot, mode = "full") {
11
+ const findings = [];
12
+ if (mode !== "full" && mode !== "ci")
13
+ return findings;
14
+ const extensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".json", ".yaml", ".yml"];
15
+ function scanDir(dir) {
16
+ if (!fs.existsSync(dir))
17
+ return;
18
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
19
+ for (const entry of entries) {
20
+ const fullPath = path.join(dir, entry.name);
21
+ if (entry.isDirectory()) {
22
+ if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
23
+ scanDir(fullPath);
24
+ }
25
+ }
26
+ else if (extensions.includes(path.extname(entry.name))) {
27
+ const content = fs.readFileSync(fullPath, "utf-8");
28
+ for (const { pattern, severity } of SENSITIVE_PATTERNS) {
29
+ const matches = content.match(pattern);
30
+ if (matches) {
31
+ findings.push({
32
+ severity,
33
+ message: `Potential secret detected: ${matches[0].slice(0, 30)}...`,
34
+ file: path.relative(repoRoot, fullPath),
35
+ blocking: severity === "P0",
36
+ category: "security",
37
+ problem_class: "secret_exposure",
38
+ required_skills: [],
39
+ required_reads: [],
40
+ });
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ scanDir(repoRoot);
47
+ return findings;
48
+ }
@@ -0,0 +1,6 @@
1
+ export function run(repoRoot, mode = "full") {
2
+ const findings = [];
3
+ if (mode !== "full" && mode !== "ci")
4
+ return findings;
5
+ return findings;
6
+ }
@@ -0,0 +1,6 @@
1
+ export function run(repoRoot, mode = "full") {
2
+ const findings = [];
3
+ if (mode !== "full" && mode !== "ci")
4
+ return findings;
5
+ return findings;
6
+ }
@@ -0,0 +1,13 @@
1
+ export function createFinding(params) {
2
+ return {
3
+ severity: params.severity,
4
+ message: params.message,
5
+ file: params.file,
6
+ line: params.line,
7
+ blocking: params.blocking ?? false,
8
+ category: params.category ?? "general",
9
+ problem_class: params.problem_class ?? "unknown",
10
+ required_skills: params.required_skills ?? [],
11
+ required_reads: params.required_reads ?? [],
12
+ };
13
+ }
@@ -0,0 +1,20 @@
1
+ import { execSync } from "child_process";
2
+ const REPO_ROOT = process.cwd();
3
+ export function main() {
4
+ const args = process.argv.slice(2);
5
+ if (args[0] === "next") {
6
+ try {
7
+ const result = execSync("git log --oneline -1", { cwd: REPO_ROOT, encoding: "utf-8" });
8
+ const match = result.match(/ADR-(\d+)/);
9
+ if (match) {
10
+ const nextNum = parseInt(match[1], 10) + 1;
11
+ console.log(`ADR-${nextNum}`);
12
+ }
13
+ }
14
+ catch { }
15
+ }
16
+ process.exit(0);
17
+ }
18
+ if (require.main === module) {
19
+ main();
20
+ }
@@ -0,0 +1,6 @@
1
+ export function run(repoRoot, mode = "full") {
2
+ const findings = [];
3
+ if (mode !== "full" && mode !== "ci")
4
+ return findings;
5
+ return findings;
6
+ }
@@ -0,0 +1,8 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ console.log("Detecting rebase triggers...");
4
+ process.exit(0);
5
+ }
6
+ if (require.main === module) {
7
+ main();
8
+ }
@@ -0,0 +1,8 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ console.log("Scanning subprocess configurations...");
4
+ process.exit(0);
5
+ }
6
+ if (require.main === module) {
7
+ main();
8
+ }
@@ -0,0 +1,8 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ console.log("Scanning for artifact verification...");
4
+ process.exit(0);
5
+ }
6
+ if (require.main === module) {
7
+ main();
8
+ }
@@ -0,0 +1,8 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ console.log("Scanning YAML schemas...");
4
+ process.exit(0);
5
+ }
6
+ if (require.main === module) {
7
+ main();
8
+ }
@@ -0,0 +1,67 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export const FRAGMENTS_DIR = path.join(__dirname, "..", "context-fragments");
4
+ export const CONTEXT_MAP = {
5
+ "bridge_agent/": ["bridge-constitution"],
6
+ "backend/product/bridge/": ["bridge-constitution"],
7
+ "mcp-server/": ["mcp-parity"],
8
+ "mcp-server-node/": ["mcp-parity"],
9
+ "backend/product/routes/protocol.py": ["protocol-consumers", "contract-consumers"],
10
+ "backend/product/protocol/": ["protocol-consumers"],
11
+ "backend/product/routes/": ["contract-consumers"],
12
+ "backend/product/db/crud_events.py": ["run-events-consumers"],
13
+ "backend/product/auth/": ["auth-consumers"],
14
+ "backend/product/db/": ["db-shared-structures"],
15
+ "backend/product/catalyst/": ["catalyst-distributed"],
16
+ "docs/issues/": ["fixed-three-layers", "closure-checklist"],
17
+ "scenes/": ["scene-fidelity", "two-language"],
18
+ "website/app/[scene]/": ["scene-fidelity", "two-language"],
19
+ "website/components/scene/": ["scene-fidelity", "two-language"],
20
+ "Bolloon.md": ["truth-source-hierarchy"],
21
+ "MEMORY.md": ["truth-source-hierarchy"],
22
+ "docs/INDEX.md": ["truth-source-hierarchy"],
23
+ "mcp-server/pyproject.toml": ["version-sources"],
24
+ "mcp-server-node/package.json": ["version-sources"],
25
+ "website/": ["two-language"],
26
+ "docs/decisions/": ["artifact-linkage"],
27
+ "backend/product/": ["issue-first"],
28
+ "backend/server.py": ["issue-first"],
29
+ "mcp-server/boll_mcp/": ["issue-first"],
30
+ "mcp-server-node/src/": ["issue-first"],
31
+ "website/app/": ["issue-first"],
32
+ };
33
+ export const FALLBACK_FRAGMENTS = ["general-dev-principles"];
34
+ export function match(filePath) {
35
+ if (!filePath)
36
+ return [];
37
+ if (path.isAbsolute(filePath))
38
+ return [];
39
+ const normalized = path.normalize(filePath).replace(/\\/g, "/");
40
+ if (normalized.startsWith("../") || normalized === ".." || normalized.includes("/../")) {
41
+ return [];
42
+ }
43
+ const matched = [];
44
+ const sortedPatterns = Object.keys(CONTEXT_MAP).sort((a, b) => b.length - a.length);
45
+ for (const pattern of sortedPatterns) {
46
+ if (normalized.startsWith(pattern) || normalized.endsWith(pattern)) {
47
+ matched.push(...CONTEXT_MAP[pattern]);
48
+ }
49
+ }
50
+ return [...new Set(matched)];
51
+ }
52
+ export function loadFragment(name) {
53
+ if (!name)
54
+ return "";
55
+ const candidate = path.join(FRAGMENTS_DIR, `${name}.md`);
56
+ try {
57
+ const resolved = path.resolve(candidate);
58
+ const fragmentsDirResolved = path.resolve(FRAGMENTS_DIR);
59
+ if (!resolved.startsWith(fragmentsDirResolved))
60
+ return "";
61
+ if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {
62
+ return fs.readFileSync(resolved, "utf-8").trim();
63
+ }
64
+ }
65
+ catch { }
66
+ return "";
67
+ }