codeloop-mcp-server 0.1.63 → 0.1.64
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.
- package/dist/auth/critical_floors.d.ts.map +1 -1
- package/dist/auth/critical_floors.js +4 -0
- package/dist/auth/critical_floors.js.map +1 -1
- package/dist/auth/key_resolver.d.ts +55 -0
- package/dist/auth/key_resolver.d.ts.map +1 -0
- package/dist/auth/key_resolver.js +41 -0
- package/dist/auth/key_resolver.js.map +1 -0
- package/dist/auth/key_source.d.ts +60 -4
- package/dist/auth/key_source.d.ts.map +1 -1
- package/dist/auth/key_source.js +281 -48
- package/dist/auth/key_source.js.map +1 -1
- package/dist/evidence/observability.d.ts +67 -0
- package/dist/evidence/observability.d.ts.map +1 -0
- package/dist/evidence/observability.js +57 -0
- package/dist/evidence/observability.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -4
- package/dist/index.js.map +1 -1
- package/dist/runners/app_logger.d.ts.map +1 -1
- package/dist/runners/app_logger.js +31 -3
- package/dist/runners/app_logger.js.map +1 -1
- package/dist/runners/logging_readiness.d.ts +72 -0
- package/dist/runners/logging_readiness.d.ts.map +1 -0
- package/dist/runners/logging_readiness.js +419 -0
- package/dist/runners/logging_readiness.js.map +1 -0
- package/dist/runners/remote_logs.d.ts +105 -0
- package/dist/runners/remote_logs.d.ts.map +1 -0
- package/dist/runners/remote_logs.js +336 -0
- package/dist/runners/remote_logs.js.map +1 -0
- package/dist/tools/gate_check.d.ts.map +1 -1
- package/dist/tools/gate_check.js +25 -0
- package/dist/tools/gate_check.js.map +1 -1
- package/dist/tools/interaction_replay.d.ts +18 -0
- package/dist/tools/interaction_replay.d.ts.map +1 -1
- package/dist/tools/interaction_replay.js +102 -1
- package/dist/tools/interaction_replay.js.map +1 -1
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +61 -5
- package/dist/tools/verify.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.1.64 — Remote / hosting / third-party log collection via provider CLIs.
|
|
3
|
+
*
|
|
4
|
+
* Auto-detects the deploy targets + SaaS providers a project uses from its
|
|
5
|
+
* markers (config files, dependencies), and when the provider CLI is
|
|
6
|
+
* installed pulls the latest read-only logs into the run's logs/ dir. Those
|
|
7
|
+
* captured logs are then folded into runtime_log_scan so production / 3rd
|
|
8
|
+
* party errors flow through the same `runtime_log_clean_evidence` blocker as
|
|
9
|
+
* local logs. When a detected provider's CLI is missing, we surface a
|
|
10
|
+
* push-to-install directive.
|
|
11
|
+
*
|
|
12
|
+
* Safety: every command is a READ-ONLY `logs`-style subcommand run with a
|
|
13
|
+
* hard timeout. Streaming commands (wrangler tail, stripe logs tail, fly
|
|
14
|
+
* logs) are killed by the timeout and their partial output is captured.
|
|
15
|
+
*/
|
|
16
|
+
export interface RemoteLogProvider {
|
|
17
|
+
id: string;
|
|
18
|
+
displayName: string;
|
|
19
|
+
/** Default CLI binary to probe. */
|
|
20
|
+
cli: string;
|
|
21
|
+
/** Project markers that indicate this provider is in use. */
|
|
22
|
+
detect: (cwd: string) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Build the read-only logs command args. Return null when the command
|
|
25
|
+
* cannot be built without extra config (e.g. an AWS log-group name or a
|
|
26
|
+
* Vercel deployment URL) — the caller then asks the agent to configure it.
|
|
27
|
+
*/
|
|
28
|
+
logsArgs: (tail: number) => string[] | null;
|
|
29
|
+
/** Shown when the CLI is not installed. */
|
|
30
|
+
installHint: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CapturedRemoteLog {
|
|
33
|
+
id: string;
|
|
34
|
+
displayName: string;
|
|
35
|
+
path: string;
|
|
36
|
+
command: string;
|
|
37
|
+
}
|
|
38
|
+
export interface MissingRemoteCli {
|
|
39
|
+
id: string;
|
|
40
|
+
displayName: string;
|
|
41
|
+
cli: string;
|
|
42
|
+
install_hint: string;
|
|
43
|
+
}
|
|
44
|
+
export interface RemoteLogsEvidence {
|
|
45
|
+
generated_at: string;
|
|
46
|
+
enabled: boolean;
|
|
47
|
+
mode: "auto" | "configured" | "off";
|
|
48
|
+
/** Providers detected as in-use for this project. */
|
|
49
|
+
detected: string[];
|
|
50
|
+
captured: CapturedRemoteLog[];
|
|
51
|
+
/** Detected providers whose CLI is not installed — push the agent to install. */
|
|
52
|
+
missing_clis: MissingRemoteCli[];
|
|
53
|
+
/** Providers whose CLI is installed but reported an auth/login error. */
|
|
54
|
+
auth_needed: string[];
|
|
55
|
+
/** Providers detected but needing a logs_command override (target unknown). */
|
|
56
|
+
needs_config: string[];
|
|
57
|
+
reason?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface RemoteLogsConfig {
|
|
60
|
+
enabled?: boolean;
|
|
61
|
+
mode?: "auto" | "configured" | "off";
|
|
62
|
+
tail_lines?: number;
|
|
63
|
+
timeout_seconds?: number;
|
|
64
|
+
providers?: Array<{
|
|
65
|
+
id: string;
|
|
66
|
+
enabled?: boolean;
|
|
67
|
+
cli?: string;
|
|
68
|
+
logs_command?: string;
|
|
69
|
+
install_hint?: string;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Built-in provider registry. Covers the common deploy + SaaS targets; the
|
|
74
|
+
* long tail is handled via config.remote_logs.providers overrides.
|
|
75
|
+
*/
|
|
76
|
+
export declare const PROVIDER_REGISTRY: RemoteLogProvider[];
|
|
77
|
+
export interface ResolvedCandidate {
|
|
78
|
+
provider: RemoteLogProvider;
|
|
79
|
+
/** Effective CLI (config override wins). */
|
|
80
|
+
cli: string;
|
|
81
|
+
/** Full command override from config, if any (string form). */
|
|
82
|
+
commandOverride?: string;
|
|
83
|
+
installHint: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Pure: pick the candidate providers given the project, config, and registry.
|
|
87
|
+
* - mode "off" / enabled:false -> []
|
|
88
|
+
* - mode "configured" -> only providers explicitly listed in config (enabled).
|
|
89
|
+
* - mode "auto" (default) -> registry providers whose detect() matches, PLUS
|
|
90
|
+
* any explicitly-configured providers; config can disable a provider.
|
|
91
|
+
*/
|
|
92
|
+
export declare function selectRemoteLogCandidates(cwd: string, config: RemoteLogsConfig, registry?: RemoteLogProvider[]): ResolvedCandidate[];
|
|
93
|
+
/**
|
|
94
|
+
* Collect remote logs. Best-effort: never throws. Writes remote_logs.json
|
|
95
|
+
* into runDir and the per-provider logs into logDir.
|
|
96
|
+
*/
|
|
97
|
+
export declare function collectRemoteLogs(cwd: string, config: RemoteLogsConfig, logDir: string): Promise<RemoteLogsEvidence>;
|
|
98
|
+
export declare function writeRemoteLogsEvidence(runDir: string, ev: RemoteLogsEvidence): void;
|
|
99
|
+
export declare function loadRemoteLogsEvidence(runDir: string): RemoteLogsEvidence | null;
|
|
100
|
+
/** Captured remote log files in a run's logs dir, for runtime_log_scan. */
|
|
101
|
+
export declare function listCapturedRemoteLogs(logDir: string): Array<{
|
|
102
|
+
source: string;
|
|
103
|
+
path: string;
|
|
104
|
+
}>;
|
|
105
|
+
//# sourceMappingURL=remote_logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote_logs.d.ts","sourceRoot":"","sources":["../../src/runners/remote_logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { checkToolAvailable, runCommand } from "./base.js";
|
|
4
|
+
const FILE = "remote_logs.json";
|
|
5
|
+
function fileExists(cwd, ...names) {
|
|
6
|
+
return names.some((n) => existsSync(join(cwd, n)));
|
|
7
|
+
}
|
|
8
|
+
function pkgIncludes(cwd, re) {
|
|
9
|
+
try {
|
|
10
|
+
const p = join(cwd, "package.json");
|
|
11
|
+
return existsSync(p) && re.test(readFileSync(p, "utf-8"));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function hasEnvRef(cwd, re) {
|
|
18
|
+
for (const f of [".env", ".env.local", ".env.production"]) {
|
|
19
|
+
try {
|
|
20
|
+
const p = join(cwd, f);
|
|
21
|
+
if (existsSync(p) && re.test(readFileSync(p, "utf-8")))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
/* ignore */
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Built-in provider registry. Covers the common deploy + SaaS targets; the
|
|
32
|
+
* long tail is handled via config.remote_logs.providers overrides.
|
|
33
|
+
*/
|
|
34
|
+
export const PROVIDER_REGISTRY = [
|
|
35
|
+
{
|
|
36
|
+
id: "vercel",
|
|
37
|
+
displayName: "Vercel",
|
|
38
|
+
cli: "vercel",
|
|
39
|
+
detect: (cwd) => fileExists(cwd, "vercel.json", ".vercel") || pkgIncludes(cwd, /"vercel"/),
|
|
40
|
+
logsArgs: () => null, // `vercel logs <deployment-url>` needs a target
|
|
41
|
+
installHint: "npm i -g vercel (then `vercel login`)",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "netlify",
|
|
45
|
+
displayName: "Netlify",
|
|
46
|
+
cli: "netlify",
|
|
47
|
+
detect: (cwd) => fileExists(cwd, "netlify.toml", ".netlify"),
|
|
48
|
+
logsArgs: () => null, // `netlify logs:function <name>` needs a function target
|
|
49
|
+
installHint: "npm i -g netlify-cli (then `netlify login`)",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "heroku",
|
|
53
|
+
displayName: "Heroku",
|
|
54
|
+
cli: "heroku",
|
|
55
|
+
detect: (cwd) => fileExists(cwd, "Procfile", "app.json") || hasGitRemoteMatch(cwd, /heroku/),
|
|
56
|
+
logsArgs: (tail) => ["logs", "-n", String(tail)],
|
|
57
|
+
installHint: "https://devcenter.heroku.com/articles/heroku-cli (then `heroku login`)",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "fly",
|
|
61
|
+
displayName: "Fly.io",
|
|
62
|
+
cli: "fly",
|
|
63
|
+
detect: (cwd) => fileExists(cwd, "fly.toml"),
|
|
64
|
+
logsArgs: () => ["logs"], // streams; killed by timeout, partial output captured
|
|
65
|
+
installHint: "https://fly.io/docs/flyctl/install/ (then `fly auth login`)",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "railway",
|
|
69
|
+
displayName: "Railway",
|
|
70
|
+
cli: "railway",
|
|
71
|
+
detect: (cwd) => fileExists(cwd, "railway.json", "railway.toml"),
|
|
72
|
+
logsArgs: () => ["logs"],
|
|
73
|
+
installHint: "npm i -g @railway/cli (then `railway login`)",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "render",
|
|
77
|
+
displayName: "Render",
|
|
78
|
+
cli: "render",
|
|
79
|
+
detect: (cwd) => fileExists(cwd, "render.yaml"),
|
|
80
|
+
logsArgs: () => null, // needs a service id
|
|
81
|
+
installHint: "https://render.com/docs/cli (then `render login`)",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "cloudflare",
|
|
85
|
+
displayName: "Cloudflare Workers",
|
|
86
|
+
cli: "wrangler",
|
|
87
|
+
detect: (cwd) => fileExists(cwd, "wrangler.toml", "wrangler.jsonc", "wrangler.json"),
|
|
88
|
+
logsArgs: () => ["tail", "--format", "json"], // streams; killed by timeout
|
|
89
|
+
installHint: "npm i -g wrangler (then `wrangler login`)",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "firebase",
|
|
93
|
+
displayName: "Firebase",
|
|
94
|
+
cli: "firebase",
|
|
95
|
+
detect: (cwd) => fileExists(cwd, "firebase.json", ".firebaserc"),
|
|
96
|
+
logsArgs: (tail) => ["functions:log", "-n", String(tail)],
|
|
97
|
+
installHint: "npm i -g firebase-tools (then `firebase login`)",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "gcloud",
|
|
101
|
+
displayName: "Google Cloud",
|
|
102
|
+
cli: "gcloud",
|
|
103
|
+
detect: (cwd) => fileExists(cwd, "app.yaml", ".gcloudignore", "cloudbuild.yaml"),
|
|
104
|
+
logsArgs: (tail) => ["logging", "read", "severity>=ERROR", "--limit", String(tail), "--freshness=1d"],
|
|
105
|
+
installHint: "https://cloud.google.com/sdk/docs/install (then `gcloud auth login`)",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "aws",
|
|
109
|
+
displayName: "AWS CloudWatch",
|
|
110
|
+
cli: "aws",
|
|
111
|
+
detect: (cwd) => fileExists(cwd, "serverless.yml", "serverless.yaml", "samconfig.toml", "template.yaml", "cdk.json"),
|
|
112
|
+
logsArgs: () => null, // `aws logs tail <log-group>` needs the group name
|
|
113
|
+
installHint: "https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html (then `aws configure`)",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: "supabase",
|
|
117
|
+
displayName: "Supabase",
|
|
118
|
+
cli: "supabase",
|
|
119
|
+
detect: (cwd) => fileExists(cwd, "supabase") || pkgIncludes(cwd, /"@supabase\/supabase-js"/),
|
|
120
|
+
logsArgs: () => null,
|
|
121
|
+
installHint: "npm i -g supabase (then `supabase login`)",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "stripe",
|
|
125
|
+
displayName: "Stripe",
|
|
126
|
+
cli: "stripe",
|
|
127
|
+
detect: (cwd) => pkgIncludes(cwd, /"stripe"/) || hasEnvRef(cwd, /STRIPE_(SECRET|API)_KEY/),
|
|
128
|
+
logsArgs: () => ["logs", "tail"], // streams; killed by timeout
|
|
129
|
+
installHint: "https://stripe.com/docs/stripe-cli (then `stripe login`)",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "convex",
|
|
133
|
+
displayName: "Convex",
|
|
134
|
+
cli: "convex",
|
|
135
|
+
detect: (cwd) => fileExists(cwd, "convex") || pkgIncludes(cwd, /"convex"/),
|
|
136
|
+
logsArgs: () => ["logs"],
|
|
137
|
+
installHint: "npm i -g convex (then `npx convex login`)",
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
function hasGitRemoteMatch(cwd, re) {
|
|
141
|
+
try {
|
|
142
|
+
const cfg = join(cwd, ".git", "config");
|
|
143
|
+
return existsSync(cfg) && re.test(readFileSync(cfg, "utf-8"));
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Pure: pick the candidate providers given the project, config, and registry.
|
|
151
|
+
* - mode "off" / enabled:false -> []
|
|
152
|
+
* - mode "configured" -> only providers explicitly listed in config (enabled).
|
|
153
|
+
* - mode "auto" (default) -> registry providers whose detect() matches, PLUS
|
|
154
|
+
* any explicitly-configured providers; config can disable a provider.
|
|
155
|
+
*/
|
|
156
|
+
export function selectRemoteLogCandidates(cwd, config, registry = PROVIDER_REGISTRY) {
|
|
157
|
+
if (config.enabled === false || config.mode === "off")
|
|
158
|
+
return [];
|
|
159
|
+
const mode = config.mode ?? "auto";
|
|
160
|
+
const overrides = new Map((config.providers ?? []).map((p) => [p.id, p]));
|
|
161
|
+
const byId = new Map(registry.map((p) => [p.id, p]));
|
|
162
|
+
const out = [];
|
|
163
|
+
const seen = new Set();
|
|
164
|
+
const pushCandidate = (provider) => {
|
|
165
|
+
if (seen.has(provider.id))
|
|
166
|
+
return;
|
|
167
|
+
const ov = overrides.get(provider.id);
|
|
168
|
+
if (ov?.enabled === false)
|
|
169
|
+
return;
|
|
170
|
+
seen.add(provider.id);
|
|
171
|
+
out.push({
|
|
172
|
+
provider,
|
|
173
|
+
cli: ov?.cli ?? provider.cli,
|
|
174
|
+
commandOverride: ov?.logs_command,
|
|
175
|
+
installHint: ov?.install_hint ?? provider.installHint,
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
if (mode === "auto") {
|
|
179
|
+
for (const provider of registry) {
|
|
180
|
+
try {
|
|
181
|
+
if (provider.detect(cwd))
|
|
182
|
+
pushCandidate(provider);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
/* detect is best-effort */
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Explicitly-configured providers are always candidates (both modes).
|
|
190
|
+
for (const ov of config.providers ?? []) {
|
|
191
|
+
if (ov.enabled === false)
|
|
192
|
+
continue;
|
|
193
|
+
const known = byId.get(ov.id);
|
|
194
|
+
if (known) {
|
|
195
|
+
pushCandidate(known);
|
|
196
|
+
}
|
|
197
|
+
else if (ov.cli || ov.logs_command) {
|
|
198
|
+
// Custom provider not in the registry — long-tail CLI support.
|
|
199
|
+
seen.add(ov.id);
|
|
200
|
+
out.push({
|
|
201
|
+
provider: {
|
|
202
|
+
id: ov.id,
|
|
203
|
+
displayName: ov.id,
|
|
204
|
+
cli: ov.cli ?? ov.id,
|
|
205
|
+
detect: () => true,
|
|
206
|
+
logsArgs: () => null,
|
|
207
|
+
installHint: ov.install_hint ?? `install the ${ov.id} CLI`,
|
|
208
|
+
},
|
|
209
|
+
cli: ov.cli ?? ov.id,
|
|
210
|
+
commandOverride: ov.logs_command,
|
|
211
|
+
installHint: ov.install_hint ?? `install the ${ov.id} CLI`,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
const AUTH_ERROR_RE = /(not (logged in|authenticated)|unauthorized|please (log|sign) ?in|run `?\w+ login|no active account|credentials? (not|missing)|401 )/i;
|
|
218
|
+
/**
|
|
219
|
+
* Collect remote logs. Best-effort: never throws. Writes remote_logs.json
|
|
220
|
+
* into runDir and the per-provider logs into logDir.
|
|
221
|
+
*/
|
|
222
|
+
export async function collectRemoteLogs(cwd, config, logDir) {
|
|
223
|
+
const mode = config.mode ?? "auto";
|
|
224
|
+
const ev = {
|
|
225
|
+
generated_at: new Date().toISOString(),
|
|
226
|
+
enabled: config.enabled !== false && mode !== "off",
|
|
227
|
+
mode,
|
|
228
|
+
detected: [],
|
|
229
|
+
captured: [],
|
|
230
|
+
missing_clis: [],
|
|
231
|
+
auth_needed: [],
|
|
232
|
+
needs_config: [],
|
|
233
|
+
};
|
|
234
|
+
if (!ev.enabled) {
|
|
235
|
+
ev.reason = "remote log collection disabled in config";
|
|
236
|
+
return ev;
|
|
237
|
+
}
|
|
238
|
+
const tail = config.tail_lines ?? 200;
|
|
239
|
+
const timeoutMs = (config.timeout_seconds ?? 25) * 1000;
|
|
240
|
+
let candidates;
|
|
241
|
+
try {
|
|
242
|
+
candidates = selectRemoteLogCandidates(cwd, config);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
candidates = [];
|
|
246
|
+
}
|
|
247
|
+
ev.detected = candidates.map((c) => c.provider.id);
|
|
248
|
+
for (const cand of candidates) {
|
|
249
|
+
try {
|
|
250
|
+
const installed = await checkToolAvailable(cand.cli);
|
|
251
|
+
if (!installed) {
|
|
252
|
+
ev.missing_clis.push({
|
|
253
|
+
id: cand.provider.id,
|
|
254
|
+
displayName: cand.provider.displayName,
|
|
255
|
+
cli: cand.cli,
|
|
256
|
+
install_hint: cand.installHint,
|
|
257
|
+
});
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
let cmd;
|
|
261
|
+
let args;
|
|
262
|
+
if (cand.commandOverride) {
|
|
263
|
+
const parts = cand.commandOverride.split(/\s+/).filter(Boolean);
|
|
264
|
+
cmd = parts[0];
|
|
265
|
+
args = parts.slice(1);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
const a = cand.provider.logsArgs(tail);
|
|
269
|
+
if (!a) {
|
|
270
|
+
ev.needs_config.push(cand.provider.id);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
cmd = cand.cli;
|
|
274
|
+
args = a;
|
|
275
|
+
}
|
|
276
|
+
mkdirSync(logDir, { recursive: true });
|
|
277
|
+
const outPath = join(logDir, `remote_${cand.provider.id}.log`);
|
|
278
|
+
const res = await runCommand(cmd, args, cwd, undefined, undefined, timeoutMs);
|
|
279
|
+
const body = `$ ${cmd} ${args.join(" ")}\nexit_code: ${res.exit_code}\n\n${res.stdout}\n${res.stderr}\n`;
|
|
280
|
+
try {
|
|
281
|
+
writeFileSync(outPath, body, "utf-8");
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
/* best-effort */
|
|
285
|
+
}
|
|
286
|
+
if (AUTH_ERROR_RE.test(res.stderr) || AUTH_ERROR_RE.test(res.stdout)) {
|
|
287
|
+
ev.auth_needed.push(cand.provider.id);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
ev.captured.push({
|
|
291
|
+
id: cand.provider.id,
|
|
292
|
+
displayName: cand.provider.displayName,
|
|
293
|
+
path: outPath,
|
|
294
|
+
command: `${cmd} ${args.join(" ")}`,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
/* one provider failing must never break the others or verify */
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return ev;
|
|
302
|
+
}
|
|
303
|
+
export function writeRemoteLogsEvidence(runDir, ev) {
|
|
304
|
+
try {
|
|
305
|
+
mkdirSync(runDir, { recursive: true });
|
|
306
|
+
writeFileSync(join(runDir, FILE), JSON.stringify(ev, null, 2), "utf-8");
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
/* best-effort */
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
export function loadRemoteLogsEvidence(runDir) {
|
|
313
|
+
const p = join(runDir, FILE);
|
|
314
|
+
if (!existsSync(p))
|
|
315
|
+
return null;
|
|
316
|
+
try {
|
|
317
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/** Captured remote log files in a run's logs dir, for runtime_log_scan. */
|
|
324
|
+
export function listCapturedRemoteLogs(logDir) {
|
|
325
|
+
if (!existsSync(logDir))
|
|
326
|
+
return [];
|
|
327
|
+
try {
|
|
328
|
+
return readdirSync(logDir)
|
|
329
|
+
.filter((f) => f.startsWith("remote_") && f.endsWith(".log"))
|
|
330
|
+
.map((f) => ({ source: f.replace(/\.log$/, ""), path: join(logDir, f) }));
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=remote_logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote_logs.js","sourceRoot":"","sources":["../../src/runners/remote_logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate_check.d.ts","sourceRoot":"","sources":["../../src/tools/gate_check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,cAAc,EAEf,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"gate_check.d.ts","sourceRoot":"","sources":["../../src/tools/gate_check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,cAAc,EAEf,MAAM,sBAAsB,CAAC;AA4D9B,wBAAsB,YAAY,CAChC,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,EACtB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,eAAe,CAAC,CAwG1B;AAyED,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/tools/gate_check.js
CHANGED
|
@@ -12,6 +12,7 @@ import { loadCycleIssues, summariseCycleIssue, } from "../evidence/cycle_issues.
|
|
|
12
12
|
import { loadCodeQualityEvidence, evaluateStaticAnalysisGate, evaluateCoverageGate, resolveCoverageThreshold, } from "../evidence/deep_internal.js";
|
|
13
13
|
import { loadBackendVerification, evaluateBackendSmokeGate, evaluateApiContractGate, evaluateDbSchemaGate, } from "../evidence/backend_verification.js";
|
|
14
14
|
import { loadRuntimeLogScan, evaluateRuntimeLogGate, } from "../evidence/runtime_log_scan.js";
|
|
15
|
+
import { loadObservabilityEvidence, evaluateObservabilityGate, } from "../evidence/observability.js";
|
|
15
16
|
export async function runGateCheck(input, config, cwd = process.cwd()) {
|
|
16
17
|
const baseDir = getArtifactsBaseDir(cwd);
|
|
17
18
|
const meta = loadRunMeta(input.run_id, baseDir);
|
|
@@ -153,6 +154,8 @@ function nextStepForGate(name, reason, cwd) {
|
|
|
153
154
|
return `API responses violate the declared contract (${reason}). Reconcile the route handlers with the OpenAPI/Swagger schema (or update the schema if the change is intentional), then call codeloop_verify.`;
|
|
154
155
|
case "db_schema_evidence":
|
|
155
156
|
return `Database schema drift or a failed migration (${reason}). Generate + apply the pending migration for your ORM (dotnet ef migrations add / Django makemigrations / alembic revision --autogenerate / prisma migrate dev / rails db:migrate), then call codeloop_verify.`;
|
|
157
|
+
case "logging_observability_evidence":
|
|
158
|
+
return `The project lacks a logging system (${reason}). Read artifacts/runs/<latest>/observability.json for the per-stack recommendations, then BUILD the missing piece(s): (1) a structured, leveled logger (pino/winston, Python logging/loguru, Serilog/ILogger, slog/zap, tracing) wired through the app instead of bare console/print; (2) request/HTTP logging middleware on servers (method, path, status, latency); (3) a global error handler / React error boundary that logs the full stack trace at the boundary. Persist logs to ./logs when observability.require_log_sink is on. Then call codeloop_verify. Per-project tuning lives in .codeloop/config.json -> observability.`;
|
|
156
159
|
default:
|
|
157
160
|
return `Inspect ${cwd}/artifacts/runs/<latest>/meta.json and the gate's evidence_path; address the specific issue, then call codeloop_gate_check again.`;
|
|
158
161
|
}
|
|
@@ -723,6 +726,28 @@ function evaluateDeepInternalGates(runId, cwd, config) {
|
|
|
723
726
|
};
|
|
724
727
|
const logVerdict = evaluateRuntimeLogGate(logScan);
|
|
725
728
|
results.push({ gate: runtimeLogGate, passed: logVerdict.passed, reason: logVerdict.reason });
|
|
729
|
+
// ── logging_observability_evidence (0.1.64) ──────────────────────
|
|
730
|
+
// The project must HAVE a logging system (logger + request logging +
|
|
731
|
+
// global error handler, per stack/kind), not just emit clean logs. The
|
|
732
|
+
// gate severity is taken from the evidence (config-driven; default
|
|
733
|
+
// blocker). Disabled entirely via config.observability.enabled=false,
|
|
734
|
+
// in which case verify writes no evidence and the gate passes as n/a.
|
|
735
|
+
const obsCfgEnabled = config.observability?.enabled !== false;
|
|
736
|
+
if (obsCfgEnabled) {
|
|
737
|
+
const obs = loadObservabilityEvidence(runDir);
|
|
738
|
+
const obsGate = {
|
|
739
|
+
name: "logging_observability_evidence",
|
|
740
|
+
description: "Project must have a logging system (logger, request logging, global error handler) so runtime faults are catchable.",
|
|
741
|
+
rule: "observability.json missing_required is empty (n/a when no instrumentable app source)",
|
|
742
|
+
input_artifacts: ["observability.json"],
|
|
743
|
+
pass_threshold: true,
|
|
744
|
+
severity_if_failed: obs?.severity === "warning" ? "warning" : "blocker",
|
|
745
|
+
retry_allowance: 5,
|
|
746
|
+
escalation_condition: "Logging system still missing after 5 attempts",
|
|
747
|
+
};
|
|
748
|
+
const obsVerdict = evaluateObservabilityGate(obs);
|
|
749
|
+
results.push({ gate: obsGate, passed: obsVerdict.passed, reason: obsVerdict.reason });
|
|
750
|
+
}
|
|
726
751
|
return results;
|
|
727
752
|
}
|
|
728
753
|
function evaluateGate(gate, meta, config, specContent, acceptanceContent, cwd) {
|