@fro.bot/systematic 3.15.0 → 3.15.1
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/cli.js +147 -94
- package/dist/index-7cyxcwf5.js +8486 -0
- package/dist/index.js +127 -124
- package/dist/pi.js +23 -7
- package/package.json +6 -6
- package/skills/ce-review/references/review-summary-schema.json +1 -1
- package/dist/index-0stf3ag0.js +0 -17100
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @bun
|
|
3
3
|
import {
|
|
4
|
+
parseFrontmatter,
|
|
5
|
+
parse,
|
|
6
|
+
parseTree,
|
|
7
|
+
modify,
|
|
4
8
|
applyEdits,
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
_isoDateTime,
|
|
10
|
+
_isoDate,
|
|
11
|
+
_isoTime,
|
|
12
|
+
_isoDuration,
|
|
13
|
+
string,
|
|
14
|
+
ZodISODateTime,
|
|
15
|
+
ZodISODate,
|
|
16
|
+
ZodISOTime,
|
|
17
|
+
ZodISODuration,
|
|
18
|
+
number,
|
|
19
|
+
boolean,
|
|
20
|
+
array,
|
|
21
|
+
object,
|
|
22
|
+
union,
|
|
23
|
+
discriminatedUnion,
|
|
24
|
+
_enum,
|
|
25
|
+
literal,
|
|
26
|
+
loadConfigWithSources,
|
|
27
|
+
getConfigPaths,
|
|
7
28
|
extractString,
|
|
8
29
|
findAgentsInDir,
|
|
9
30
|
findCommandsInDir,
|
|
10
31
|
findSkillsInDir,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
32
|
+
discoverSkills
|
|
33
|
+
} from "./index-7cyxcwf5.js";
|
|
34
|
+
var __defProp = Object.defineProperty;
|
|
35
|
+
var __returnValue = (v) => v;
|
|
36
|
+
function __exportSetter(name, newValue) {
|
|
37
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
38
|
+
}
|
|
39
|
+
var __export = (target, all) => {
|
|
40
|
+
for (var name in all)
|
|
41
|
+
__defProp(target, name, {
|
|
42
|
+
get: all[name],
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
set: __exportSetter.bind(all, name)
|
|
46
|
+
});
|
|
47
|
+
};
|
|
18
48
|
|
|
19
49
|
// src/cli.ts
|
|
20
50
|
import fs6 from "fs";
|
|
@@ -778,7 +808,30 @@ function buildCapabilitySnapshot(options) {
|
|
|
778
808
|
options.outputSink?.(serialized);
|
|
779
809
|
return snapshot;
|
|
780
810
|
}
|
|
781
|
-
|
|
811
|
+
// node_modules/.bun/zod@4.5.4/node_modules/zod/v4/classic/iso.js
|
|
812
|
+
var exports_iso = {};
|
|
813
|
+
__export(exports_iso, {
|
|
814
|
+
ZodISODate: () => ZodISODate,
|
|
815
|
+
ZodISODateTime: () => ZodISODateTime,
|
|
816
|
+
ZodISODuration: () => ZodISODuration,
|
|
817
|
+
ZodISOTime: () => ZodISOTime,
|
|
818
|
+
date: () => date,
|
|
819
|
+
datetime: () => datetime,
|
|
820
|
+
duration: () => duration,
|
|
821
|
+
time: () => time
|
|
822
|
+
});
|
|
823
|
+
function datetime(params) {
|
|
824
|
+
return _isoDateTime(ZodISODateTime, params);
|
|
825
|
+
}
|
|
826
|
+
function date(params) {
|
|
827
|
+
return _isoDate(ZodISODate, params);
|
|
828
|
+
}
|
|
829
|
+
function time(params) {
|
|
830
|
+
return _isoTime(ZodISOTime, params);
|
|
831
|
+
}
|
|
832
|
+
function duration(params) {
|
|
833
|
+
return _isoDuration(ZodISODuration, params);
|
|
834
|
+
}
|
|
782
835
|
// src/lib/pi-subagents-export.ts
|
|
783
836
|
import * as crypto2 from "crypto";
|
|
784
837
|
import * as fs3 from "fs";
|
|
@@ -1424,10 +1477,10 @@ function ownedFilenames(manifest) {
|
|
|
1424
1477
|
function parseSourceCategoryAndKey(sourceRelPath) {
|
|
1425
1478
|
const parts = sourceRelPath.split("/");
|
|
1426
1479
|
if (parts.length >= 3 && parts[0] === "agents") {
|
|
1427
|
-
const
|
|
1480
|
+
const fileName = parts.at(-1) ?? "";
|
|
1428
1481
|
return {
|
|
1429
1482
|
category: parts[1],
|
|
1430
|
-
agentKey:
|
|
1483
|
+
agentKey: fileName.replace(/\.md$/, "")
|
|
1431
1484
|
};
|
|
1432
1485
|
}
|
|
1433
1486
|
const fileName = parts.at(-1) ?? sourceRelPath;
|
|
@@ -1949,7 +2002,7 @@ function cleanup(agentsRoot, configOptions) {
|
|
|
1949
2002
|
...targets.map((t) => t.path),
|
|
1950
2003
|
...manifestPath ? [manifestPath] : []
|
|
1951
2004
|
];
|
|
1952
|
-
const
|
|
2005
|
+
const tx = runWithRollback(pathsToWatch, [
|
|
1953
2006
|
...targets.map(({ path: p, filename, hash }) => () => {
|
|
1954
2007
|
if (fs3.existsSync(p)) {
|
|
1955
2008
|
assertHashMatchesOrThrow(p, hash, filename, "delete");
|
|
@@ -1963,7 +2016,7 @@ function cleanup(agentsRoot, configOptions) {
|
|
|
1963
2016
|
}
|
|
1964
2017
|
] : []
|
|
1965
2018
|
]);
|
|
1966
|
-
return { kind: "tx", tx
|
|
2019
|
+
return { kind: "tx", tx };
|
|
1967
2020
|
});
|
|
1968
2021
|
if (!lockResult.locked) {
|
|
1969
2022
|
if (lockResult.isContention)
|
|
@@ -2010,8 +2063,8 @@ function hasParentDirectoryTraversal(input) {
|
|
|
2010
2063
|
}
|
|
2011
2064
|
function pathContainsSymlink(candidate) {
|
|
2012
2065
|
let current = path3.parse(candidate).root;
|
|
2013
|
-
const
|
|
2014
|
-
for (const segment of
|
|
2066
|
+
const relative = path3.relative(current, candidate);
|
|
2067
|
+
for (const segment of relative.split(path3.sep)) {
|
|
2015
2068
|
if (!segment)
|
|
2016
2069
|
continue;
|
|
2017
2070
|
current = path3.join(current, segment);
|
|
@@ -2025,8 +2078,8 @@ function pathContainsSymlink(candidate) {
|
|
|
2025
2078
|
return false;
|
|
2026
2079
|
}
|
|
2027
2080
|
function isWithinDirectory(candidate, directory) {
|
|
2028
|
-
const
|
|
2029
|
-
return
|
|
2081
|
+
const relative = path3.relative(directory, candidate);
|
|
2082
|
+
return relative !== "" && relative !== ".." && !relative.startsWith(`..${path3.sep}`) && !path3.isAbsolute(relative);
|
|
2030
2083
|
}
|
|
2031
2084
|
function resolveReviewArtifactPath(input, cwd) {
|
|
2032
2085
|
if (hasParentDirectoryTraversal(input)) {
|
|
@@ -2096,14 +2149,14 @@ var REVIEW_ARTIFACT_CUSTOM_MESSAGES = [
|
|
|
2096
2149
|
"unsatisfied risk coverage must not cite an input finding ID",
|
|
2097
2150
|
"passed validation must not include a reason; non-passed validation requires a reason"
|
|
2098
2151
|
];
|
|
2099
|
-
var boundedText = (maxLength) =>
|
|
2100
|
-
var DispatchOutcomeSchema =
|
|
2152
|
+
var boundedText = (maxLength) => string().min(1).max(maxLength).regex(/\S/);
|
|
2153
|
+
var DispatchOutcomeSchema = _enum([
|
|
2101
2154
|
"findings",
|
|
2102
2155
|
"empty",
|
|
2103
2156
|
"malformed",
|
|
2104
2157
|
"never_returned"
|
|
2105
2158
|
]);
|
|
2106
|
-
var DispositionSchema =
|
|
2159
|
+
var DispositionSchema = _enum([
|
|
2107
2160
|
"surviving",
|
|
2108
2161
|
"merged",
|
|
2109
2162
|
"suppressed",
|
|
@@ -2111,12 +2164,12 @@ var DispositionSchema = exports_external.enum([
|
|
|
2111
2164
|
"rejected"
|
|
2112
2165
|
]);
|
|
2113
2166
|
var AdmittedDispositionSchema = DispositionSchema.exclude(["rejected"]);
|
|
2114
|
-
var HarnessSchema =
|
|
2167
|
+
var HarnessSchema = _enum(["opencode", "pi", "claude-code"]);
|
|
2115
2168
|
var RepoRelativePathSchema = boundedText(256).regex(/^(?!\/)(?![A-Za-z]:[\\/])(?!\\).+/);
|
|
2116
2169
|
var ReviewerSchema = boundedText(MAX_REVIEWER_LENGTH);
|
|
2117
|
-
var BranchSchema =
|
|
2118
|
-
var HeadShaSchema =
|
|
2119
|
-
var CompletedAtSchema =
|
|
2170
|
+
var BranchSchema = string().max(MAX_BRANCH_LENGTH);
|
|
2171
|
+
var HeadShaSchema = string().regex(/^[0-9a-f]{40}$/);
|
|
2172
|
+
var CompletedAtSchema = exports_iso.datetime({ offset: false });
|
|
2120
2173
|
var ReasonSchema = boundedText(MAX_REASON_LENGTH);
|
|
2121
2174
|
var RISK_CRITICAL_PERSONAS = [
|
|
2122
2175
|
"security",
|
|
@@ -2125,42 +2178,42 @@ var RISK_CRITICAL_PERSONAS = [
|
|
|
2125
2178
|
"reliability",
|
|
2126
2179
|
"performance"
|
|
2127
2180
|
];
|
|
2128
|
-
var RiskCriticalPersonaSchema =
|
|
2181
|
+
var RiskCriticalPersonaSchema = _enum(RISK_CRITICAL_PERSONAS);
|
|
2129
2182
|
var FindingTitleSchema = boundedText(256);
|
|
2130
|
-
var SeveritySchema =
|
|
2183
|
+
var SeveritySchema = _enum(["P0", "P1", "P2", "P3", "unknown"]);
|
|
2131
2184
|
var FindingSeveritySchema = SeveritySchema.exclude(["unknown"]);
|
|
2132
|
-
var AutofixClassSchema =
|
|
2185
|
+
var AutofixClassSchema = _enum([
|
|
2133
2186
|
"safe_auto",
|
|
2134
2187
|
"gated_auto",
|
|
2135
2188
|
"manual",
|
|
2136
2189
|
"advisory"
|
|
2137
2190
|
]);
|
|
2138
|
-
var OwnerSchema =
|
|
2191
|
+
var OwnerSchema = _enum([
|
|
2139
2192
|
"review-fixer",
|
|
2140
2193
|
"downstream-resolver",
|
|
2141
2194
|
"human",
|
|
2142
2195
|
"release"
|
|
2143
2196
|
]);
|
|
2144
2197
|
var BoundedEvidenceStringSchema = boundedText(500).regex(/^(?!\/)(?![A-Za-z]:[\\/])(?!\\).+/);
|
|
2145
|
-
var OverflowEvidenceSchema =
|
|
2146
|
-
overflow:
|
|
2198
|
+
var OverflowEvidenceSchema = object({
|
|
2199
|
+
overflow: literal(true),
|
|
2147
2200
|
excerpt: BoundedEvidenceStringSchema
|
|
2148
2201
|
}).strict();
|
|
2149
|
-
var EvidenceSchema =
|
|
2150
|
-
var AdmittedInputFindingSchema =
|
|
2151
|
-
record_type:
|
|
2202
|
+
var EvidenceSchema = array(union([BoundedEvidenceStringSchema, OverflowEvidenceSchema])).min(1).max(5);
|
|
2203
|
+
var AdmittedInputFindingSchema = object({
|
|
2204
|
+
record_type: literal("admitted"),
|
|
2152
2205
|
input_id: boundedText(MAX_INPUT_ID_LENGTH),
|
|
2153
2206
|
reviewer: ReviewerSchema,
|
|
2154
|
-
confidence:
|
|
2207
|
+
confidence: number().min(0).max(1),
|
|
2155
2208
|
disposition: AdmittedDispositionSchema,
|
|
2156
2209
|
reason: ReasonSchema
|
|
2157
2210
|
}).strict();
|
|
2158
|
-
var RejectedInputFindingSchema =
|
|
2159
|
-
record_type:
|
|
2211
|
+
var RejectedInputFindingSchema = object({
|
|
2212
|
+
record_type: literal("rejected_summary"),
|
|
2160
2213
|
reviewer: ReviewerSchema,
|
|
2161
2214
|
dispatch_outcome: DispatchOutcomeSchema,
|
|
2162
|
-
rejected_finding_count:
|
|
2163
|
-
rejected_severities:
|
|
2215
|
+
rejected_finding_count: number().int().positive().max(MAX_FINDINGS),
|
|
2216
|
+
rejected_severities: array(SeveritySchema).max(MAX_FINDINGS),
|
|
2164
2217
|
disposition: DispositionSchema.extract(["rejected"]),
|
|
2165
2218
|
reason: ReasonSchema
|
|
2166
2219
|
}).strict().superRefine((row, ctx) => {
|
|
@@ -2172,31 +2225,31 @@ var RejectedInputFindingSchema = exports_external.object({
|
|
|
2172
2225
|
});
|
|
2173
2226
|
}
|
|
2174
2227
|
});
|
|
2175
|
-
var InputFindingSchema =
|
|
2228
|
+
var InputFindingSchema = discriminatedUnion("record_type", [
|
|
2176
2229
|
AdmittedInputFindingSchema,
|
|
2177
2230
|
RejectedInputFindingSchema
|
|
2178
2231
|
]);
|
|
2179
|
-
var ProvenanceSchema =
|
|
2232
|
+
var ProvenanceSchema = object({
|
|
2180
2233
|
fingerprint: boundedText(512),
|
|
2181
|
-
submitters:
|
|
2182
|
-
agreement_credit:
|
|
2234
|
+
submitters: array(ReviewerSchema).max(MAX_PERSONAS),
|
|
2235
|
+
agreement_credit: array(ReviewerSchema).max(MAX_PERSONAS)
|
|
2183
2236
|
}).strict();
|
|
2184
|
-
var SynthesizedFindingFieldsSchema =
|
|
2237
|
+
var SynthesizedFindingFieldsSchema = object({
|
|
2185
2238
|
title: FindingTitleSchema,
|
|
2186
2239
|
severity: FindingSeveritySchema,
|
|
2187
2240
|
file: RepoRelativePathSchema,
|
|
2188
|
-
line:
|
|
2241
|
+
line: number().int().positive(),
|
|
2189
2242
|
why_it_matters: boundedText(2048),
|
|
2190
2243
|
autofix_class: AutofixClassSchema,
|
|
2191
2244
|
owner: OwnerSchema,
|
|
2192
|
-
requires_verification:
|
|
2193
|
-
confidence:
|
|
2245
|
+
requires_verification: boolean(),
|
|
2246
|
+
confidence: number().min(0).max(1),
|
|
2194
2247
|
evidence: EvidenceSchema,
|
|
2195
|
-
pre_existing:
|
|
2196
|
-
suggested_fix:
|
|
2197
|
-
validated:
|
|
2248
|
+
pre_existing: boolean(),
|
|
2249
|
+
suggested_fix: string().max(2048).nullable().optional(),
|
|
2250
|
+
validated: boolean().optional(),
|
|
2198
2251
|
validation_reason: ReasonSchema.optional(),
|
|
2199
|
-
input_finding_ids:
|
|
2252
|
+
input_finding_ids: array(boundedText(MAX_INPUT_ID_LENGTH)).min(1).max(MAX_FINDINGS),
|
|
2200
2253
|
provenance: ProvenanceSchema
|
|
2201
2254
|
}).strict();
|
|
2202
2255
|
var SynthesizedFindingSchema = SynthesizedFindingFieldsSchema.superRefine((finding, ctx) => {
|
|
@@ -2208,12 +2261,12 @@ var SynthesizedFindingSchema = SynthesizedFindingFieldsSchema.superRefine((findi
|
|
|
2208
2261
|
});
|
|
2209
2262
|
}
|
|
2210
2263
|
});
|
|
2211
|
-
var DispatchSchema =
|
|
2264
|
+
var DispatchSchema = object({
|
|
2212
2265
|
persona: ReviewerSchema,
|
|
2213
2266
|
dispatch_outcome: DispatchOutcomeSchema,
|
|
2214
|
-
input_finding_count:
|
|
2267
|
+
input_finding_count: number().int().nonnegative().max(MAX_FINDINGS),
|
|
2215
2268
|
rejection_reason: ReasonSchema.optional(),
|
|
2216
|
-
selection_surface:
|
|
2269
|
+
selection_surface: array(RepoRelativePathSchema).max(MAX_FINDINGS).optional(),
|
|
2217
2270
|
selection_reason: ReasonSchema.optional()
|
|
2218
2271
|
}).strict().superRefine((dispatch, ctx) => {
|
|
2219
2272
|
if (RISK_CRITICAL_PERSONAS.includes(dispatch.persona) && (!dispatch.selection_surface || dispatch.selection_surface.length === 0)) {
|
|
@@ -2224,29 +2277,29 @@ var DispatchSchema = exports_external.object({
|
|
|
2224
2277
|
});
|
|
2225
2278
|
}
|
|
2226
2279
|
});
|
|
2227
|
-
var DispositionCountsSchema =
|
|
2228
|
-
surviving:
|
|
2229
|
-
merged:
|
|
2230
|
-
suppressed:
|
|
2231
|
-
filtered:
|
|
2232
|
-
rejected:
|
|
2280
|
+
var DispositionCountsSchema = object({
|
|
2281
|
+
surviving: number().int().nonnegative().max(MAX_FINDINGS * MAX_PERSONAS),
|
|
2282
|
+
merged: number().int().nonnegative().max(MAX_FINDINGS * MAX_PERSONAS),
|
|
2283
|
+
suppressed: number().int().nonnegative().max(MAX_FINDINGS * MAX_PERSONAS),
|
|
2284
|
+
filtered: number().int().nonnegative().max(MAX_FINDINGS * MAX_PERSONAS),
|
|
2285
|
+
rejected: number().int().nonnegative().max(MAX_FINDINGS * MAX_PERSONAS)
|
|
2233
2286
|
}).strict();
|
|
2234
|
-
var CoverageSchema =
|
|
2235
|
-
reviewers:
|
|
2236
|
-
validators:
|
|
2237
|
-
residual_risks:
|
|
2238
|
-
testing_gaps:
|
|
2239
|
-
failed_reviewers:
|
|
2240
|
-
validator_failures:
|
|
2241
|
-
intent_uncertainty:
|
|
2287
|
+
var CoverageSchema = object({
|
|
2288
|
+
reviewers: number().int().nonnegative().max(MAX_PERSONAS).optional(),
|
|
2289
|
+
validators: number().int().nonnegative().max(MAX_PERSONAS).optional(),
|
|
2290
|
+
residual_risks: array(ReasonSchema).max(MAX_PERSONAS),
|
|
2291
|
+
testing_gaps: array(ReasonSchema).max(MAX_PERSONAS),
|
|
2292
|
+
failed_reviewers: array(ReviewerSchema).max(MAX_PERSONAS),
|
|
2293
|
+
validator_failures: array(ReasonSchema).max(MAX_PERSONAS),
|
|
2294
|
+
intent_uncertainty: array(ReasonSchema).max(MAX_PERSONAS)
|
|
2242
2295
|
}).strict();
|
|
2243
|
-
var DeclinedMergeSchema =
|
|
2296
|
+
var DeclinedMergeSchema = object({
|
|
2244
2297
|
file: RepoRelativePathSchema,
|
|
2245
|
-
input_finding_ids:
|
|
2298
|
+
input_finding_ids: array(boundedText(MAX_INPUT_ID_LENGTH)).min(2).max(MAX_FINDINGS),
|
|
2246
2299
|
reason: ReasonSchema
|
|
2247
2300
|
}).strict();
|
|
2248
|
-
var ValidationSchema =
|
|
2249
|
-
status:
|
|
2301
|
+
var ValidationSchema = object({
|
|
2302
|
+
status: _enum([
|
|
2250
2303
|
"passed",
|
|
2251
2304
|
"failed",
|
|
2252
2305
|
"unavailable",
|
|
@@ -2269,9 +2322,9 @@ var ValidationSchema = exports_external.object({
|
|
|
2269
2322
|
});
|
|
2270
2323
|
}
|
|
2271
2324
|
});
|
|
2272
|
-
var RiskCoverageSchema =
|
|
2325
|
+
var RiskCoverageSchema = object({
|
|
2273
2326
|
persona: RiskCriticalPersonaSchema,
|
|
2274
|
-
satisfied:
|
|
2327
|
+
satisfied: boolean(),
|
|
2275
2328
|
input_finding_id: boundedText(MAX_INPUT_ID_LENGTH).optional()
|
|
2276
2329
|
}).strict().superRefine((coverage, ctx) => {
|
|
2277
2330
|
if (coverage.satisfied && coverage.input_finding_id === undefined) {
|
|
@@ -2289,14 +2342,14 @@ var RiskCoverageSchema = exports_external.object({
|
|
|
2289
2342
|
});
|
|
2290
2343
|
}
|
|
2291
2344
|
});
|
|
2292
|
-
var ReviewArtifactSchema =
|
|
2293
|
-
schema_version:
|
|
2345
|
+
var ReviewArtifactSchema = object({
|
|
2346
|
+
schema_version: literal(1),
|
|
2294
2347
|
run_id: boundedText(MAX_RUN_ID_LENGTH),
|
|
2295
2348
|
branch: BranchSchema,
|
|
2296
2349
|
head_sha: HeadShaSchema,
|
|
2297
|
-
mode:
|
|
2350
|
+
mode: _enum(["interactive", "autofix", "headless"]),
|
|
2298
2351
|
harness: HarnessSchema,
|
|
2299
|
-
run_status:
|
|
2352
|
+
run_status: _enum([
|
|
2300
2353
|
"in_progress",
|
|
2301
2354
|
"completed",
|
|
2302
2355
|
"degraded",
|
|
@@ -2304,15 +2357,15 @@ var ReviewArtifactSchema = exports_external.object({
|
|
|
2304
2357
|
]),
|
|
2305
2358
|
verdict: boundedText(256),
|
|
2306
2359
|
completed_at: CompletedAtSchema,
|
|
2307
|
-
dispatches:
|
|
2308
|
-
input_findings:
|
|
2309
|
-
findings:
|
|
2310
|
-
declined_merges:
|
|
2311
|
-
risk_coverage:
|
|
2360
|
+
dispatches: array(DispatchSchema).max(MAX_PERSONAS),
|
|
2361
|
+
input_findings: array(InputFindingSchema).max(MAX_FINDINGS * MAX_PERSONAS),
|
|
2362
|
+
findings: array(SynthesizedFindingSchema).max(MAX_FINDINGS),
|
|
2363
|
+
declined_merges: array(DeclinedMergeSchema).max(MAX_FINDINGS).optional(),
|
|
2364
|
+
risk_coverage: array(RiskCoverageSchema).max(MAX_PERSONAS).optional(),
|
|
2312
2365
|
disposition_counts: DispositionCountsSchema,
|
|
2313
|
-
applied_fixes:
|
|
2314
|
-
residual_actionable_work:
|
|
2315
|
-
advisory_outputs:
|
|
2366
|
+
applied_fixes: array(ReasonSchema).max(MAX_FINDINGS),
|
|
2367
|
+
residual_actionable_work: array(ReasonSchema).max(MAX_FINDINGS),
|
|
2368
|
+
advisory_outputs: array(ReasonSchema).max(MAX_FINDINGS),
|
|
2316
2369
|
coverage: CoverageSchema,
|
|
2317
2370
|
validation: ValidationSchema.optional()
|
|
2318
2371
|
}).strict();
|
|
@@ -2365,8 +2418,8 @@ function lstatOrNull(targetPath) {
|
|
|
2365
2418
|
function assertRealpathUnderCwd(dir, cwd) {
|
|
2366
2419
|
const realDir = fs5.realpathSync(dir);
|
|
2367
2420
|
const realCwd = fs5.realpathSync(cwd);
|
|
2368
|
-
const
|
|
2369
|
-
if (
|
|
2421
|
+
const relative = path4.relative(realCwd, realDir);
|
|
2422
|
+
if (relative.startsWith("..") || path4.isAbsolute(relative)) {
|
|
2370
2423
|
throw createSetupError(`Refusing to write under ${dir}: resolved directory escapes the project root`);
|
|
2371
2424
|
}
|
|
2372
2425
|
}
|
|
@@ -2459,8 +2512,8 @@ function writeTempAndRename(destPath, content, mode, preserveExactMode, ops) {
|
|
|
2459
2512
|
throw error;
|
|
2460
2513
|
}
|
|
2461
2514
|
}
|
|
2462
|
-
function makeTempPath(parentDir,
|
|
2463
|
-
return path4.join(parentDir, `.${
|
|
2515
|
+
function makeTempPath(parentDir, basename) {
|
|
2516
|
+
return path4.join(parentDir, `.${basename}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
2464
2517
|
}
|
|
2465
2518
|
function cleanupTemp(tempPath, ops) {
|
|
2466
2519
|
if (!fs5.existsSync(tempPath))
|
|
@@ -2515,8 +2568,8 @@ function setupOpenCode(cwd, ops) {
|
|
|
2515
2568
|
throw createSetupError(`Invalid OpenCode config in ${targetPath}: \`plugins\` (plural) is not supported by OpenCode's schema; use singular \`plugin\``);
|
|
2516
2569
|
}
|
|
2517
2570
|
if (!Object.hasOwn(parsed, "plugin")) {
|
|
2518
|
-
const
|
|
2519
|
-
atomicWrite(targetPath, applyEdits(rawText,
|
|
2571
|
+
const edits = modify(rawText, ["plugin"], [SYSTEMATIC_PACKAGE_NAME], {});
|
|
2572
|
+
atomicWrite(targetPath, applyEdits(rawText, edits), existing.bytes, existing.mode, ops);
|
|
2520
2573
|
return { status: "configured", targetPath };
|
|
2521
2574
|
}
|
|
2522
2575
|
const existingValue = parsed.plugin;
|
|
@@ -2577,8 +2630,8 @@ function setupPi(cwd, ops) {
|
|
|
2577
2630
|
}
|
|
2578
2631
|
const existingPackages = parsed.packages;
|
|
2579
2632
|
if (existingPackages === undefined) {
|
|
2580
|
-
const
|
|
2581
|
-
atomicWrite(targetPath, applyEdits(rawText,
|
|
2633
|
+
const edits = modify(rawText, ["packages"], [PI_PACKAGE_IDENTIFIER], {});
|
|
2634
|
+
atomicWrite(targetPath, applyEdits(rawText, edits), existing.bytes, existing.mode, ops);
|
|
2582
2635
|
return { status: "configured", targetPath };
|
|
2583
2636
|
}
|
|
2584
2637
|
if (!Array.isArray(existingPackages)) {
|