overlane 0.1.123 → 0.1.124
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/overlane.mjs +774 -134
- package/package.json +1 -1
- package/plugins/claude/plugins/mvrx-harness/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-context.mjs +33 -33
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-guard.mjs +24 -24
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-intake.mjs +36 -36
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-quota.mjs +34 -34
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-statusline.mjs +25 -25
- package/plugins/claude/plugins/mvrx-harness/scripts/harness-stop.mjs +29 -29
- package/plugins/codex/plugins/mvrx-harness/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-context.mjs +33 -33
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-guard.mjs +24 -24
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-intake.mjs +36 -36
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-quota.mjs +34 -34
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-statusline.mjs +25 -25
- package/plugins/codex/plugins/mvrx-harness/scripts/harness-stop.mjs +29 -29
- package/plugins/release-manifest.json +20 -20
package/dist/overlane.mjs
CHANGED
|
@@ -23049,6 +23049,375 @@ var init_code_map = __esm({
|
|
|
23049
23049
|
}
|
|
23050
23050
|
});
|
|
23051
23051
|
|
|
23052
|
+
// ../contracts/src/plans.ts
|
|
23053
|
+
var PLAN_IDS, BillingPlanId, CHECKOUT_PLANS, CheckoutPlanId, METERS, Meter, AllowanceValue, PlanAllowances, PlanData, OverageRates, FreeTierControls, PlanCatalog, TenantPlanLimits;
|
|
23054
|
+
var init_plans = __esm({
|
|
23055
|
+
"../contracts/src/plans.ts"() {
|
|
23056
|
+
"use strict";
|
|
23057
|
+
init_zod();
|
|
23058
|
+
PLAN_IDS = ["free", "pro", "team", "business", "enterprise"];
|
|
23059
|
+
BillingPlanId = external_exports.enum(PLAN_IDS);
|
|
23060
|
+
CHECKOUT_PLANS = ["pro", "team", "business"];
|
|
23061
|
+
CheckoutPlanId = external_exports.enum(CHECKOUT_PLANS);
|
|
23062
|
+
METERS = ["reviews", "ciMinutes", "docsCalls", "hostedInference"];
|
|
23063
|
+
Meter = external_exports.enum(METERS);
|
|
23064
|
+
AllowanceValue = external_exports.union([external_exports.number().int().nonnegative(), external_exports.literal("unlimited"), external_exports.null()]);
|
|
23065
|
+
PlanAllowances = external_exports.object({
|
|
23066
|
+
privateProjects: AllowanceValue,
|
|
23067
|
+
tasks: AllowanceValue,
|
|
23068
|
+
reviews: AllowanceValue,
|
|
23069
|
+
docsCalls: AllowanceValue,
|
|
23070
|
+
ciMinutes: AllowanceValue
|
|
23071
|
+
}).strict();
|
|
23072
|
+
PlanData = external_exports.object({
|
|
23073
|
+
id: BillingPlanId,
|
|
23074
|
+
name: external_exports.string().min(1),
|
|
23075
|
+
audience: external_exports.string().min(1),
|
|
23076
|
+
/** Per month (per seat for per-seat plans), billed monthly. Null for Free and Enterprise. */
|
|
23077
|
+
monthlyCents: external_exports.number().int().positive().nullable(),
|
|
23078
|
+
/** Per month (per seat for per-seat plans), billed annually. */
|
|
23079
|
+
annualMonthlyCents: external_exports.number().int().positive().nullable(),
|
|
23080
|
+
unit: external_exports.enum(["free", "month", "seat / month", "custom"]),
|
|
23081
|
+
perSeat: external_exports.boolean(),
|
|
23082
|
+
/** Seat allowances are pooled across the workspace (Team) rather than held per person (REQ-BIL-07). */
|
|
23083
|
+
pooled: external_exports.boolean(),
|
|
23084
|
+
minimumSeats: external_exports.number().int().positive().optional(),
|
|
23085
|
+
maximumSeats: external_exports.number().int().positive().optional(),
|
|
23086
|
+
/** An allowance on a per-seat plan is per seat; on a workspace plan (Free) it is for the whole workspace. */
|
|
23087
|
+
allowances: PlanAllowances,
|
|
23088
|
+
/** Observability retention in days; null when the plan states none. */
|
|
23089
|
+
retentionDays: external_exports.number().int().positive().nullable(),
|
|
23090
|
+
/** Memory levels, as shown on the pricing page. */
|
|
23091
|
+
memory: external_exports.string().nullable(),
|
|
23092
|
+
/** Whether usage beyond an allowance is billed. Free has no card on file, so it stops instead (REQ-BIL-11). */
|
|
23093
|
+
overage: external_exports.boolean()
|
|
23094
|
+
}).strict();
|
|
23095
|
+
OverageRates = external_exports.object({
|
|
23096
|
+
/** Micro-dollars per review beyond the allowance ($0.10). */
|
|
23097
|
+
reviewMicros: external_exports.number().int().positive(),
|
|
23098
|
+
/** Micro-dollars per CI minute beyond the allowance ($0.006). */
|
|
23099
|
+
ciMinuteMicros: external_exports.number().int().positive(),
|
|
23100
|
+
/** Markup on hosted inference and compute at provider cost, in basis points (10% = 1000). BYOK is free. */
|
|
23101
|
+
hostedMarkupBps: external_exports.number().int().nonnegative()
|
|
23102
|
+
}).strict();
|
|
23103
|
+
FreeTierControls = external_exports.object({
|
|
23104
|
+
/** CPU seconds one CI job may use on a plan with no card on file. */
|
|
23105
|
+
ciJobCpuSeconds: external_exports.number().int().positive(),
|
|
23106
|
+
/** Requests per minute per tenant on Free, and on a paid plan. */
|
|
23107
|
+
requestsPerMinute: external_exports.number().int().positive(),
|
|
23108
|
+
paidRequestsPerMinute: external_exports.number().int().positive(),
|
|
23109
|
+
/** Only when the person has chosen to connect an account on another service (GitHub, GitLab, ...): how old it must be. No account is ever required (ADR 0050). */
|
|
23110
|
+
minimumConnectedAccountAgeDays: external_exports.number().int().nonnegative(),
|
|
23111
|
+
/** CI beyond the free allowance needs a card, which means a paid plan. */
|
|
23112
|
+
cardRequiredForCiBeyondAllowance: external_exports.literal(true)
|
|
23113
|
+
}).strict();
|
|
23114
|
+
PlanCatalog = external_exports.object({
|
|
23115
|
+
version: external_exports.literal("1"),
|
|
23116
|
+
currency: external_exports.literal("USD"),
|
|
23117
|
+
/** Every plan, in order. */
|
|
23118
|
+
plans: external_exports.array(PlanData).length(PLAN_IDS.length),
|
|
23119
|
+
overage: OverageRates,
|
|
23120
|
+
/** Length of the failed-payment grace period, in days, before any restriction (REQ-BIL-09). */
|
|
23121
|
+
graceDays: external_exports.number().int().positive(),
|
|
23122
|
+
/** Days before the end of grace that a reminder notice is sent. */
|
|
23123
|
+
graceReminderDays: external_exports.array(external_exports.number().int().positive()),
|
|
23124
|
+
freeTier: FreeTierControls
|
|
23125
|
+
}).strict().superRefine((catalog, ctx) => {
|
|
23126
|
+
catalog.plans.forEach((plan3, index) => {
|
|
23127
|
+
if (plan3.id !== PLAN_IDS[index]) ctx.addIssue({ code: "custom", path: ["plans", index, "id"], message: `plans are listed in order: expected ${PLAN_IDS[index]}` });
|
|
23128
|
+
if (plan3.monthlyCents === null !== (plan3.annualMonthlyCents === null)) ctx.addIssue({ code: "custom", path: ["plans", index], message: "monthly and annual prices are both set or both null" });
|
|
23129
|
+
if (plan3.monthlyCents !== null && plan3.annualMonthlyCents !== null && plan3.annualMonthlyCents >= plan3.monthlyCents) {
|
|
23130
|
+
ctx.addIssue({ code: "custom", path: ["plans", index, "annualMonthlyCents"], message: "annual billing is cheaper per month" });
|
|
23131
|
+
}
|
|
23132
|
+
});
|
|
23133
|
+
});
|
|
23134
|
+
TenantPlanLimits = external_exports.object({
|
|
23135
|
+
tenantId: external_exports.string().min(1),
|
|
23136
|
+
plan: BillingPlanId,
|
|
23137
|
+
seats: external_exports.number().int().positive(),
|
|
23138
|
+
/** Total for the workspace this period: per-seat allowance times seats on a per-seat plan. */
|
|
23139
|
+
allowances: PlanAllowances,
|
|
23140
|
+
retentionDays: external_exports.number().int().positive().nullable(),
|
|
23141
|
+
/** True once the tenant is past a downgrade or grace restriction: reads work, writes do not (REQ-BIL-06, REQ-BIL-09). */
|
|
23142
|
+
readOnly: external_exports.boolean(),
|
|
23143
|
+
/** Whether usage beyond an allowance is billed (true) or refused (false). */
|
|
23144
|
+
overage: external_exports.boolean(),
|
|
23145
|
+
periodStart: external_exports.iso.datetime({ offset: true }),
|
|
23146
|
+
periodEnd: external_exports.iso.datetime({ offset: true })
|
|
23147
|
+
}).strict();
|
|
23148
|
+
}
|
|
23149
|
+
});
|
|
23150
|
+
|
|
23151
|
+
// ../contracts/src/billing.ts
|
|
23152
|
+
var BillingInterval, SUBSCRIPTION_STATUSES, SubscriptionStatus, Subscription, Seat, UsageEventInput, UsageEvent, RecordUsageResponse, INVOICE_STATUSES, InvoiceStatus, InvoiceLine, Invoice, GRACE_STATES, GraceState, GraceNotice, Grace, CAP_SCOPES, CapScope, Cap, PutCapRequest, DeleteCapRequest, MeterUsage, UsageSummary, CheckoutRequest, CheckoutResponse, ChangePlanRequest, OverLimit, ChangePlanResponse, SeatChangeRequest, SeatChangeResponse, CancelRequest, PortalResponse, BillingStatus, UsageDecision, STRIPE_EVENT_TYPES, StripeEventType, epochSeconds, StripeSubscriptionObject, StripeInvoiceObject, StripeCheckoutObject, StripeEvent, WEBHOOK_OUTCOMES, WebhookOutcome, WebhookResult, billingPaths;
|
|
23153
|
+
var init_billing = __esm({
|
|
23154
|
+
"../contracts/src/billing.ts"() {
|
|
23155
|
+
"use strict";
|
|
23156
|
+
init_zod();
|
|
23157
|
+
init_common();
|
|
23158
|
+
init_plans();
|
|
23159
|
+
BillingInterval = external_exports.enum(["month", "year"]);
|
|
23160
|
+
SUBSCRIPTION_STATUSES = ["active", "past_due", "canceled", "incomplete"];
|
|
23161
|
+
SubscriptionStatus = external_exports.enum(SUBSCRIPTION_STATUSES);
|
|
23162
|
+
Subscription = external_exports.object({
|
|
23163
|
+
tenantId: TenantId,
|
|
23164
|
+
plan: BillingPlanId,
|
|
23165
|
+
interval: BillingInterval,
|
|
23166
|
+
seats: external_exports.number().int().positive(),
|
|
23167
|
+
status: SubscriptionStatus,
|
|
23168
|
+
stripeCustomerId: external_exports.string().min(1).optional(),
|
|
23169
|
+
stripeSubscriptionId: external_exports.string().min(1).optional(),
|
|
23170
|
+
currentPeriodStart: Timestamp,
|
|
23171
|
+
currentPeriodEnd: Timestamp,
|
|
23172
|
+
cancelAtPeriodEnd: external_exports.boolean(),
|
|
23173
|
+
/** Set by a downgrade over the new limits or by the end of a failed-payment grace period. Reads work; writes are refused; nothing is deleted (REQ-BIL-06). */
|
|
23174
|
+
readOnly: external_exports.boolean(),
|
|
23175
|
+
readOnlyReason: external_exports.enum(["downgrade_over_limit", "payment_failed"]).optional(),
|
|
23176
|
+
updatedAt: Timestamp
|
|
23177
|
+
}).strict();
|
|
23178
|
+
Seat = external_exports.object({
|
|
23179
|
+
tenantId: TenantId,
|
|
23180
|
+
purchased: external_exports.number().int().positive(),
|
|
23181
|
+
minimum: external_exports.number().int().positive(),
|
|
23182
|
+
maximum: external_exports.number().int().positive().nullable(),
|
|
23183
|
+
assigned: external_exports.number().int().nonnegative()
|
|
23184
|
+
}).strict();
|
|
23185
|
+
UsageEventInput = external_exports.object({
|
|
23186
|
+
meter: Meter,
|
|
23187
|
+
quantity: external_exports.number().int().positive().max(1e9),
|
|
23188
|
+
idempotencyKey: external_exports.string().min(1).max(200),
|
|
23189
|
+
/** When the usage happened (not when it arrived). */
|
|
23190
|
+
at: Timestamp,
|
|
23191
|
+
feature: external_exports.string().min(1).max(64).optional(),
|
|
23192
|
+
projectId: external_exports.string().min(1).max(128).optional(),
|
|
23193
|
+
agentId: external_exports.string().min(1).max(128).optional(),
|
|
23194
|
+
/** Provider cost in micro-dollars, for hosted inference. The platform adds the markup. */
|
|
23195
|
+
costMicros: external_exports.number().int().nonnegative().optional()
|
|
23196
|
+
}).strict();
|
|
23197
|
+
UsageEvent = UsageEventInput.extend({
|
|
23198
|
+
tenantId: TenantId,
|
|
23199
|
+
/** Monotonic per tenant, assigned when first recorded; a replay returns the first one. */
|
|
23200
|
+
sequence: external_exports.number().int().positive(),
|
|
23201
|
+
/** Start of the billing period whose invoice carries this usage. Late usage after an invoice closed lands on the next one (REQ-BIL-08). */
|
|
23202
|
+
periodStart: Timestamp,
|
|
23203
|
+
receivedAt: Timestamp,
|
|
23204
|
+
/** True when the event arrived after its own period's invoice closed. */
|
|
23205
|
+
late: external_exports.boolean()
|
|
23206
|
+
}).strict();
|
|
23207
|
+
RecordUsageResponse = external_exports.object({ event: UsageEvent, duplicate: external_exports.boolean() }).strict();
|
|
23208
|
+
INVOICE_STATUSES = ["draft", "open", "paid", "void", "uncollectible"];
|
|
23209
|
+
InvoiceStatus = external_exports.enum(INVOICE_STATUSES);
|
|
23210
|
+
InvoiceLine = external_exports.object({
|
|
23211
|
+
kind: external_exports.enum(["subscription", "proration", "usage"]),
|
|
23212
|
+
meter: Meter.optional(),
|
|
23213
|
+
description: external_exports.string().min(1).max(200),
|
|
23214
|
+
quantity: external_exports.number().int().nonnegative(),
|
|
23215
|
+
unitMicros: external_exports.number().int().nonnegative().optional(),
|
|
23216
|
+
amountCents: external_exports.number().int()
|
|
23217
|
+
}).strict();
|
|
23218
|
+
Invoice = external_exports.object({
|
|
23219
|
+
tenantId: TenantId,
|
|
23220
|
+
invoiceId: external_exports.string().min(1),
|
|
23221
|
+
status: InvoiceStatus,
|
|
23222
|
+
periodStart: Timestamp,
|
|
23223
|
+
periodEnd: Timestamp,
|
|
23224
|
+
lines: external_exports.array(InvoiceLine),
|
|
23225
|
+
totalCents: external_exports.number().int(),
|
|
23226
|
+
/** The invoice stopped taking new usage at this time. Usage that arrives later goes on the next invoice. */
|
|
23227
|
+
closedAt: Timestamp.optional(),
|
|
23228
|
+
paidAt: Timestamp.optional(),
|
|
23229
|
+
failedAttempts: external_exports.number().int().nonnegative()
|
|
23230
|
+
}).strict();
|
|
23231
|
+
GRACE_STATES = ["none", "grace", "restricted"];
|
|
23232
|
+
GraceState = external_exports.enum(GRACE_STATES);
|
|
23233
|
+
GraceNotice = external_exports.object({
|
|
23234
|
+
id: external_exports.string().min(1),
|
|
23235
|
+
kind: external_exports.enum(["payment_failed", "reminder", "restricted", "recovered"]),
|
|
23236
|
+
at: Timestamp,
|
|
23237
|
+
message: external_exports.string().min(1)
|
|
23238
|
+
}).strict();
|
|
23239
|
+
Grace = external_exports.object({
|
|
23240
|
+
tenantId: TenantId,
|
|
23241
|
+
state: GraceState,
|
|
23242
|
+
invoiceId: external_exports.string().min(1).optional(),
|
|
23243
|
+
startedAt: Timestamp.optional(),
|
|
23244
|
+
endsAt: Timestamp.optional(),
|
|
23245
|
+
notices: external_exports.array(GraceNotice)
|
|
23246
|
+
}).strict();
|
|
23247
|
+
CAP_SCOPES = ["team", "project", "agent"];
|
|
23248
|
+
CapScope = external_exports.enum(CAP_SCOPES);
|
|
23249
|
+
Cap = external_exports.object({
|
|
23250
|
+
tenantId: TenantId,
|
|
23251
|
+
scope: CapScope,
|
|
23252
|
+
/** Project ID or agent token ID; absent for the whole team. */
|
|
23253
|
+
scopeId: external_exports.string().min(1).max(128).optional(),
|
|
23254
|
+
/** Per billing period, in cents of metered spend (overage plus hosted inference with markup). */
|
|
23255
|
+
limitCents: external_exports.number().int().positive().max(1e8),
|
|
23256
|
+
updatedBy: external_exports.string().min(1),
|
|
23257
|
+
updatedAt: Timestamp
|
|
23258
|
+
}).strict().superRefine((cap, ctx) => {
|
|
23259
|
+
if (cap.scope === "team" && cap.scopeId !== void 0) ctx.addIssue({ code: "custom", path: ["scopeId"], message: "a team cap has no scope ID" });
|
|
23260
|
+
if (cap.scope !== "team" && cap.scopeId === void 0) ctx.addIssue({ code: "custom", path: ["scopeId"], message: "a project or agent cap names its project or agent" });
|
|
23261
|
+
});
|
|
23262
|
+
PutCapRequest = external_exports.object({
|
|
23263
|
+
requestId: external_exports.string().min(1).max(128),
|
|
23264
|
+
scope: CapScope,
|
|
23265
|
+
scopeId: external_exports.string().min(1).max(128).optional(),
|
|
23266
|
+
limitCents: external_exports.number().int().positive().max(1e8)
|
|
23267
|
+
}).strict();
|
|
23268
|
+
DeleteCapRequest = external_exports.object({ requestId: external_exports.string().min(1).max(128), scope: CapScope, scopeId: external_exports.string().min(1).max(128).optional() }).strict();
|
|
23269
|
+
MeterUsage = external_exports.object({
|
|
23270
|
+
meter: Meter,
|
|
23271
|
+
used: external_exports.number().int().nonnegative(),
|
|
23272
|
+
/** Total allowance for the workspace this period (per-seat allowance times seats). Null when the plan states none. */
|
|
23273
|
+
allowance: AllowanceValue,
|
|
23274
|
+
overUnits: external_exports.number().int().nonnegative(),
|
|
23275
|
+
/** Price of one unit beyond the allowance, in micro-dollars; null for hosted inference (provider cost plus markup) and unmetered-for-billing meters. */
|
|
23276
|
+
rateMicros: external_exports.number().int().nonnegative().nullable(),
|
|
23277
|
+
overageMicros: external_exports.number().int().nonnegative()
|
|
23278
|
+
}).strict();
|
|
23279
|
+
UsageSummary = external_exports.object({
|
|
23280
|
+
tenantId: TenantId,
|
|
23281
|
+
plan: BillingPlanId,
|
|
23282
|
+
periodStart: Timestamp,
|
|
23283
|
+
periodEnd: Timestamp,
|
|
23284
|
+
meters: external_exports.array(MeterUsage),
|
|
23285
|
+
/** Metered spend this period: overage plus hosted inference with markup, in micro-dollars. */
|
|
23286
|
+
spendMicros: external_exports.number().int().nonnegative(),
|
|
23287
|
+
/** Plain-language messages: an allowance reached, overage starting, a cap near. */
|
|
23288
|
+
notices: external_exports.array(external_exports.string().min(1))
|
|
23289
|
+
}).strict();
|
|
23290
|
+
CheckoutRequest = external_exports.object({
|
|
23291
|
+
requestId: external_exports.string().min(1).max(128),
|
|
23292
|
+
plan: CheckoutPlanId,
|
|
23293
|
+
interval: BillingInterval.default("month"),
|
|
23294
|
+
seats: external_exports.number().int().positive().max(1e4).default(1)
|
|
23295
|
+
}).strict();
|
|
23296
|
+
CheckoutResponse = external_exports.object({
|
|
23297
|
+
tenantId: TenantId,
|
|
23298
|
+
sessionId: external_exports.string().min(1),
|
|
23299
|
+
/** A Stripe-hosted page. Card details are entered there and never reach Overlane (REQ-BIL-13). */
|
|
23300
|
+
url: external_exports.string().url(),
|
|
23301
|
+
plan: CheckoutPlanId,
|
|
23302
|
+
interval: BillingInterval,
|
|
23303
|
+
seats: external_exports.number().int().positive(),
|
|
23304
|
+
/** What the first period costs before tax, in cents. Stripe Tax adds tax at checkout. */
|
|
23305
|
+
firstPeriodCents: external_exports.number().int().nonnegative()
|
|
23306
|
+
}).strict();
|
|
23307
|
+
ChangePlanRequest = external_exports.object({
|
|
23308
|
+
requestId: external_exports.string().min(1).max(128),
|
|
23309
|
+
plan: BillingPlanId.exclude(["enterprise"]),
|
|
23310
|
+
interval: BillingInterval.optional(),
|
|
23311
|
+
seats: external_exports.number().int().positive().max(1e4).optional()
|
|
23312
|
+
}).strict();
|
|
23313
|
+
OverLimit = external_exports.object({ what: external_exports.string().min(1), used: external_exports.number().int().nonnegative(), limit: external_exports.number().int().nonnegative() }).strict();
|
|
23314
|
+
ChangePlanResponse = external_exports.object({
|
|
23315
|
+
subscription: Subscription,
|
|
23316
|
+
/** Charge (positive) or credit (negative) for the rest of the period, in cents. */
|
|
23317
|
+
prorationCents: external_exports.number().int(),
|
|
23318
|
+
/** What the new plan's limits are exceeded by. When non-empty the workspace is read-only; nothing is deleted. */
|
|
23319
|
+
overLimit: external_exports.array(OverLimit),
|
|
23320
|
+
deleted: external_exports.literal(0)
|
|
23321
|
+
}).strict();
|
|
23322
|
+
SeatChangeRequest = external_exports.object({ requestId: external_exports.string().min(1).max(128), seats: external_exports.number().int().positive().max(1e4) }).strict();
|
|
23323
|
+
SeatChangeResponse = external_exports.object({
|
|
23324
|
+
subscription: Subscription,
|
|
23325
|
+
seat: Seat,
|
|
23326
|
+
/** Prorated charge (positive) or credit (negative) for the remainder of the period, in cents (REQ-BIL-05). */
|
|
23327
|
+
prorationCents: external_exports.number().int()
|
|
23328
|
+
}).strict();
|
|
23329
|
+
CancelRequest = external_exports.object({ requestId: external_exports.string().min(1).max(128), atPeriodEnd: external_exports.boolean().default(true) }).strict();
|
|
23330
|
+
PortalResponse = external_exports.object({ tenantId: TenantId, url: external_exports.string().url() }).strict();
|
|
23331
|
+
BillingStatus = external_exports.object({
|
|
23332
|
+
tenantId: TenantId,
|
|
23333
|
+
subscription: Subscription,
|
|
23334
|
+
seat: Seat,
|
|
23335
|
+
grace: Grace,
|
|
23336
|
+
limits: TenantPlanLimits,
|
|
23337
|
+
usage: UsageSummary,
|
|
23338
|
+
caps: external_exports.array(Cap),
|
|
23339
|
+
invoices: external_exports.array(Invoice),
|
|
23340
|
+
/** True when Stripe is configured; false while the live leg is pending and the in-process fake serves. */
|
|
23341
|
+
live: external_exports.boolean()
|
|
23342
|
+
}).strict();
|
|
23343
|
+
UsageDecision = external_exports.object({
|
|
23344
|
+
tenantId: TenantId,
|
|
23345
|
+
meter: Meter,
|
|
23346
|
+
outcome: external_exports.enum(["within_allowance", "overage", "refused", "cap_reached", "read_only"]),
|
|
23347
|
+
allowed: external_exports.boolean(),
|
|
23348
|
+
/** Micro-dollars this unit costs; zero within the allowance. */
|
|
23349
|
+
chargeMicros: external_exports.number().int().nonnegative(),
|
|
23350
|
+
message: external_exports.string().min(1),
|
|
23351
|
+
nextCommand: external_exports.string().nullable(),
|
|
23352
|
+
exitCode: external_exports.union([external_exports.literal(0), external_exports.literal(6)])
|
|
23353
|
+
}).strict();
|
|
23354
|
+
STRIPE_EVENT_TYPES = [
|
|
23355
|
+
"checkout.session.completed",
|
|
23356
|
+
"customer.subscription.created",
|
|
23357
|
+
"customer.subscription.updated",
|
|
23358
|
+
"customer.subscription.deleted",
|
|
23359
|
+
"invoice.created",
|
|
23360
|
+
"invoice.finalized",
|
|
23361
|
+
"invoice.paid",
|
|
23362
|
+
"invoice.payment_failed"
|
|
23363
|
+
];
|
|
23364
|
+
StripeEventType = external_exports.enum(STRIPE_EVENT_TYPES);
|
|
23365
|
+
epochSeconds = external_exports.number().int().nonnegative();
|
|
23366
|
+
StripeSubscriptionObject = external_exports.object({
|
|
23367
|
+
id: external_exports.string().min(1),
|
|
23368
|
+
customer: external_exports.string().min(1),
|
|
23369
|
+
status: external_exports.enum(["active", "past_due", "canceled", "incomplete", "unpaid", "trialing", "incomplete_expired"]),
|
|
23370
|
+
cancel_at_period_end: external_exports.boolean(),
|
|
23371
|
+
current_period_start: epochSeconds,
|
|
23372
|
+
current_period_end: epochSeconds,
|
|
23373
|
+
quantity: external_exports.number().int().positive(),
|
|
23374
|
+
metadata: external_exports.object({ tenantId: TenantId, plan: CheckoutPlanId, interval: BillingInterval }).passthrough()
|
|
23375
|
+
}).passthrough();
|
|
23376
|
+
StripeInvoiceObject = external_exports.object({
|
|
23377
|
+
id: external_exports.string().min(1),
|
|
23378
|
+
customer: external_exports.string().min(1),
|
|
23379
|
+
subscription: external_exports.string().min(1).nullable(),
|
|
23380
|
+
status: external_exports.enum(["draft", "open", "paid", "void", "uncollectible"]),
|
|
23381
|
+
amount_due: external_exports.number().int().nonnegative(),
|
|
23382
|
+
amount_paid: external_exports.number().int().nonnegative(),
|
|
23383
|
+
period_start: epochSeconds,
|
|
23384
|
+
period_end: epochSeconds,
|
|
23385
|
+
attempt_count: external_exports.number().int().nonnegative().default(0),
|
|
23386
|
+
metadata: external_exports.object({ tenantId: TenantId.optional() }).passthrough().default({})
|
|
23387
|
+
}).passthrough();
|
|
23388
|
+
StripeCheckoutObject = external_exports.object({
|
|
23389
|
+
id: external_exports.string().min(1),
|
|
23390
|
+
customer: external_exports.string().min(1),
|
|
23391
|
+
subscription: external_exports.string().min(1).nullable(),
|
|
23392
|
+
metadata: external_exports.object({ tenantId: TenantId }).passthrough()
|
|
23393
|
+
}).passthrough();
|
|
23394
|
+
StripeEvent = external_exports.object({
|
|
23395
|
+
id: external_exports.string().min(1),
|
|
23396
|
+
type: external_exports.string().min(1),
|
|
23397
|
+
created: epochSeconds,
|
|
23398
|
+
data: external_exports.object({ object: external_exports.record(external_exports.string(), external_exports.unknown()) })
|
|
23399
|
+
}).passthrough();
|
|
23400
|
+
WEBHOOK_OUTCOMES = ["applied", "replayed", "stale", "ignored"];
|
|
23401
|
+
WebhookOutcome = external_exports.enum(WEBHOOK_OUTCOMES);
|
|
23402
|
+
WebhookResult = external_exports.object({ ok: external_exports.literal(true), outcome: WebhookOutcome, eventId: external_exports.string().min(1) }).strict();
|
|
23403
|
+
billingPaths = {
|
|
23404
|
+
status: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing`,
|
|
23405
|
+
checkout: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/checkout`,
|
|
23406
|
+
plan: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/plan`,
|
|
23407
|
+
seats: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/seats`,
|
|
23408
|
+
cancel: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/cancel`,
|
|
23409
|
+
portal: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/portal`,
|
|
23410
|
+
usage: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/usage`,
|
|
23411
|
+
decision: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/usage/decision`,
|
|
23412
|
+
caps: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/caps`,
|
|
23413
|
+
invoices: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/invoices`,
|
|
23414
|
+
limits: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/billing/limits`,
|
|
23415
|
+
stripeWebhook: "/webhooks/billing/stripe",
|
|
23416
|
+
workosWebhook: "/webhooks/billing/workos"
|
|
23417
|
+
};
|
|
23418
|
+
}
|
|
23419
|
+
});
|
|
23420
|
+
|
|
23052
23421
|
// ../contracts/src/index.ts
|
|
23053
23422
|
var init_src = __esm({
|
|
23054
23423
|
"../contracts/src/index.ts"() {
|
|
@@ -23079,6 +23448,8 @@ var init_src = __esm({
|
|
|
23079
23448
|
init_review();
|
|
23080
23449
|
init_guardrails();
|
|
23081
23450
|
init_code_map();
|
|
23451
|
+
init_plans();
|
|
23452
|
+
init_billing();
|
|
23082
23453
|
}
|
|
23083
23454
|
});
|
|
23084
23455
|
|
|
@@ -30431,7 +30802,7 @@ var VERSION;
|
|
|
30431
30802
|
var init_assets = __esm({
|
|
30432
30803
|
"src/assets.ts"() {
|
|
30433
30804
|
"use strict";
|
|
30434
|
-
VERSION = true ? "0.1.
|
|
30805
|
+
VERSION = true ? "0.1.124" : "0.0.0-dev";
|
|
30435
30806
|
}
|
|
30436
30807
|
});
|
|
30437
30808
|
|
|
@@ -59337,19 +59708,287 @@ var tokenRevokeCommand = defineCommand({
|
|
|
59337
59708
|
});
|
|
59338
59709
|
var identityCommands = [authLoginCommand, authLogoutCommand, authTokenCommand, teamListCommand, teamInviteCommand, tokenCreateCommand, tokenListCommand, tokenRevokeCommand];
|
|
59339
59710
|
|
|
59340
|
-
// ../cli/src/commands/
|
|
59711
|
+
// ../cli/src/commands/billing.ts
|
|
59341
59712
|
init_src();
|
|
59342
59713
|
init_zod();
|
|
59343
59714
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
59344
|
-
import { readFileSync as readFileSync8 } from "node:fs";
|
|
59345
|
-
import { resolve as resolve8 } from "node:path";
|
|
59346
59715
|
var common2 = { needsAuth: true, needsNetwork: true };
|
|
59347
59716
|
var requestId3 = () => `cli-${randomUUID3()}`;
|
|
59348
59717
|
async function connected(inv) {
|
|
59718
|
+
const project = await connectedProject(inv.deps, "billing");
|
|
59719
|
+
return { call: serviceCall(inv.deps, project.serviceUrl, project.token), tenantId: project.binding.tenantId };
|
|
59720
|
+
}
|
|
59721
|
+
async function planned(inv, method, path, body2, note) {
|
|
59722
|
+
const project = await offlineProject(inv.deps, "billing");
|
|
59723
|
+
return planOutcome(inv.deps, dryRunPlan({ service: project.serviceUrl, requests: [{ method, path: path(project.binding.tenantId), ...body2 === void 0 ? {} : { body: body2 }, ...note === void 0 ? {} : { note } }] }));
|
|
59724
|
+
}
|
|
59725
|
+
var usd = (cents) => `$${Math.trunc(cents / 100)}.${String(cents % 100).padStart(2, "0")}`;
|
|
59726
|
+
var micros = (value) => value % 1e4 === 0 ? usd(value / 1e4) : `$${(value / 1e6).toFixed(3)}`;
|
|
59727
|
+
function parseUsdToCents(text) {
|
|
59728
|
+
const match = /^(\d{1,7})(?:\.(\d{1,2}))?$/.exec(text.trim());
|
|
59729
|
+
if (match === null) throw new UsageError("--usd must be an amount like 50 or 12.50", { hint: "overlane billing caps set --scope team --usd 50" });
|
|
59730
|
+
return Number(match[1]) * 100 + Number((match[2] ?? "").padEnd(2, "0") || "0");
|
|
59731
|
+
}
|
|
59732
|
+
function positiveInt(text, flag) {
|
|
59733
|
+
if (text === void 0) return void 0;
|
|
59734
|
+
if (!/^\d+$/.test(text) || Number(text) < 1) throw new UsageError(`--${flag} must be a whole number of at least 1`);
|
|
59735
|
+
return Number(text);
|
|
59736
|
+
}
|
|
59737
|
+
var PLAN_FLAG = (plans, required2) => ({ name: "plan", type: "string", required: required2, enum: plans, value: "PLAN", description: "The plan" });
|
|
59738
|
+
var INTERVAL_FLAG = { name: "interval", type: "string", enum: ["month", "year"], value: "month|year", description: "Billing period; annual billing is cheaper per month" };
|
|
59739
|
+
var SEATS_FLAG = { name: "seats", type: "string", value: "N", description: "Seats (Business needs at least 10; Pro is one person)" };
|
|
59740
|
+
var billingStatusCommand = defineCommand({
|
|
59741
|
+
path: ["billing", "status"],
|
|
59742
|
+
summary: "Show the plan, seats, usage against allowances, caps, grace period and invoices",
|
|
59743
|
+
description: "Shows what this workspace is on, what the plan allows (from the one plan data file the pricing page also reads), what is used this period, any spending caps, and whether a failed payment has started a grace period. Read-only for every role, agents included.",
|
|
59744
|
+
examples: ["overlane billing status", "overlane billing status --json"],
|
|
59745
|
+
effect: "read",
|
|
59746
|
+
...common2,
|
|
59747
|
+
keywords: ["billing", "plan", "subscription", "invoice", "what plan am i on", "seats", "grace period", "read-only"],
|
|
59748
|
+
result: BillingStatus,
|
|
59749
|
+
text: (d) => [
|
|
59750
|
+
`plan: ${d.subscription.plan} (${d.subscription.status}), ${d.subscription.seats} seat${d.subscription.seats === 1 ? "" : "s"}, ${d.subscription.interval}ly${d.subscription.cancelAtPeriodEnd ? ", ends at the period end" : ""}`,
|
|
59751
|
+
...d.limits.readOnly ? ["this workspace is READ-ONLY: nothing was deleted; reading works"] : [],
|
|
59752
|
+
...d.grace.state === "none" ? [] : [`payment: ${d.grace.state}${d.grace.endsAt === void 0 ? "" : ` until ${d.grace.endsAt.slice(0, 10)}`}`],
|
|
59753
|
+
...d.usage.meters.map((m) => `${m.meter}: ${m.used}${typeof m.allowance === "number" ? ` of ${m.allowance}` : m.allowance === "unlimited" ? " (unlimited)" : ""}${m.overageMicros > 0 ? `, overage ${micros(m.overageMicros)}` : ""}`),
|
|
59754
|
+
`metered spend this period: ${micros(d.usage.spendMicros)}`,
|
|
59755
|
+
...d.caps.map((c) => `cap ${c.scope}${c.scopeId === void 0 ? "" : ` ${c.scopeId}`}: ${usd(c.limitCents)}`),
|
|
59756
|
+
...d.usage.notices,
|
|
59757
|
+
...d.grace.notices.slice(-1).map((n) => n.message),
|
|
59758
|
+
...d.live ? [] : ["payments: not connected to Stripe in this deployment (live leg pending)"]
|
|
59759
|
+
],
|
|
59760
|
+
handler: async (inv) => {
|
|
59761
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59762
|
+
return { data: await call2(BillingStatus, "GET", billingPaths.status(tenantId)) };
|
|
59763
|
+
}
|
|
59764
|
+
});
|
|
59765
|
+
var billingUsageCommand = defineCommand({
|
|
59766
|
+
path: ["billing", "usage"],
|
|
59767
|
+
summary: "Show usage this period against each allowance, with the overage price from the plan data file",
|
|
59768
|
+
description: "Lists reviews, CI minutes, docs calls and hosted inference used this period, the allowance each plan gives, units beyond it and what they cost. Beyond an allowance nothing stops unless a spending cap is set.",
|
|
59769
|
+
examples: ["overlane billing usage", "overlane billing usage --json"],
|
|
59770
|
+
effect: "read",
|
|
59771
|
+
...common2,
|
|
59772
|
+
keywords: ["usage", "allowance", "overage", "reviews used", "ci minutes", "how much have i used"],
|
|
59773
|
+
result: UsageSummary,
|
|
59774
|
+
text: (d) => [`period: ${d.periodStart.slice(0, 10)} to ${d.periodEnd.slice(0, 10)}`, ...d.meters.map((m) => `${m.meter}: ${m.used}${typeof m.allowance === "number" ? ` / ${m.allowance}` : ""}${m.rateMicros === null ? "" : ` (${micros(m.rateMicros)} each beyond)`}${m.overageMicros > 0 ? ` overage ${micros(m.overageMicros)}` : ""}`), `metered spend: ${micros(d.spendMicros)}`, ...d.notices],
|
|
59775
|
+
handler: async (inv) => {
|
|
59776
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59777
|
+
return { data: await call2(UsageSummary, "GET", billingPaths.usage(tenantId)) };
|
|
59778
|
+
}
|
|
59779
|
+
});
|
|
59780
|
+
var billingCheckCommand = defineCommand({
|
|
59781
|
+
path: ["billing", "check"],
|
|
59782
|
+
summary: "Ask whether a spend is allowed now; exits 6 when a limit or cap refuses it",
|
|
59783
|
+
description: "Asks the billing service before a review, CI run or hosted inference call: within the allowance, over it and billed (with a notice), or refused (a plan with no overage path, a reached spending cap, a read-only workspace). A refusal exits 6 and names the next command.",
|
|
59784
|
+
flags: [
|
|
59785
|
+
{ name: "meter", type: "string", required: true, enum: METERS, value: "METER", description: "What is being spent" },
|
|
59786
|
+
{ name: "quantity", type: "string", value: "N", description: "Units, default 1" },
|
|
59787
|
+
{ name: "cost-micros", type: "string", value: "N", description: "Provider cost of a hosted inference call, in millionths of a dollar" },
|
|
59788
|
+
{ name: "project", type: "string", value: "ID", description: "The project, for a project cap" },
|
|
59789
|
+
{ name: "agent", type: "string", value: "ID", description: "The agent token, for an agent cap" },
|
|
59790
|
+
{ name: "byok", type: "boolean", description: "The call runs on your own key: no platform charge" }
|
|
59791
|
+
],
|
|
59792
|
+
examples: ["overlane billing check --meter reviews", "overlane billing check --meter hostedInference --cost-micros 2000 --agent tok_1"],
|
|
59793
|
+
effect: "read",
|
|
59794
|
+
...common2,
|
|
59795
|
+
keywords: ["can i spend", "spending cap reached", "limit check", "exit 6", "budget gate"],
|
|
59796
|
+
result: UsageDecision,
|
|
59797
|
+
text: (d) => [`${d.allowed ? "ALLOWED" : "REFUSED"} (${d.outcome}) ${d.message}`, ...d.nextCommand === null ? [] : [`next: ${d.nextCommand}`]],
|
|
59798
|
+
handler: async (inv) => {
|
|
59799
|
+
const meter = textFlag(inv, "meter");
|
|
59800
|
+
if (meter === void 0) throw new UsageError("check needs --meter", { hint: "overlane billing check --meter reviews" });
|
|
59801
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59802
|
+
const quantity = positiveInt(textFlag(inv, "quantity"), "quantity");
|
|
59803
|
+
const cost = textFlag(inv, "cost-micros");
|
|
59804
|
+
const body2 = { meter, ...quantity === void 0 ? {} : { quantity }, ...cost === void 0 ? {} : { costMicros: Number(cost) }, ...textFlag(inv, "project") === void 0 ? {} : { projectId: textFlag(inv, "project") }, ...textFlag(inv, "agent") === void 0 ? {} : { agentId: textFlag(inv, "agent") }, ...boolFlag(inv, "byok") ? { byok: true } : {} };
|
|
59805
|
+
const decision = await call2(UsageDecision, "POST", billingPaths.decision(tenantId), body2);
|
|
59806
|
+
return decision.allowed ? { data: decision } : { data: decision, exit: EXIT.blocked, error: new CliError(decision.message, { code: decision.outcome, exit: EXIT.blocked, ...decision.nextCommand === null ? {} : { hint: decision.nextCommand } }) };
|
|
59807
|
+
}
|
|
59808
|
+
});
|
|
59809
|
+
var billingCheckoutCommand = defineCommand({
|
|
59810
|
+
path: ["billing", "checkout"],
|
|
59811
|
+
summary: "Start buying a plan: prints a Stripe-hosted checkout link (a person pays; agents cannot)",
|
|
59812
|
+
description: "Opens a checkout for Pro, Team or Business. Business needs at least 10 seats. The link is a Stripe-hosted page where the card is entered; Overlane never sees it. The plan is active when the payment webhook arrives. Enterprise is contract-only.",
|
|
59813
|
+
flags: [PLAN_FLAG(["pro", "team", "business"], true), INTERVAL_FLAG, SEATS_FLAG],
|
|
59814
|
+
examples: ["overlane billing checkout --plan team --seats 5", "overlane billing checkout --plan business --seats 10 --interval year --dry-run"],
|
|
59815
|
+
effect: "write",
|
|
59816
|
+
...common2,
|
|
59817
|
+
keywords: ["upgrade", "buy", "subscribe", "pay", "checkout", "choose plan"],
|
|
59818
|
+
result: withDryRun(CheckoutResponse),
|
|
59819
|
+
text: (d) => "url" in d ? [`${d.plan} x ${d.seats} (${d.interval}ly): first period ${usd(d.firstPeriodCents)} before tax`, `open: ${d.url}`] : [],
|
|
59820
|
+
handler: async (inv) => {
|
|
59821
|
+
const body2 = { requestId: requestId3(), plan: textFlag(inv, "plan"), interval: textFlag(inv, "interval") ?? "month", ...textFlag(inv, "seats") === void 0 ? {} : { seats: positiveInt(textFlag(inv, "seats"), "seats") } };
|
|
59822
|
+
if (inv.dryRun) return planned(inv, "POST", billingPaths.checkout, body2, "opens a Stripe-hosted checkout; nothing is charged");
|
|
59823
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59824
|
+
return { data: await call2(CheckoutResponse, "POST", billingPaths.checkout(tenantId), body2) };
|
|
59825
|
+
}
|
|
59826
|
+
});
|
|
59827
|
+
var billingPlanCommand = defineCommand({
|
|
59828
|
+
path: ["billing", "plan"],
|
|
59829
|
+
summary: "Upgrade or downgrade the plan; a downgrade over the new limits makes the workspace read-only and deletes nothing",
|
|
59830
|
+
description: "Changes a paid plan with proration for the rest of the period. `--plan free` ends the paid plan at the end of the period already paid for. If data is over the new plan's limits the workspace becomes read-only (reads keep working) and nothing is ever deleted; upgrading restores it.",
|
|
59831
|
+
flags: [PLAN_FLAG(["free", "pro", "team", "business"], true), INTERVAL_FLAG, SEATS_FLAG],
|
|
59832
|
+
examples: ["overlane billing plan --plan team --seats 4", "overlane billing plan --plan free --dry-run"],
|
|
59833
|
+
effect: "write",
|
|
59834
|
+
...common2,
|
|
59835
|
+
keywords: ["downgrade", "upgrade", "change plan", "switch plan", "go back to free"],
|
|
59836
|
+
result: withDryRun(ChangePlanResponse),
|
|
59837
|
+
text: (d) => "subscription" in d ? [`plan: ${d.subscription.plan}, ${d.subscription.seats} seats`, `proration: ${d.prorationCents >= 0 ? "charge" : "credit"} ${usd(Math.abs(d.prorationCents))}`, ...d.overLimit.map((o) => `over the limit: ${o.what} ${o.used} of ${o.limit}; the workspace is read-only, nothing is deleted`)] : [],
|
|
59838
|
+
handler: async (inv) => {
|
|
59839
|
+
const body2 = { requestId: requestId3(), plan: textFlag(inv, "plan"), ...textFlag(inv, "interval") === void 0 ? {} : { interval: textFlag(inv, "interval") }, ...textFlag(inv, "seats") === void 0 ? {} : { seats: positiveInt(textFlag(inv, "seats"), "seats") } };
|
|
59840
|
+
if (inv.dryRun) return planned(inv, "POST", billingPaths.plan, body2, "prorates the rest of the period");
|
|
59841
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59842
|
+
return { data: await call2(ChangePlanResponse, "POST", billingPaths.plan(tenantId), body2) };
|
|
59843
|
+
}
|
|
59844
|
+
});
|
|
59845
|
+
var billingSeatsCommand = defineCommand({
|
|
59846
|
+
path: ["billing", "seats"],
|
|
59847
|
+
summary: "Change the number of seats mid-cycle; the change prorates",
|
|
59848
|
+
description: "Sets the seat count on a per-seat plan. The charge or credit for the rest of the period is prorated by the second. Business never goes below 10 seats, and seats cannot drop below the people who hold one.",
|
|
59849
|
+
flags: [{ ...SEATS_FLAG, required: true }],
|
|
59850
|
+
examples: ["overlane billing seats --seats 8", "overlane billing seats --seats 12 --dry-run"],
|
|
59851
|
+
effect: "write",
|
|
59852
|
+
...common2,
|
|
59853
|
+
keywords: ["add seats", "remove seats", "more people", "proration", "seat count"],
|
|
59854
|
+
result: withDryRun(SeatChangeResponse),
|
|
59855
|
+
text: (d) => "seat" in d ? [`seats: ${d.seat.purchased} (${d.seat.assigned} in use)`, `proration: ${d.prorationCents >= 0 ? "charge" : "credit"} ${usd(Math.abs(d.prorationCents))}`] : [],
|
|
59856
|
+
handler: async (inv) => {
|
|
59857
|
+
const body2 = { requestId: requestId3(), seats: positiveInt(textFlag(inv, "seats"), "seats") };
|
|
59858
|
+
if (inv.dryRun) return planned(inv, "POST", billingPaths.seats, body2, "prorates the rest of the period");
|
|
59859
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59860
|
+
return { data: await call2(SeatChangeResponse, "POST", billingPaths.seats(tenantId), body2) };
|
|
59861
|
+
}
|
|
59862
|
+
});
|
|
59863
|
+
var billingCancelCommand = defineCommand({
|
|
59864
|
+
path: ["billing", "cancel"],
|
|
59865
|
+
summary: "Cancel the paid plan at the end of the period already paid for",
|
|
59866
|
+
description: "Cancels at the period end by default, so everything keeps working until then. With --now the plan ends immediately. Data over the Free limits becomes read-only; nothing is deleted.",
|
|
59867
|
+
flags: [{ name: "now", type: "boolean", description: "End the plan immediately instead of at the period end" }],
|
|
59868
|
+
examples: ["overlane billing cancel", "overlane billing cancel --dry-run"],
|
|
59869
|
+
effect: "destructive",
|
|
59870
|
+
...common2,
|
|
59871
|
+
keywords: ["cancel subscription", "stop paying", "end plan"],
|
|
59872
|
+
result: withDryRun(Subscription),
|
|
59873
|
+
text: (d) => "plan" in d ? [`plan: ${d.plan}${d.cancelAtPeriodEnd ? `, ends ${d.currentPeriodEnd.slice(0, 10)}` : ""}`] : [],
|
|
59874
|
+
handler: async (inv) => {
|
|
59875
|
+
const body2 = { requestId: requestId3(), atPeriodEnd: !boolFlag(inv, "now") };
|
|
59876
|
+
if (inv.dryRun) return planned(inv, "POST", billingPaths.cancel, body2);
|
|
59877
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59878
|
+
return { data: await call2(Subscription, "POST", billingPaths.cancel(tenantId), body2) };
|
|
59879
|
+
}
|
|
59880
|
+
});
|
|
59881
|
+
var billingPortalCommand = defineCommand({
|
|
59882
|
+
path: ["billing", "portal"],
|
|
59883
|
+
summary: "Print a link to Stripe's billing portal: card, invoices and tax details",
|
|
59884
|
+
description: "Opens a Stripe-hosted portal where a person updates the card, downloads invoices and edits tax details. Overlane never stores card data.",
|
|
59885
|
+
examples: ["overlane billing portal"],
|
|
59886
|
+
effect: "write",
|
|
59887
|
+
...common2,
|
|
59888
|
+
keywords: ["update card", "invoices", "tax id", "payment method", "billing portal"],
|
|
59889
|
+
result: withDryRun(PortalResponse),
|
|
59890
|
+
text: (d) => "url" in d ? [`open: ${d.url}`] : [],
|
|
59891
|
+
handler: async (inv) => {
|
|
59892
|
+
if (inv.dryRun) return planned(inv, "POST", billingPaths.portal, {});
|
|
59893
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59894
|
+
return { data: await call2(PortalResponse, "POST", billingPaths.portal(tenantId), {}) };
|
|
59895
|
+
}
|
|
59896
|
+
});
|
|
59897
|
+
var CapList = external_exports.object({ tenantId: external_exports.string(), caps: external_exports.array(Cap) }).strict();
|
|
59898
|
+
var CapRemoved = external_exports.object({ tenantId: external_exports.string(), removed: external_exports.literal(true) }).strict();
|
|
59899
|
+
var CAP_FLAGS = [
|
|
59900
|
+
{ name: "scope", type: "string", required: true, enum: CAP_SCOPES, value: "SCOPE", description: "team, project or agent" },
|
|
59901
|
+
{ name: "id", type: "string", value: "ID", description: "The project or agent token the cap applies to (not for team)" }
|
|
59902
|
+
];
|
|
59903
|
+
function capTarget(inv) {
|
|
59904
|
+
const scope = textFlag(inv, "scope");
|
|
59905
|
+
const id2 = textFlag(inv, "id");
|
|
59906
|
+
if (scope === void 0) throw new UsageError("this command needs --scope", { hint: "overlane billing caps set --scope team --usd 50" });
|
|
59907
|
+
if (scope === "team" && id2 !== void 0) throw new UsageError("a team cap has no --id");
|
|
59908
|
+
if (scope !== "team" && id2 === void 0) throw new UsageError(`a ${scope} cap needs --id`, { hint: `overlane billing caps set --scope ${scope} --id <${scope} id> --usd 50` });
|
|
59909
|
+
return { scope, ...id2 === void 0 ? {} : { scopeId: id2 } };
|
|
59910
|
+
}
|
|
59911
|
+
var billingCapsListCommand = defineCommand({
|
|
59912
|
+
path: ["billing", "caps", "list"],
|
|
59913
|
+
summary: "List spending caps per team, project and agent",
|
|
59914
|
+
description: "Shows each cap in dollars per billing period. With a cap set, reviews, CI and hosted inference stop at it (exit 6); with none, usage beyond an allowance is billed.",
|
|
59915
|
+
examples: ["overlane billing caps list", "overlane billing caps list --json"],
|
|
59916
|
+
effect: "read",
|
|
59917
|
+
...common2,
|
|
59918
|
+
keywords: ["spending cap", "budget", "limit spend", "caps"],
|
|
59919
|
+
result: CapList,
|
|
59920
|
+
text: (d) => d.caps.length === 0 ? ["No spending caps: usage beyond an allowance is billed, nothing stops."] : d.caps.map((c) => `${c.scope}${c.scopeId === void 0 ? "" : ` ${c.scopeId}`}: ${usd(c.limitCents)} per period`),
|
|
59921
|
+
handler: async (inv) => {
|
|
59922
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59923
|
+
return { data: await call2(CapList, "GET", billingPaths.caps(tenantId)) };
|
|
59924
|
+
}
|
|
59925
|
+
});
|
|
59926
|
+
var billingCapsSetCommand = defineCommand({
|
|
59927
|
+
path: ["billing", "caps", "set"],
|
|
59928
|
+
summary: "Set a spending cap per period for the team, a project or an agent",
|
|
59929
|
+
description: "Sets the most metered spend (overage plus hosted inference with markup) allowed per billing period. At the cap, hosted inference, AI reviews and CI stop with exit code 6 and a visible message until the next period or until the cap is raised. Only a signed-in owner can set one.",
|
|
59930
|
+
flags: [...CAP_FLAGS, { name: "usd", type: "string", required: true, value: "AMOUNT", description: "Dollars per period, for example 50 or 12.50" }],
|
|
59931
|
+
examples: ["overlane billing caps set --scope team --usd 50", "overlane billing caps set --scope agent --id tok_1 --usd 5 --dry-run"],
|
|
59932
|
+
effect: "write",
|
|
59933
|
+
...common2,
|
|
59934
|
+
keywords: ["set cap", "limit spending", "budget", "stop at"],
|
|
59935
|
+
result: withDryRun(Cap),
|
|
59936
|
+
text: (d) => "limitCents" in d ? [`cap ${d.scope}${d.scopeId === void 0 ? "" : ` ${d.scopeId}`}: ${usd(d.limitCents)} per period`] : [],
|
|
59937
|
+
handler: async (inv) => {
|
|
59938
|
+
const target = capTarget(inv);
|
|
59939
|
+
const usdText = textFlag(inv, "usd");
|
|
59940
|
+
if (usdText === void 0) throw new UsageError("set needs --usd", { hint: "overlane billing caps set --scope team --usd 50" });
|
|
59941
|
+
const body2 = { requestId: requestId3(), ...target, limitCents: parseUsdToCents(usdText) };
|
|
59942
|
+
if (inv.dryRun) return planned(inv, "PUT", billingPaths.caps, body2);
|
|
59943
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59944
|
+
return { data: await call2(Cap, "PUT", billingPaths.caps(tenantId), body2) };
|
|
59945
|
+
}
|
|
59946
|
+
});
|
|
59947
|
+
var billingCapsRemoveCommand = defineCommand({
|
|
59948
|
+
path: ["billing", "caps", "remove"],
|
|
59949
|
+
summary: "Remove a spending cap",
|
|
59950
|
+
description: "Removes a cap. Without a team cap, usage beyond an allowance is billed and nothing stops.",
|
|
59951
|
+
flags: CAP_FLAGS,
|
|
59952
|
+
examples: ["overlane billing caps remove --scope team", "overlane billing caps remove --scope project --id prj_1 --dry-run"],
|
|
59953
|
+
effect: "write",
|
|
59954
|
+
...common2,
|
|
59955
|
+
keywords: ["remove cap", "no limit", "delete cap"],
|
|
59956
|
+
result: withDryRun(CapRemoved),
|
|
59957
|
+
text: (d) => "removed" in d ? ["Cap removed."] : [],
|
|
59958
|
+
handler: async (inv) => {
|
|
59959
|
+
const body2 = { requestId: requestId3(), ...capTarget(inv) };
|
|
59960
|
+
if (inv.dryRun) return planned(inv, "DELETE", billingPaths.caps, body2);
|
|
59961
|
+
const { call: call2, tenantId } = await connected(inv);
|
|
59962
|
+
return { data: await call2(CapRemoved, "DELETE", billingPaths.caps(tenantId), body2) };
|
|
59963
|
+
}
|
|
59964
|
+
});
|
|
59965
|
+
var billingCommands = [
|
|
59966
|
+
billingStatusCommand,
|
|
59967
|
+
billingUsageCommand,
|
|
59968
|
+
billingCheckCommand,
|
|
59969
|
+
billingCheckoutCommand,
|
|
59970
|
+
billingPlanCommand,
|
|
59971
|
+
billingSeatsCommand,
|
|
59972
|
+
billingCancelCommand,
|
|
59973
|
+
billingPortalCommand,
|
|
59974
|
+
billingCapsListCommand,
|
|
59975
|
+
billingCapsSetCommand,
|
|
59976
|
+
billingCapsRemoveCommand
|
|
59977
|
+
];
|
|
59978
|
+
|
|
59979
|
+
// ../cli/src/commands/guard.ts
|
|
59980
|
+
init_src();
|
|
59981
|
+
init_zod();
|
|
59982
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
59983
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
59984
|
+
import { resolve as resolve8 } from "node:path";
|
|
59985
|
+
var common3 = { needsAuth: true, needsNetwork: true };
|
|
59986
|
+
var requestId4 = () => `cli-${randomUUID4()}`;
|
|
59987
|
+
async function connected2(inv) {
|
|
59349
59988
|
const project = await connectedProject(inv.deps, "guard");
|
|
59350
59989
|
return { project, call: serviceCall(inv.deps, project.serviceUrl, project.token), tenantId: project.binding.tenantId, projectId: project.binding.projectId };
|
|
59351
59990
|
}
|
|
59352
|
-
async function
|
|
59991
|
+
async function planned2(inv, method, path, body2, note) {
|
|
59353
59992
|
const project = await offlineProject(inv.deps, "guard");
|
|
59354
59993
|
return planOutcome(inv.deps, dryRunPlan({ service: project.serviceUrl, requests: [{ method, path: path(project.binding.tenantId), ...body2 === void 0 ? {} : { body: body2 }, ...note === void 0 ? {} : { note } }] }));
|
|
59355
59994
|
}
|
|
@@ -59398,12 +60037,12 @@ var guardRulesListCommand = defineCommand({
|
|
|
59398
60037
|
description: "Lists the platform rules (always in force), then the team and project rule files and their rules. A rule change is an audit event; every file version is listed with its digest and author.",
|
|
59399
60038
|
examples: ["overlane guard rules list", "overlane guard rules list --json"],
|
|
59400
60039
|
effect: "read",
|
|
59401
|
-
...
|
|
60040
|
+
...common3,
|
|
59402
60041
|
keywords: ["guardrails", "policy as code", "rules in force", "protected branches", "what is blocked", "rule files"],
|
|
59403
60042
|
result: GuardRulesResponse,
|
|
59404
60043
|
text: (d) => [...d.rules.map((rule) => `${rule.layer.padEnd(8)} ${rule.effect.padEnd(16)} ${rule.id}${rule.dryRun ? " [dry-run]" : ""} ${rule.description}`), ...d.files.map((file2) => `file ${file2.layer} v${file2.version} ${file2.digest.slice(0, 19)} by ${file2.author}`)],
|
|
59405
60044
|
handler: async (inv) => {
|
|
59406
|
-
const { call: call2, tenantId, projectId } = await
|
|
60045
|
+
const { call: call2, tenantId, projectId } = await connected2(inv);
|
|
59407
60046
|
return { data: await call2(GuardRulesResponse, "GET", `${guardPaths.rules(tenantId)}?projectId=${encodeURIComponent(projectId)}`) };
|
|
59408
60047
|
}
|
|
59409
60048
|
});
|
|
@@ -59473,7 +60112,7 @@ var guardRulesPutCommand = defineCommand({
|
|
|
59473
60112
|
],
|
|
59474
60113
|
examples: ['overlane guard rules put --file rules.json --reason "freeze deploys on Fridays"', "overlane guard rules put --file rules.json --layer project --dry-run"],
|
|
59475
60114
|
effect: "write",
|
|
59476
|
-
...
|
|
60115
|
+
...common3,
|
|
59477
60116
|
keywords: ["publish rules", "update guardrails", "change policy", "upload rule file", "freeze deploys"],
|
|
59478
60117
|
result: withDryRun(GuardRuleFileRecord),
|
|
59479
60118
|
text: (d) => "version" in d ? [`Published ${d.layer} rule file v${d.version} (${d.ruleCount} rules, ${d.digest.slice(0, 19)}).`] : [],
|
|
@@ -59487,12 +60126,12 @@ var guardRulesPutCommand = defineCommand({
|
|
|
59487
60126
|
return planOutcome(inv.deps, dryRunPlan({ service: offline.serviceUrl, requests: [{ method: "PUT", path: guardPaths.rules(offline.binding.tenantId), body: { requestId: "<generated>", layer, ...layer === "project" ? { projectId: offline.binding.projectId } : {}, content: `<contents of ${file2}>`, ...reason === void 0 ? {} : { reason } }, note: "the file is validated and scanned for credentials on the server" }] }));
|
|
59488
60127
|
}
|
|
59489
60128
|
const content = readText3(inv, file2);
|
|
59490
|
-
const { call: call2, tenantId, projectId } = await
|
|
59491
|
-
return { data: await call2(GuardRuleFileRecord, "PUT", guardPaths.rules(tenantId), { requestId:
|
|
60129
|
+
const { call: call2, tenantId, projectId } = await connected2(inv);
|
|
60130
|
+
return { data: await call2(GuardRuleFileRecord, "PUT", guardPaths.rules(tenantId), { requestId: requestId4(), layer, ...layer === "project" ? { projectId } : {}, content, ...reason === void 0 ? {} : { reason } }) };
|
|
59492
60131
|
}
|
|
59493
60132
|
});
|
|
59494
60133
|
async function evaluate(inv, dryRun) {
|
|
59495
|
-
const { call: call2, tenantId, projectId } = await
|
|
60134
|
+
const { call: call2, tenantId, projectId } = await connected2(inv);
|
|
59496
60135
|
const contentFile = textFlag(inv, "content-file");
|
|
59497
60136
|
const body2 = {
|
|
59498
60137
|
...actionOf(inv),
|
|
@@ -59518,12 +60157,12 @@ var guardCheckCommand = defineCommand({
|
|
|
59518
60157
|
flags: [...DECISION_FLAGS, { name: "approval", type: "string", value: "ID", description: "An approval that covers exactly this action" }],
|
|
59519
60158
|
examples: ["overlane guard check --tool git.push --branch main --task held", 'overlane guard check --tool deploy.run --environment production --summary "Deploy build 42" --dry-run'],
|
|
59520
60159
|
effect: "write",
|
|
59521
|
-
...
|
|
60160
|
+
...common3,
|
|
59522
60161
|
keywords: ["check action", "pre push check", "ci gate", "is this allowed", "approval required", "blocked by policy"],
|
|
59523
60162
|
result: withDryRun(GuardEvaluateResponse),
|
|
59524
60163
|
text: (d) => "decision" in d ? describeDecision(d.decision) : [],
|
|
59525
60164
|
handler: async (inv) => {
|
|
59526
|
-
if (inv.dryRun) return
|
|
60165
|
+
if (inv.dryRun) return planned2(inv, "POST", guardPaths.evaluate, { ...actionOf(inv) }, "the decision is recorded; a rule that needs approval opens one");
|
|
59527
60166
|
const reply = await evaluate(inv, false);
|
|
59528
60167
|
return reply.decision.allowed ? { data: reply } : refusalOutcome(reply, reply.decision);
|
|
59529
60168
|
}
|
|
@@ -59535,7 +60174,7 @@ var guardDryRunCommand = defineCommand({
|
|
|
59535
60174
|
flags: DECISION_FLAGS,
|
|
59536
60175
|
examples: ["overlane guard dry-run --tool git.push --branch main --task held", "overlane guard dry-run --tool egress.fetch --host registry.example.com --json"],
|
|
59537
60176
|
effect: "read",
|
|
59538
|
-
...
|
|
60177
|
+
...common3,
|
|
59539
60178
|
keywords: ["dry run rules", "what would block", "test policy", "simulate", "would be refused"],
|
|
59540
60179
|
result: GuardEvaluateResponse,
|
|
59541
60180
|
text: (d) => describeDecision(d.decision),
|
|
@@ -59551,14 +60190,14 @@ var guardScanCommand = defineCommand({
|
|
|
59551
60190
|
],
|
|
59552
60191
|
examples: ["overlane guard scan --path src/config.ts", "overlane guard scan --path ci.log --source log --json"],
|
|
59553
60192
|
effect: "read",
|
|
59554
|
-
...
|
|
60193
|
+
...common3,
|
|
59555
60194
|
keywords: ["secret scan", "find credentials", "leaked key", "push protection", "scan file"],
|
|
59556
60195
|
result: SecretScanResult,
|
|
59557
60196
|
text: (d) => d.findings.length === 0 ? ["No credentials found."] : d.findings.map((finding) => `${finding.disposition.padEnd(8)} ${finding.rule}${finding.path === void 0 ? "" : ` ${finding.path}`}${finding.line === void 0 ? "" : `:${finding.line}`}`),
|
|
59558
60197
|
handler: async (inv) => {
|
|
59559
60198
|
const path = textFlag(inv, "path");
|
|
59560
60199
|
if (path === void 0) throw new UsageError("scan needs --path", { hint: "overlane guard scan --path src/config.ts" });
|
|
59561
|
-
const { call: call2, tenantId } = await
|
|
60200
|
+
const { call: call2, tenantId } = await connected2(inv);
|
|
59562
60201
|
const result = await call2(SecretScanResult, "POST", guardPaths.scan(tenantId), { source: textFlag(inv, "source") ?? "push", content: readText3(inv, path), path });
|
|
59563
60202
|
return result.blocked ? { data: result, exit: EXIT.blocked, error: new CliError("a credential was found; nothing should be pushed until it is removed and rotated", { code: "secret_detected", exit: EXIT.blocked, hint: "overlane guard scan --path <file>" }) } : { data: result };
|
|
59564
60203
|
}
|
|
@@ -59571,12 +60210,12 @@ var guardApprovalsListCommand = defineCommand({
|
|
|
59571
60210
|
flags: [{ name: "status", type: "string", enum: ["pending", "approved", "denied"], description: "Only approvals with this status" }],
|
|
59572
60211
|
examples: ["overlane guard approvals list", "overlane guard approvals list --status pending --json"],
|
|
59573
60212
|
effect: "read",
|
|
59574
|
-
...
|
|
60213
|
+
...common3,
|
|
59575
60214
|
keywords: ["pending approvals", "approve before write", "who needs to approve", "approval queue"],
|
|
59576
60215
|
result: ApprovalList2,
|
|
59577
60216
|
text: (d) => d.approvals.length === 0 ? ["No approvals."] : d.approvals.flatMap((a) => [`${a.status.padEnd(9)} ${a.id} ${a.tool} by ${a.requestedBy} (rule ${a.ruleId})`, ` ${a.summary}`]),
|
|
59578
60217
|
handler: async (inv) => {
|
|
59579
|
-
const { call: call2, tenantId } = await
|
|
60218
|
+
const { call: call2, tenantId } = await connected2(inv);
|
|
59580
60219
|
const status = textFlag(inv, "status");
|
|
59581
60220
|
return { data: await call2(ApprovalList2, "GET", `${guardPaths.approvals(tenantId)}${status === void 0 ? "" : `?status=${status}`}`) };
|
|
59582
60221
|
}
|
|
@@ -59593,7 +60232,7 @@ var guardApprovalsAnswerCommand = defineCommand({
|
|
|
59593
60232
|
],
|
|
59594
60233
|
examples: ["overlane guard approvals answer apr_1 --decision approve", 'overlane guard approvals answer apr_1 --decision approve --evidence "diff reviewed" --reason "matches the task" --dry-run'],
|
|
59595
60234
|
effect: "write",
|
|
59596
|
-
...
|
|
60235
|
+
...common3,
|
|
59597
60236
|
keywords: ["approve action", "deny action", "answer approval", "allow push", "sign off"],
|
|
59598
60237
|
result: withDryRun(GuardApproval),
|
|
59599
60238
|
text: (d) => "status" in d ? [`${d.id} is ${d.status}.`] : [],
|
|
@@ -59604,8 +60243,8 @@ var guardApprovalsAnswerCommand = defineCommand({
|
|
|
59604
60243
|
const evidence = listFlag(inv, "evidence");
|
|
59605
60244
|
const parsed = AnswerGuardApprovalRequest.safeParse({ decision: textFlag(inv, "decision"), ...reason === void 0 ? {} : { reason }, ...evidence.length === 0 ? {} : { evidence } });
|
|
59606
60245
|
if (!parsed.success) throw new UsageError("--decision must be approve or deny", { hint: `overlane guard approvals answer ${approvalId} --decision approve` });
|
|
59607
|
-
if (inv.dryRun) return
|
|
59608
|
-
const { call: call2, tenantId } = await
|
|
60246
|
+
if (inv.dryRun) return planned2(inv, "POST", (tenantId2) => guardPaths.answer(tenantId2, approvalId), parsed.data);
|
|
60247
|
+
const { call: call2, tenantId } = await connected2(inv);
|
|
59609
60248
|
return { data: await call2(GuardApproval, "POST", guardPaths.answer(tenantId, approvalId), parsed.data) };
|
|
59610
60249
|
}
|
|
59611
60250
|
});
|
|
@@ -59614,10 +60253,10 @@ var guardCommands = [guardRulesListCommand, guardRulesTestCommand, guardRulesPut
|
|
|
59614
60253
|
// ../cli/src/commands/memory.ts
|
|
59615
60254
|
init_src();
|
|
59616
60255
|
init_zod();
|
|
59617
|
-
import { randomUUID as
|
|
60256
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
59618
60257
|
var SERVICE_FLAG3 = { name: "service", type: "string", value: "URL", description: "The service address (default: HARNESS_SERVICE_URL, then the project's binding, then the hosted service)" };
|
|
59619
60258
|
var TEAM_FLAG3 = { name: "team", type: "string", value: "TENANT_ID", description: "The team (tenant) to act on (default: the one your token belongs to)" };
|
|
59620
|
-
var
|
|
60259
|
+
var common4 = { needsAuth: true, needsNetwork: true };
|
|
59621
60260
|
async function authed3(inv) {
|
|
59622
60261
|
const target = await resolveTarget(inv.deps, textFlag(inv, "service"));
|
|
59623
60262
|
const token = await requireToken(inv.deps, target.storeKey);
|
|
@@ -59636,7 +60275,7 @@ async function plan2(inv, method, path, body2, note) {
|
|
|
59636
60275
|
const tenant = textFlag(inv, "team") ?? ":your-team";
|
|
59637
60276
|
return planOutcome(inv.deps, dryRunPlan({ service: target.service, requests: [{ method, path: path(tenant), ...body2 === void 0 ? {} : { body: body2 }, ...note === void 0 ? {} : { note } }] }));
|
|
59638
60277
|
}
|
|
59639
|
-
var
|
|
60278
|
+
var requestId5 = () => `cli-${randomUUID5()}`;
|
|
59640
60279
|
var memorySearchCommand = defineCommand({
|
|
59641
60280
|
path: ["memory", "search"],
|
|
59642
60281
|
summary: "Search memory across project, team, user and global scopes",
|
|
@@ -59651,7 +60290,7 @@ var memorySearchCommand = defineCommand({
|
|
|
59651
60290
|
],
|
|
59652
60291
|
examples: ['overlane memory search "how do we deploy"', 'overlane memory search "indentation" --scope team --json'],
|
|
59653
60292
|
effect: "read",
|
|
59654
|
-
...
|
|
60293
|
+
...common4,
|
|
59655
60294
|
keywords: ["recall", "remember", "what do we know", "find memory", "lookup", "notes", "conventions", "decisions"],
|
|
59656
60295
|
result: MemorySearchResponse,
|
|
59657
60296
|
text: (d) => d.items.length === 0 ? ["No memories match."] : d.items.map((i2) => `${i2.scope.padEnd(7)} ${i2.status.padEnd(9)} ${i2.id} ${i2.title}${i2.stale ? " [stale]" : ""}${i2.overriddenBy === null ? "" : ` [overridden by ${i2.overriddenBy}]`}`),
|
|
@@ -59685,7 +60324,7 @@ var memoryAddCommand = defineCommand({
|
|
|
59685
60324
|
],
|
|
59686
60325
|
examples: ['overlane memory add --title "Deploy day" "Deploys go out on Tuesdays" --project prj_1', 'overlane memory add --title "Editor" --scope user "I prefer a dark theme" --dry-run'],
|
|
59687
60326
|
effect: "write",
|
|
59688
|
-
...
|
|
60327
|
+
...common4,
|
|
59689
60328
|
keywords: ["remember this", "save a note", "record a decision", "store convention", "candidate"],
|
|
59690
60329
|
result: AddResult,
|
|
59691
60330
|
handler: async (inv) => {
|
|
@@ -59693,7 +60332,7 @@ var memoryAddCommand = defineCommand({
|
|
|
59693
60332
|
if (title === void 0) throw new UsageError("add needs --title", { hint: 'overlane memory add --title "..." "<text>"' });
|
|
59694
60333
|
const project = textFlag(inv, "project");
|
|
59695
60334
|
const parsed = MemoryCandidate.safeParse({
|
|
59696
|
-
requestId:
|
|
60335
|
+
requestId: requestId5(),
|
|
59697
60336
|
scope: textFlag(inv, "scope") ?? "project",
|
|
59698
60337
|
...project === void 0 ? {} : { projectId: project },
|
|
59699
60338
|
category: textFlag(inv, "category") ?? "fact",
|
|
@@ -59724,7 +60363,7 @@ var memoryConfirmCommand = defineCommand({
|
|
|
59724
60363
|
],
|
|
59725
60364
|
examples: ["overlane memory confirm mem_ab12", "overlane memory confirm mem_ab12 --basis ci_evidence --evidence 0123abc:unit_tests --dry-run"],
|
|
59726
60365
|
effect: "write",
|
|
59727
|
-
...
|
|
60366
|
+
...common4,
|
|
59728
60367
|
keywords: ["approve memory", "verify", "promote candidate", "second observer", "ci evidence"],
|
|
59729
60368
|
result: ConfirmResult,
|
|
59730
60369
|
handler: async (inv) => {
|
|
@@ -59748,7 +60387,7 @@ var memoryPromoteCommand = defineCommand({
|
|
|
59748
60387
|
flags: [SERVICE_FLAG3, TEAM_FLAG3, { name: "to", type: "string", enum: ["team", "global"], default: "team", description: "Where to promote it" }],
|
|
59749
60388
|
examples: ["overlane memory promote mem_ab12 --to team", "overlane memory promote mem_cd34 --to global --dry-run"],
|
|
59750
60389
|
effect: "write",
|
|
59751
|
-
...
|
|
60390
|
+
...common4,
|
|
59752
60391
|
keywords: ["share with team", "contribute", "global memory", "make team wide"],
|
|
59753
60392
|
result: withDryRun(MemoryPromoteResponse),
|
|
59754
60393
|
handler: async (inv) => {
|
|
@@ -59776,7 +60415,7 @@ var memoryExportCommand = defineCommand({
|
|
|
59776
60415
|
],
|
|
59777
60416
|
examples: ["overlane memory export --json", "overlane memory export --scope user --user usr_1 --json"],
|
|
59778
60417
|
effect: "read",
|
|
59779
|
-
...
|
|
60418
|
+
...common4,
|
|
59780
60419
|
keywords: ["download memory", "backup", "data portability", "gdpr", "subject access"],
|
|
59781
60420
|
result: MemoryExportRecord,
|
|
59782
60421
|
text: (d) => [`${d.items.length} memories exported at ${d.exportedAt}. Use --json for the full content.`],
|
|
@@ -59800,7 +60439,7 @@ var memoryDeleteCommand = defineCommand({
|
|
|
59800
60439
|
flags: [SERVICE_FLAG3, TEAM_FLAG3],
|
|
59801
60440
|
examples: ["overlane memory delete mem_ab12 --force", "overlane memory delete mem_ab12 --dry-run"],
|
|
59802
60441
|
effect: "destructive",
|
|
59803
|
-
...
|
|
60442
|
+
...common4,
|
|
59804
60443
|
keywords: ["remove memory", "forget", "erase", "wrong memory", "gdpr deletion"],
|
|
59805
60444
|
result: withDryRun(MemoryDeleteResponse),
|
|
59806
60445
|
handler: async (inv) => {
|
|
@@ -59821,7 +60460,7 @@ var memoryUnlearnCommand = defineCommand({
|
|
|
59821
60460
|
flags: [SERVICE_FLAG3, TEAM_FLAG3],
|
|
59822
60461
|
examples: ["overlane memory unlearn mem_ab12 --force", "overlane memory unlearn mem_ab12 --dry-run"],
|
|
59823
60462
|
effect: "destructive",
|
|
59824
|
-
...
|
|
60463
|
+
...common4,
|
|
59825
60464
|
keywords: ["unlearn", "forget everything derived", "retract", "poisoned memory", "bad memory"],
|
|
59826
60465
|
result: withDryRun(MemoryUnlearnRecord),
|
|
59827
60466
|
handler: async (inv) => {
|
|
@@ -59841,7 +60480,7 @@ var memoryStatusCommand = defineCommand({
|
|
|
59841
60480
|
flags: [SERVICE_FLAG3, TEAM_FLAG3],
|
|
59842
60481
|
examples: ["overlane memory status", "overlane memory status --json"],
|
|
59843
60482
|
effect: "read",
|
|
59844
|
-
...
|
|
60483
|
+
...common4,
|
|
59845
60484
|
keywords: ["memory health", "stale memory", "how many memories", "contribution", "opt in"],
|
|
59846
60485
|
result: MemoryStatusResponse,
|
|
59847
60486
|
text: (d) => [...Object.entries(d.counts).map(([key, n]) => `${key}: ${n}`), `stale: ${d.stale}`, `global contribution: ${d.settings.globalContribution ? "on" : "off"}`, `pending jobs: ${d.pendingJobs}`],
|
|
@@ -59859,7 +60498,7 @@ var memoryContributionCommand = defineCommand({
|
|
|
59859
60498
|
flags: [SERVICE_FLAG3, TEAM_FLAG3],
|
|
59860
60499
|
examples: ["overlane memory contribution on", "overlane memory contribution off --dry-run"],
|
|
59861
60500
|
effect: "write",
|
|
59862
|
-
...
|
|
60501
|
+
...common4,
|
|
59863
60502
|
keywords: ["opt in", "opt out", "share patterns", "global pool", "contribute"],
|
|
59864
60503
|
result: withDryRun(MemorySettings),
|
|
59865
60504
|
handler: async (inv) => {
|
|
@@ -59879,10 +60518,10 @@ var memoryCommands = [memorySearchCommand, memoryAddCommand, memoryConfirmComman
|
|
|
59879
60518
|
// ../cli/src/commands/issue.ts
|
|
59880
60519
|
init_src();
|
|
59881
60520
|
init_zod();
|
|
59882
|
-
import { randomUUID as
|
|
60521
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
59883
60522
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
59884
|
-
var
|
|
59885
|
-
var
|
|
60523
|
+
var common5 = { needsAuth: true, needsNetwork: true };
|
|
60524
|
+
var requestId6 = () => `cli-${randomUUID6()}`;
|
|
59886
60525
|
var PRIORITIES = ["P0", "P1", "P2", "P3"];
|
|
59887
60526
|
var STATUSES = ["backlog", "todo", "in_progress", "in_review", "cancelled"];
|
|
59888
60527
|
async function send(deps, label, schema, method, path, body2, dryRun) {
|
|
@@ -59919,7 +60558,7 @@ var issueListCommand = defineCommand({
|
|
|
59919
60558
|
flags: [{ name: "status", type: "string", enum: ["backlog", "todo", "in_progress", "in_review", "done", "cancelled"], description: "Only issues in this status" }],
|
|
59920
60559
|
examples: ["overlane issue list", "overlane issue list --status todo --json"],
|
|
59921
60560
|
effect: "read",
|
|
59922
|
-
...
|
|
60561
|
+
...common5,
|
|
59923
60562
|
keywords: ["issues", "backlog", "tickets", "work items", "what is open", "list issues"],
|
|
59924
60563
|
result: external_exports.object({ issues: external_exports.array(IssueShown) }),
|
|
59925
60564
|
handler: async (inv) => {
|
|
@@ -59940,7 +60579,7 @@ var issueShowCommand = defineCommand({
|
|
|
59940
60579
|
args: [{ name: "issue-id", required: true, description: "The issue ID, for example iss_ab12cd34ef56gh78" }],
|
|
59941
60580
|
examples: ["overlane issue show iss_ab12cd34ef56gh78"],
|
|
59942
60581
|
effect: "read",
|
|
59943
|
-
...
|
|
60582
|
+
...common5,
|
|
59944
60583
|
keywords: ["issue details", "ticket", "view issue", "who is working on"],
|
|
59945
60584
|
result: IssueShown,
|
|
59946
60585
|
handler: async (inv) => {
|
|
@@ -59963,7 +60602,7 @@ var issueEventsCommand = defineCommand({
|
|
|
59963
60602
|
args: [{ name: "issue-id", required: true, description: "The issue ID" }],
|
|
59964
60603
|
examples: ["overlane issue events iss_ab12cd34ef56gh78"],
|
|
59965
60604
|
effect: "read",
|
|
59966
|
-
...
|
|
60605
|
+
...common5,
|
|
59967
60606
|
keywords: ["audit", "history", "who changed", "field changes", "issue log"],
|
|
59968
60607
|
result: IssueEventList,
|
|
59969
60608
|
handler: async (inv) => {
|
|
@@ -59988,12 +60627,12 @@ var issueNewCommand = defineCommand({
|
|
|
59988
60627
|
],
|
|
59989
60628
|
examples: ['overlane issue new "Back-time drifts by a second"', 'overlane issue new "Fix export" --priority P0 --description "Fails on empty notes"'],
|
|
59990
60629
|
effect: "write",
|
|
59991
|
-
...
|
|
60630
|
+
...common5,
|
|
59992
60631
|
keywords: ["create issue", "new issue", "file a ticket", "add work item", "report bug"],
|
|
59993
60632
|
result: withDryRun(Issue),
|
|
59994
60633
|
handler: async (inv) => {
|
|
59995
60634
|
const estimate = textFlag(inv, "estimate");
|
|
59996
|
-
const body2 = { requestId:
|
|
60635
|
+
const body2 = { requestId: requestId6(), title: inv.positionals.join(" "), description: textFlag(inv, "description") ?? "", priority: priorityFlag(inv) ?? "P1", status: textFlag(inv, "status") ?? "backlog", ...estimate === void 0 ? {} : { estimate: Number(estimate) } };
|
|
59997
60636
|
const result = await send(inv.deps, "issue", Issue, "POST", issuePaths.issues, body2, inv.dryRun);
|
|
59998
60637
|
if (result.value !== void 0) say(inv.deps, `Created #${result.value.number} ${result.value.issueId}`);
|
|
59999
60638
|
return result;
|
|
@@ -60013,7 +60652,7 @@ var issueUpdateCommand = defineCommand({
|
|
|
60013
60652
|
],
|
|
60014
60653
|
examples: ["overlane issue update iss_ab12cd34ef56gh78 --priority P0", 'overlane issue update iss_ab12cd34ef56gh78 --status in_progress --title "New title"'],
|
|
60015
60654
|
effect: "write",
|
|
60016
|
-
...
|
|
60655
|
+
...common5,
|
|
60017
60656
|
keywords: ["edit issue", "change status", "change priority", "rename issue", "update ticket"],
|
|
60018
60657
|
result: withDryRun(Issue),
|
|
60019
60658
|
handler: async (inv) => {
|
|
@@ -60021,7 +60660,7 @@ var issueUpdateCommand = defineCommand({
|
|
|
60021
60660
|
if (id2 === void 0) throw new UsageError("update needs an ISSUE_ID");
|
|
60022
60661
|
const estimate = textFlag(inv, "estimate");
|
|
60023
60662
|
const body2 = {
|
|
60024
|
-
requestId:
|
|
60663
|
+
requestId: requestId6(),
|
|
60025
60664
|
...textFlag(inv, "title") === void 0 ? {} : { title: textFlag(inv, "title") },
|
|
60026
60665
|
...textFlag(inv, "description") === void 0 ? {} : { description: textFlag(inv, "description") },
|
|
60027
60666
|
...textFlag(inv, "status") === void 0 ? {} : { status: textFlag(inv, "status") },
|
|
@@ -60042,14 +60681,14 @@ var issueAssignCommand = defineCommand({
|
|
|
60042
60681
|
],
|
|
60043
60682
|
examples: ["overlane issue assign iss_ab12cd34ef56gh78 agent:claude-code", "overlane issue assign iss_ab12cd34ef56gh78 none"],
|
|
60044
60683
|
effect: "write",
|
|
60045
|
-
...
|
|
60684
|
+
...common5,
|
|
60046
60685
|
keywords: ["assign", "give to agent", "hand to bot", "delegate", "who works on this", "unassign"],
|
|
60047
60686
|
result: withDryRun(AssignResult),
|
|
60048
60687
|
handler: async (inv) => {
|
|
60049
60688
|
const id2 = inv.positionals[0];
|
|
60050
60689
|
if (id2 === void 0) throw new UsageError("assign needs an ISSUE_ID and an assignee");
|
|
60051
60690
|
const assignee = parseAssignee(inv.positionals[1]);
|
|
60052
|
-
const result = await send(inv.deps, "issue", AssignResult, "POST", (t, p) => issuePaths.assign(t, p, id2), { requestId:
|
|
60691
|
+
const result = await send(inv.deps, "issue", AssignResult, "POST", (t, p) => issuePaths.assign(t, p, id2), { requestId: requestId6(), assignee }, inv.dryRun);
|
|
60053
60692
|
if (result.value !== void 0) say(inv.deps, result.value.taskId === null ? "Assigned." : `Assigned. Task: ${result.value.taskId}${result.value.createdTask ? " (new)" : ""}`);
|
|
60054
60693
|
return result;
|
|
60055
60694
|
}
|
|
@@ -60065,7 +60704,7 @@ var issueImportCommand = defineCommand({
|
|
|
60065
60704
|
flags: [{ name: "preview", type: "boolean", description: "Report what the import would create or update, and write nothing" }],
|
|
60066
60705
|
examples: ["overlane issue import linear ./linear-export.json --preview", "overlane issue import jira ./jira-search.json"],
|
|
60067
60706
|
effect: "write",
|
|
60068
|
-
...
|
|
60707
|
+
...common5,
|
|
60069
60708
|
keywords: ["import", "migrate from linear", "migrate from jira", "github projects import", "bring issues in"],
|
|
60070
60709
|
result: withDryRun(ImportReport),
|
|
60071
60710
|
handler: async (inv) => {
|
|
@@ -60078,7 +60717,7 @@ var issueImportCommand = defineCommand({
|
|
|
60078
60717
|
} catch {
|
|
60079
60718
|
throw new UsageError(`${file2} is not a readable JSON file`);
|
|
60080
60719
|
}
|
|
60081
|
-
const result = await send(inv.deps, "issue", ImportReport, "POST", issuePaths.import, { requestId:
|
|
60720
|
+
const result = await send(inv.deps, "issue", ImportReport, "POST", issuePaths.import, { requestId: requestId6(), source, dryRun: boolFlag(inv, "preview"), data }, inv.dryRun);
|
|
60082
60721
|
if (result.value !== void 0) {
|
|
60083
60722
|
const r = result.value;
|
|
60084
60723
|
say(inv.deps, `${r.dryRun ? "Would import" : "Imported"} from ${r.source}: ${r.created} new, ${r.updated} updated, ${r.unchanged} unchanged, ${r.skipped.length} skipped.`);
|
|
@@ -60092,7 +60731,7 @@ var issueSyncCommand = defineCommand({
|
|
|
60092
60731
|
description: "Overlane issues work with no sync; syncing with GitHub is optional. Shows the repository and mode: off (default), read_only (GitHub changes flow in, nothing is written to GitHub) or write_back (an owner or admin opted in).",
|
|
60093
60732
|
examples: ["overlane issue sync"],
|
|
60094
60733
|
effect: "read",
|
|
60095
|
-
...
|
|
60734
|
+
...common5,
|
|
60096
60735
|
keywords: ["github sync", "sync status", "two-way sync", "write back"],
|
|
60097
60736
|
result: SyncConfig,
|
|
60098
60737
|
handler: async (inv) => {
|
|
@@ -60112,13 +60751,13 @@ var issueSyncSetCommand = defineCommand({
|
|
|
60112
60751
|
],
|
|
60113
60752
|
examples: ["overlane issue sync set acme/app read_only", "overlane issue sync set acme/app off"],
|
|
60114
60753
|
effect: "write",
|
|
60115
|
-
...
|
|
60754
|
+
...common5,
|
|
60116
60755
|
keywords: ["enable github sync", "write back", "turn off sync", "read only sync"],
|
|
60117
60756
|
result: withDryRun(SyncConfig),
|
|
60118
60757
|
handler: async (inv) => {
|
|
60119
60758
|
const [repository, mode] = inv.positionals;
|
|
60120
60759
|
if (repository === void 0 || mode === void 0) throw new UsageError("sync set needs REPOSITORY and MODE");
|
|
60121
|
-
return send(inv.deps, "issue", SyncConfig, "PUT", issuePaths.sync, { requestId:
|
|
60760
|
+
return send(inv.deps, "issue", SyncConfig, "PUT", issuePaths.sync, { requestId: requestId6(), repository, mode }, inv.dryRun);
|
|
60122
60761
|
}
|
|
60123
60762
|
});
|
|
60124
60763
|
var issueCommands = [issueListCommand, issueShowCommand, issueEventsCommand, issueNewCommand, issueUpdateCommand, issueAssignCommand, issueImportCommand, issueSyncCommand, issueSyncSetCommand];
|
|
@@ -60126,7 +60765,7 @@ var issueCommands = [issueListCommand, issueShowCommand, issueEventsCommand, iss
|
|
|
60126
60765
|
// ../cli/src/commands/issue-views.ts
|
|
60127
60766
|
init_src();
|
|
60128
60767
|
init_zod();
|
|
60129
|
-
var
|
|
60768
|
+
var common6 = { needsAuth: true, needsNetwork: true };
|
|
60130
60769
|
var Deleted = external_exports.object({ deleted: external_exports.literal(true) });
|
|
60131
60770
|
var FIELDS = ["status", "priority", "assigneeType", "assignee", "labelId", "workProjectId", "cycleId", "estimate", "source", "title", "number", "createdAt", "updatedAt"];
|
|
60132
60771
|
function parseCondition(text) {
|
|
@@ -60142,7 +60781,7 @@ var viewListCommand = defineCommand({
|
|
|
60142
60781
|
description: "Lists saved views: a filter plus a group-by and sort over any issue field.",
|
|
60143
60782
|
examples: ["overlane view list"],
|
|
60144
60783
|
effect: "read",
|
|
60145
|
-
...
|
|
60784
|
+
...common6,
|
|
60146
60785
|
keywords: ["saved views", "filters", "board", "group by"],
|
|
60147
60786
|
result: ViewList,
|
|
60148
60787
|
handler: async (inv) => {
|
|
@@ -60160,7 +60799,7 @@ var viewRunCommand = defineCommand({
|
|
|
60160
60799
|
args: [{ name: "view-id", required: true, description: "The saved view ID" }],
|
|
60161
60800
|
examples: ["overlane view run viw_ab12cd34ef56gh78"],
|
|
60162
60801
|
effect: "read",
|
|
60163
|
-
...
|
|
60802
|
+
...common6,
|
|
60164
60803
|
keywords: ["run view", "show board", "group issues"],
|
|
60165
60804
|
result: ViewResult,
|
|
60166
60805
|
handler: async (inv) => {
|
|
@@ -60188,12 +60827,12 @@ var viewNewCommand = defineCommand({
|
|
|
60188
60827
|
],
|
|
60189
60828
|
examples: ["overlane view new Urgent --filter priority=P0 --group-by status", 'overlane view new "Agent work" --filter assigneeType=agent --group-by status'],
|
|
60190
60829
|
effect: "write",
|
|
60191
|
-
...
|
|
60830
|
+
...common6,
|
|
60192
60831
|
keywords: ["create view", "save filter", "board", "group by status"],
|
|
60193
60832
|
result: withDryRun(SavedView),
|
|
60194
60833
|
handler: async (inv) => {
|
|
60195
60834
|
const definition = { filter: listFlag(inv, "filter").map(parseCondition), groupBy: textFlag(inv, "group-by") ?? null, sortBy: textFlag(inv, "sort-by") ?? "number", sortDirection: boolFlag(inv, "desc") ? "desc" : "asc" };
|
|
60196
|
-
return send(inv.deps, "view", SavedView, "POST", issuePaths.views, { requestId:
|
|
60835
|
+
return send(inv.deps, "view", SavedView, "POST", issuePaths.views, { requestId: requestId6(), name: inv.positionals.join(" "), definition }, inv.dryRun);
|
|
60197
60836
|
}
|
|
60198
60837
|
});
|
|
60199
60838
|
var viewDeleteCommand = defineCommand({
|
|
@@ -60203,7 +60842,7 @@ var viewDeleteCommand = defineCommand({
|
|
|
60203
60842
|
args: [{ name: "view-id", required: false, description: "The saved view ID (required; checked after the --force confirmation)" }],
|
|
60204
60843
|
examples: ["overlane view delete viw_ab12cd34ef56gh78 --force"],
|
|
60205
60844
|
effect: "destructive",
|
|
60206
|
-
...
|
|
60845
|
+
...common6,
|
|
60207
60846
|
keywords: ["remove view", "delete filter"],
|
|
60208
60847
|
result: withDryRun(Deleted),
|
|
60209
60848
|
handler: async (inv) => {
|
|
@@ -60218,7 +60857,7 @@ var loopListCommand = defineCommand({
|
|
|
60218
60857
|
description: "Lists loops: a trigger (schedule or event), a filter over issues and the executor they dispatch.",
|
|
60219
60858
|
examples: ["overlane loop list"],
|
|
60220
60859
|
effect: "read",
|
|
60221
|
-
...
|
|
60860
|
+
...common6,
|
|
60222
60861
|
keywords: ["loops", "scheduled work", "recurring", "automation"],
|
|
60223
60862
|
result: LoopList,
|
|
60224
60863
|
handler: async (inv) => {
|
|
@@ -60242,7 +60881,7 @@ var loopNewCommand = defineCommand({
|
|
|
60242
60881
|
],
|
|
60243
60882
|
examples: ["overlane loop new Nightly --every 1440 --filter priority=P0", "overlane loop new OnAssign --on issue.assigned"],
|
|
60244
60883
|
effect: "write",
|
|
60245
|
-
...
|
|
60884
|
+
...common6,
|
|
60246
60885
|
keywords: ["schedule agent", "recurring work", "event trigger", "automation", "nightly"],
|
|
60247
60886
|
result: withDryRun(LoopDefinition),
|
|
60248
60887
|
handler: async (inv) => {
|
|
@@ -60250,7 +60889,7 @@ var loopNewCommand = defineCommand({
|
|
|
60250
60889
|
const on = textFlag(inv, "on");
|
|
60251
60890
|
if (every === void 0 === (on === void 0)) throw new UsageError("pass exactly one of --every MINUTES or --on EVENT");
|
|
60252
60891
|
const trigger = every !== void 0 ? { kind: "schedule", everyMinutes: Number(every) } : { kind: "event", on };
|
|
60253
|
-
return send(inv.deps, "loop", LoopDefinition, "POST", issuePaths.loops, { requestId:
|
|
60892
|
+
return send(inv.deps, "loop", LoopDefinition, "POST", issuePaths.loops, { requestId: requestId6(), name: inv.positionals.join(" "), trigger, filter: listFlag(inv, "filter").map(parseCondition), executor: textFlag(inv, "executor") ?? "claude-code" }, inv.dryRun);
|
|
60254
60893
|
}
|
|
60255
60894
|
});
|
|
60256
60895
|
var loopSetCommand = defineCommand({
|
|
@@ -60263,13 +60902,13 @@ var loopSetCommand = defineCommand({
|
|
|
60263
60902
|
],
|
|
60264
60903
|
examples: ["overlane loop set lop_ab12cd34ef56gh78 off"],
|
|
60265
60904
|
effect: "write",
|
|
60266
|
-
...
|
|
60905
|
+
...common6,
|
|
60267
60906
|
keywords: ["disable loop", "enable loop", "stop schedule"],
|
|
60268
60907
|
result: withDryRun(LoopDefinition),
|
|
60269
60908
|
handler: async (inv) => {
|
|
60270
60909
|
const [id2, state] = inv.positionals;
|
|
60271
60910
|
if (id2 === void 0 || state !== "on" && state !== "off") throw new UsageError("set needs a LOOP_ID and on or off");
|
|
60272
|
-
return send(inv.deps, "loop", LoopDefinition, "PATCH", (t, p) => issuePaths.loop(t, p, id2), { requestId:
|
|
60911
|
+
return send(inv.deps, "loop", LoopDefinition, "PATCH", (t, p) => issuePaths.loop(t, p, id2), { requestId: requestId6(), enabled: state === "on" }, inv.dryRun);
|
|
60273
60912
|
}
|
|
60274
60913
|
});
|
|
60275
60914
|
var loopFireCommand = defineCommand({
|
|
@@ -60279,13 +60918,13 @@ var loopFireCommand = defineCommand({
|
|
|
60279
60918
|
args: [{ name: "loop-id", required: true, description: "The loop ID" }],
|
|
60280
60919
|
examples: ["overlane loop fire lop_ab12cd34ef56gh78"],
|
|
60281
60920
|
effect: "write",
|
|
60282
|
-
...
|
|
60921
|
+
...common6,
|
|
60283
60922
|
keywords: ["run loop", "trigger loop", "dispatch agent"],
|
|
60284
60923
|
result: withDryRun(LoopRun),
|
|
60285
60924
|
handler: async (inv) => {
|
|
60286
60925
|
const id2 = inv.positionals[0];
|
|
60287
60926
|
if (id2 === void 0) throw new UsageError("fire needs a LOOP_ID");
|
|
60288
|
-
const result = await send(inv.deps, "loop", LoopRun, "POST", (t, p) => issuePaths.loopFire(t, p, id2), { requestId:
|
|
60927
|
+
const result = await send(inv.deps, "loop", LoopRun, "POST", (t, p) => issuePaths.loopFire(t, p, id2), { requestId: requestId6(), trigger: "schedule" }, inv.dryRun);
|
|
60289
60928
|
if (result.value !== void 0) say(inv.deps, `Loop run ${result.value.runId ?? "(none)"}: ${result.value.claimed.length} claimed, stopped: ${result.value.stopReason}.`);
|
|
60290
60929
|
return result;
|
|
60291
60930
|
}
|
|
@@ -60297,7 +60936,7 @@ var loopDeleteCommand = defineCommand({
|
|
|
60297
60936
|
args: [{ name: "loop-id", required: false, description: "The loop ID (required; checked after the --force confirmation)" }],
|
|
60298
60937
|
examples: ["overlane loop delete lop_ab12cd34ef56gh78 --force"],
|
|
60299
60938
|
effect: "destructive",
|
|
60300
|
-
...
|
|
60939
|
+
...common6,
|
|
60301
60940
|
keywords: ["remove loop", "delete schedule"],
|
|
60302
60941
|
result: withDryRun(Deleted),
|
|
60303
60942
|
handler: async (inv) => {
|
|
@@ -60311,14 +60950,14 @@ var loopCommands = [loopListCommand, loopNewCommand, loopSetCommand, loopFireCom
|
|
|
60311
60950
|
|
|
60312
60951
|
// ../cli/src/commands/review.ts
|
|
60313
60952
|
init_src();
|
|
60314
|
-
import { randomUUID as
|
|
60315
|
-
var
|
|
60316
|
-
var
|
|
60317
|
-
async function
|
|
60953
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
60954
|
+
var common7 = { needsAuth: true, needsNetwork: true };
|
|
60955
|
+
var requestId7 = () => `cli-${randomUUID7()}`;
|
|
60956
|
+
async function connected3(inv) {
|
|
60318
60957
|
const project = await connectedProject(inv.deps, "review");
|
|
60319
60958
|
return { project, call: serviceCall(inv.deps, project.serviceUrl, project.token), tenantId: project.binding.tenantId, projectId: project.binding.projectId };
|
|
60320
60959
|
}
|
|
60321
|
-
async function
|
|
60960
|
+
async function planned3(inv, method, path, body2, note) {
|
|
60322
60961
|
const project = await offlineProject(inv.deps, "review");
|
|
60323
60962
|
return planOutcome(inv.deps, dryRunPlan({ service: project.serviceUrl, requests: [{ method, path: path(project.binding.tenantId, project.binding.projectId), ...body2 === void 0 ? {} : { body: body2 }, ...note === void 0 ? {} : { note } }] }));
|
|
60324
60963
|
}
|
|
@@ -60347,7 +60986,7 @@ var reviewRunCommand = defineCommand({
|
|
|
60347
60986
|
flags: [{ name: "repo", type: "string", value: "OWNER/NAME", description: "The repository (default: the origin remote of this working copy)" }],
|
|
60348
60987
|
examples: ["overlane review run 7", "overlane review run 7 --repo acme/app --dry-run"],
|
|
60349
60988
|
effect: "write",
|
|
60350
|
-
...
|
|
60989
|
+
...common7,
|
|
60351
60990
|
keywords: ["code review", "review pull request", "review pr", "ai review", "check my pr", "findings"],
|
|
60352
60991
|
result: withDryRun(ReviewRunResponse),
|
|
60353
60992
|
text: (d) => "run" in d ? [`${d.run.status} review of ${d.run.repository}#${d.run.pullNumber} (${d.run.mode}${d.run.posted ? ", posted" : ", nothing posted"}): ${d.run.findings.open} open, ${d.run.findings.fixed} fixed, ${d.run.findings.dismissed} dismissed.`, ...d.findings.filter((finding) => finding.status === "open").map(FINDING_LINE)] : [],
|
|
@@ -60355,9 +60994,9 @@ var reviewRunCommand = defineCommand({
|
|
|
60355
60994
|
const number4 = Number(inv.positionals[0]);
|
|
60356
60995
|
if (!Number.isInteger(number4) || number4 < 1) throw new UsageError("run needs a pull request number", { hint: "overlane review run 7" });
|
|
60357
60996
|
const repository = await repositoryOf(inv);
|
|
60358
|
-
const body2 = { requestId:
|
|
60359
|
-
if (inv.dryRun) return
|
|
60360
|
-
const { call: call2, tenantId, projectId } = await
|
|
60997
|
+
const body2 = { requestId: requestId7(), trigger: "manual", source: { kind: "github", repository, number: number4 } };
|
|
60998
|
+
if (inv.dryRun) return planned3(inv, "POST", reviewPaths.runs, body2, "reads the pull request through the GitHub App and runs the review");
|
|
60999
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60361
61000
|
const result = await call2(ReviewRunResponse, "POST", reviewPaths.runs(tenantId, projectId), body2);
|
|
60362
61001
|
if (result.run.status === "partial") say(inv.deps, "Partial review: the token cap was reached. The summary lists what was not covered.");
|
|
60363
61002
|
return { data: result };
|
|
@@ -60369,12 +61008,12 @@ var reviewStatusCommand = defineCommand({
|
|
|
60369
61008
|
description: "Shows whether review posts comments or is log-only, the token cap, the latest runs and the number of open findings. States the data-use terms: diffs go to model providers only under terms that exclude training.",
|
|
60370
61009
|
examples: ["overlane review status", "overlane review status --json"],
|
|
60371
61010
|
effect: "read",
|
|
60372
|
-
...
|
|
61011
|
+
...common7,
|
|
60373
61012
|
keywords: ["review mode", "log only", "review settings", "recent reviews", "how is review doing"],
|
|
60374
61013
|
result: ReviewStatusResponse,
|
|
60375
61014
|
text: (d) => [`Review mode: ${d.settings.mode}. Token cap per pull request: ${d.settings.tokenCap}. Open findings: ${d.openFindings}.`, d.settings.privacy, ...d.runs.slice(0, 5).map((run3) => `${run3.startedAt} ${run3.repository}#${run3.pullNumber} ${run3.status} ${run3.tokensUsed} tokens ${run3.model}`)],
|
|
60376
61015
|
handler: async (inv) => {
|
|
60377
|
-
const { call: call2, tenantId, projectId } = await
|
|
61016
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60378
61017
|
return { data: await call2(ReviewStatusResponse, "GET", reviewPaths.status(tenantId, projectId)) };
|
|
60379
61018
|
}
|
|
60380
61019
|
});
|
|
@@ -60389,12 +61028,12 @@ var reviewFindingsCommand = defineCommand({
|
|
|
60389
61028
|
],
|
|
60390
61029
|
examples: ["overlane review findings --status open", "overlane review findings --pull 7 --json"],
|
|
60391
61030
|
effect: "read",
|
|
60392
|
-
...
|
|
61031
|
+
...common7,
|
|
60393
61032
|
keywords: ["list findings", "open comments", "review comments", "what did review find", "defects"],
|
|
60394
61033
|
result: ReviewFindingsResponse,
|
|
60395
61034
|
text: (d) => d.findings.length === 0 ? ["No findings."] : d.findings.map(FINDING_LINE),
|
|
60396
61035
|
handler: async (inv) => {
|
|
60397
|
-
const { call: call2, tenantId, projectId } = await
|
|
61036
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60398
61037
|
const params = new URLSearchParams();
|
|
60399
61038
|
for (const name2 of ["pull", "repo", "status"]) {
|
|
60400
61039
|
const value = textFlag(inv, name2);
|
|
@@ -60415,16 +61054,16 @@ var reviewDismissCommand = defineCommand({
|
|
|
60415
61054
|
],
|
|
60416
61055
|
examples: ['overlane review dismiss fnd_1 --note "intended"', "overlane review dismiss fnd_2 --accept"],
|
|
60417
61056
|
effect: "write",
|
|
60418
|
-
...
|
|
61057
|
+
...common7,
|
|
60419
61058
|
keywords: ["dismiss finding", "ignore comment", "false positive", "accept finding", "teach reviewer", "feedback"],
|
|
60420
61059
|
result: withDryRun(FeedbackResponse),
|
|
60421
61060
|
text: (d) => "finding" in d ? [`${d.finding.id} is ${d.finding.status}.${d.learned === null ? "" : ` Learned: ${d.learned.direction} ${d.learned.rule} (${d.learned.evidence} reviews).`}`] : [],
|
|
60422
61061
|
handler: async (inv) => {
|
|
60423
61062
|
const findingId = id(inv, "dismiss");
|
|
60424
61063
|
const note = textFlag(inv, "note");
|
|
60425
|
-
const body2 = { kind: inv.values["accept"] === true ? "accept" : "dismiss", ...note === void 0 ? {} : { note }, requestId:
|
|
60426
|
-
if (inv.dryRun) return
|
|
60427
|
-
const { call: call2, tenantId, projectId } = await
|
|
61064
|
+
const body2 = { kind: inv.values["accept"] === true ? "accept" : "dismiss", ...note === void 0 ? {} : { note }, requestId: requestId7() };
|
|
61065
|
+
if (inv.dryRun) return planned3(inv, "POST", (tenantId2, projectId2) => reviewPaths.feedback(tenantId2, projectId2, findingId), body2);
|
|
61066
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60428
61067
|
return { data: await call2(FeedbackResponse, "POST", reviewPaths.feedback(tenantId, projectId, findingId), body2) };
|
|
60429
61068
|
}
|
|
60430
61069
|
});
|
|
@@ -60436,16 +61075,16 @@ var reviewAutofixCommand = defineCommand({
|
|
|
60436
61075
|
flags: [{ name: "assign", type: "string", value: "AGENT", description: "The agent or bot to assign, for example agent:fixer" }],
|
|
60437
61076
|
examples: ["overlane review autofix fnd_1", "overlane review autofix fnd_1 --assign agent:fixer --dry-run"],
|
|
60438
61077
|
effect: "write",
|
|
60439
|
-
...
|
|
61078
|
+
...common7,
|
|
60440
61079
|
keywords: ["auto fix", "autofix", "fix finding", "create task from finding", "assign to agent"],
|
|
60441
61080
|
result: withDryRun(AutofixResponse),
|
|
60442
61081
|
text: (d) => "taskId" in d ? [`Task ${d.taskId} created${d.assignee === null ? "" : ` for ${d.assignee}`}. Start it with: overlane task start ${d.taskId}`] : [],
|
|
60443
61082
|
handler: async (inv) => {
|
|
60444
61083
|
const findingId = id(inv, "autofix");
|
|
60445
61084
|
const assignee = textFlag(inv, "assign");
|
|
60446
|
-
const body2 = { requestId:
|
|
60447
|
-
if (inv.dryRun) return
|
|
60448
|
-
const { call: call2, tenantId, projectId } = await
|
|
61085
|
+
const body2 = { requestId: requestId7(), ...assignee === void 0 ? {} : { assignee } };
|
|
61086
|
+
if (inv.dryRun) return planned3(inv, "POST", (tenantId2, projectId2) => reviewPaths.autofix(tenantId2, projectId2, findingId), body2);
|
|
61087
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60449
61088
|
return { data: await call2(AutofixResponse, "POST", reviewPaths.autofix(tenantId, projectId, findingId), body2) };
|
|
60450
61089
|
}
|
|
60451
61090
|
});
|
|
@@ -60455,12 +61094,12 @@ var reviewSettingsCommand = defineCommand({
|
|
|
60455
61094
|
description: "Shows the mode (log-only until comments are enabled), the per-PR token cap, extra skip patterns and the statement that diffs go to model providers only under terms that exclude training.",
|
|
60456
61095
|
examples: ["overlane review settings"],
|
|
60457
61096
|
effect: "read",
|
|
60458
|
-
...
|
|
61097
|
+
...common7,
|
|
60459
61098
|
keywords: ["review configuration", "token cap", "skip patterns", "privacy", "no training", "data use"],
|
|
60460
61099
|
result: ReviewSettings,
|
|
60461
61100
|
text: (d) => [`Mode: ${d.mode}. Token cap: ${d.tokenCap}. Extra skip patterns: ${d.skipPatterns.length === 0 ? "none" : d.skipPatterns.join(", ")}.`, d.privacy],
|
|
60462
61101
|
handler: async (inv) => {
|
|
60463
|
-
const { call: call2, tenantId, projectId } = await
|
|
61102
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60464
61103
|
return { data: await call2(ReviewSettings, "GET", reviewPaths.settings(tenantId, projectId)) };
|
|
60465
61104
|
}
|
|
60466
61105
|
});
|
|
@@ -60475,7 +61114,7 @@ var reviewSettingsSetCommand = defineCommand({
|
|
|
60475
61114
|
],
|
|
60476
61115
|
examples: ["overlane review settings set --mode comments", "overlane review settings set --token-cap 40000 --skip 'docs/**' --dry-run"],
|
|
60477
61116
|
effect: "write",
|
|
60478
|
-
...
|
|
61117
|
+
...common7,
|
|
60479
61118
|
keywords: ["enable review comments", "turn on review", "log only", "set token cap", "skip files"],
|
|
60480
61119
|
result: withDryRun(ReviewSettings),
|
|
60481
61120
|
text: (d) => "mode" in d ? [`Review is ${d.mode}. Token cap ${d.tokenCap}.`] : [],
|
|
@@ -60489,8 +61128,8 @@ var reviewSettingsSetCommand = defineCommand({
|
|
|
60489
61128
|
});
|
|
60490
61129
|
if (!parsed.success) throw new UsageError(parsed.error.issues.map((issue2) => issue2.message).join("; "), { hint: "overlane review settings set --mode comments" });
|
|
60491
61130
|
if (Object.keys(parsed.data).length === 0) throw new UsageError("nothing to change", { hint: "overlane review settings set --mode comments" });
|
|
60492
|
-
if (inv.dryRun) return
|
|
60493
|
-
const { call: call2, tenantId, projectId } = await
|
|
61131
|
+
if (inv.dryRun) return planned3(inv, "PUT", reviewPaths.settings, parsed.data);
|
|
61132
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60494
61133
|
return { data: await call2(ReviewSettings, "PUT", reviewPaths.settings(tenantId, projectId), parsed.data) };
|
|
60495
61134
|
}
|
|
60496
61135
|
});
|
|
@@ -60500,12 +61139,12 @@ var codeMapStatusCommand = defineCommand({
|
|
|
60500
61139
|
description: "Lists every supported client in its local and cloud setting, and the bots, review service, cross-repository questions and wiki, with whether the code map is on and the reason. The default for a setting follows the latest GATE-07 result for that setting: off for a local agent with grep (the local run failed, ADR 0018), on where there is no checkout until a re-run says otherwise.",
|
|
60501
61140
|
examples: ["overlane code-map status", "overlane code-map status --json"],
|
|
60502
61141
|
effect: "read",
|
|
60503
|
-
...
|
|
61142
|
+
...common7,
|
|
60504
61143
|
keywords: ["code map", "code tools", "is the code map on", "gate-07", "code layer", "per client"],
|
|
60505
61144
|
result: CodeMapStatus,
|
|
60506
61145
|
text: (d) => d.clients.map((row) => `${row.on ? "on " : "off"} ${row.subject}: ${row.reason}`),
|
|
60507
61146
|
handler: async (inv) => {
|
|
60508
|
-
const { call: call2, tenantId, projectId } = await
|
|
61147
|
+
const { call: call2, tenantId, projectId } = await connected3(inv);
|
|
60509
61148
|
return { data: await call2(CodeMapStatus, "GET", codeMapPaths.status(tenantId, projectId)) };
|
|
60510
61149
|
}
|
|
60511
61150
|
});
|
|
@@ -61089,7 +61728,7 @@ async function doctor(deps, options) {
|
|
|
61089
61728
|
|
|
61090
61729
|
// ../cli/src/kit/setup.ts
|
|
61091
61730
|
init_src();
|
|
61092
|
-
import { randomUUID as
|
|
61731
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
61093
61732
|
import { existsSync as existsSync6, readdirSync as readdirSync2 } from "node:fs";
|
|
61094
61733
|
import { join as join22 } from "node:path";
|
|
61095
61734
|
|
|
@@ -61305,11 +61944,11 @@ async function connectKit(deps, options) {
|
|
|
61305
61944
|
const agentConfig = [join22(".claude", "settings.json"), join22(".codex", "config.toml")];
|
|
61306
61945
|
const preDirty = new Set(await dirty(deps, root, agentConfig));
|
|
61307
61946
|
const preExisting = new Set(agentConfig.filter((file2) => existsSync6(join22(root, file2))));
|
|
61308
|
-
const
|
|
61309
|
-
if (
|
|
61947
|
+
const connected4 = await connect(deps, { ...options, yes: true });
|
|
61948
|
+
if (connected4.error !== void 0 || readBindingFile(root).kind !== "ok") {
|
|
61310
61949
|
throw new CliError(`connect did not finish; the kit files are on ${KIT_BRANCH}, uncommitted. Fix the cause and run \`overlane connect\`, then commit`, { code: "connect_incomplete", hint: "overlane connect --yes" });
|
|
61311
61950
|
}
|
|
61312
|
-
const connectData =
|
|
61951
|
+
const connectData = connected4.data !== void 0 && !("dryRun" in connected4.data) ? connected4.data : void 0;
|
|
61313
61952
|
for (const file2 of agentConfig) {
|
|
61314
61953
|
if (!existsSync6(join22(root, file2)) || preDirty.has(file2) || preExisting.has(file2) && (await dirty(deps, root, [file2])).length === 0) continue;
|
|
61315
61954
|
if ((await gitOut(deps, root, "check-ignore", "-q", "--", file2)).code === 0) continue;
|
|
@@ -61328,7 +61967,7 @@ async function connectKit(deps, options) {
|
|
|
61328
61967
|
const kit = kitClient(deps, serviceUrl, binding.binding, token.token);
|
|
61329
61968
|
await kit.putPolicy({ ...DEFAULT_RUN_POLICY, buildAheadLimit: firstMilestone });
|
|
61330
61969
|
say(deps, `Run policy set (build-ahead limit ${firstMilestone}).`);
|
|
61331
|
-
const synced = await kit.syncPlan(PlanSyncRequest.parse({ requestId: `cli-${
|
|
61970
|
+
const synced = await kit.syncPlan(PlanSyncRequest.parse({ requestId: `cli-${randomUUID8()}`, sourceCommit: sha, plan: await readPlan(root) }));
|
|
61332
61971
|
say(deps, `Plan synced: ${synced.created.length} created, ${synced.updated.length} updated, ${synced.unchanged.length} unchanged, ${synced.deferred.length} deferred.`);
|
|
61333
61972
|
const pr = await openPullRequest(deps, root, repository.name);
|
|
61334
61973
|
say(deps);
|
|
@@ -61612,7 +62251,7 @@ var ReleaseRollbackResult = external_exports.union([
|
|
|
61612
62251
|
]);
|
|
61613
62252
|
|
|
61614
62253
|
// ../cli/src/commands/release.ts
|
|
61615
|
-
var
|
|
62254
|
+
var common8 = { needsAuth: true, needsNetwork: true };
|
|
61616
62255
|
var APPROVE = { name: "approve", type: "string", value: "DIGEST", description: "Approve this exact release digest when it changes executable files or policy" };
|
|
61617
62256
|
var releaseListCommand = defineCommand({
|
|
61618
62257
|
path: ["release", "list"],
|
|
@@ -61620,7 +62259,7 @@ var releaseListCommand = defineCommand({
|
|
|
61620
62259
|
description: "Lists releases with version, short digest, channel, change kinds, restart rule, compatibility and which projects pin them.",
|
|
61621
62260
|
examples: ["overlane release list"],
|
|
61622
62261
|
effect: "read",
|
|
61623
|
-
...
|
|
62262
|
+
...common8,
|
|
61624
62263
|
keywords: ["releases", "versions", "available", "published", "what versions", "all releases"],
|
|
61625
62264
|
result: ReleaseListResult,
|
|
61626
62265
|
handler: async (inv) => listReleases(inv.deps)
|
|
@@ -61631,7 +62270,7 @@ var releaseStatusCommand = defineCommand({
|
|
|
61631
62270
|
description: `Compares the installed release (.harness/release.json) with the project binding and the service's pin, and lists approvals recorded on this machine. Works when the service is down (the pin then reads "unreachable").`,
|
|
61632
62271
|
examples: ["overlane release status"],
|
|
61633
62272
|
effect: "read",
|
|
61634
|
-
...
|
|
62273
|
+
...common8,
|
|
61635
62274
|
keywords: ["installed", "version", "in sync", "update available", "which release", "pinned", "am i up to date", "current release"],
|
|
61636
62275
|
result: ReleaseStatusResult,
|
|
61637
62276
|
handler: async (inv) => releaseStatus(inv.deps)
|
|
@@ -61643,7 +62282,7 @@ var releaseUpdateCommand = defineCommand({
|
|
|
61643
62282
|
flags: [{ name: "to", type: "string", value: "DIGEST", description: "Install this release instead of the project's pin" }, APPROVE],
|
|
61644
62283
|
examples: ["overlane release update --dry-run", "overlane release update", "overlane release update --approve sha256:..."],
|
|
61645
62284
|
effect: "write",
|
|
61646
|
-
...
|
|
62285
|
+
...common8,
|
|
61647
62286
|
keywords: ["upgrade", "install release", "new version", "pull latest", "plugin update", "approve", "update plugin", "get newest"],
|
|
61648
62287
|
result: ReleaseUpdateResult,
|
|
61649
62288
|
handler: async (inv) => updateRelease(inv.deps, { to: textFlag(inv, "to"), approve: textFlag(inv, "approve"), dryRun: inv.dryRun })
|
|
@@ -61655,7 +62294,7 @@ var releaseRollbackCommand = defineCommand({
|
|
|
61655
62294
|
flags: [APPROVE],
|
|
61656
62295
|
examples: ["overlane release rollback --dry-run", "overlane release rollback --force"],
|
|
61657
62296
|
effect: "destructive",
|
|
61658
|
-
...
|
|
62297
|
+
...common8,
|
|
61659
62298
|
keywords: ["roll back", "revert", "undo update", "previous version", "downgrade", "go back", "restore", "undo release", "bad release"],
|
|
61660
62299
|
result: ReleaseRollbackResult,
|
|
61661
62300
|
handler: async (inv) => rollbackRelease(inv.deps, { approve: textFlag(inv, "approve"), dryRun: inv.dryRun })
|
|
@@ -61722,7 +62361,7 @@ var RunStatusResult = external_exports.object({
|
|
|
61722
62361
|
var RunPolicyChangeResult = withDryRun(external_exports.object({ changed: external_exports.boolean(), policy: PolicyShape }));
|
|
61723
62362
|
|
|
61724
62363
|
// ../cli/src/commands/run.ts
|
|
61725
|
-
var
|
|
62364
|
+
var common9 = { needsAuth: true, needsNetwork: true };
|
|
61726
62365
|
var EXECUTOR = { name: "executor", type: "string", enum: ["claude-code", "codex"], description: "Which agent this is (default: detected from the environment)" };
|
|
61727
62366
|
var STOP_NOTE = "A stop (policy paused, a budget spent, nothing runnable) exits 6 with the reason in the error code and the exact `overlane run end --reason ...` as the hint.";
|
|
61728
62367
|
var runStartCommand = defineCommand({
|
|
@@ -61732,7 +62371,7 @@ var runStartCommand = defineCommand({
|
|
|
61732
62371
|
flags: [{ name: "trigger", type: "string", enum: ["schedule", "interactive", "event"], default: "interactive", description: "What started the run" }, EXECUTOR],
|
|
61733
62372
|
examples: ["overlane run start --trigger schedule", "overlane run start --dry-run"],
|
|
61734
62373
|
effect: "write",
|
|
61735
|
-
...
|
|
62374
|
+
...common9,
|
|
61736
62375
|
keywords: ["begin run", "bounded step", "autonomous", "start working", "new run", "schedule", "kick off"],
|
|
61737
62376
|
result: RunStartResult,
|
|
61738
62377
|
handler: async (inv) => startRun(inv.deps, { trigger: textFlag(inv, "trigger"), executor: textFlag(inv, "executor"), dryRun: inv.dryRun })
|
|
@@ -61744,7 +62383,7 @@ var runNextCommand = defineCommand({
|
|
|
61744
62383
|
flags: [EXECUTOR],
|
|
61745
62384
|
examples: ["overlane run next"],
|
|
61746
62385
|
effect: "read",
|
|
61747
|
-
...
|
|
62386
|
+
...common9,
|
|
61748
62387
|
keywords: ["what should I work on next", "next task", "runnable", "what to do", "pick a task", "which task", "what's next", "work on", "what is next", "todo"],
|
|
61749
62388
|
result: RunNextResult,
|
|
61750
62389
|
handler: async (inv) => nextTask(inv.deps, { executor: textFlag(inv, "executor") })
|
|
@@ -61756,7 +62395,7 @@ var runClaimCommand = defineCommand({
|
|
|
61756
62395
|
args: [{ name: "task-id", required: false, description: "The task to claim (default: the next runnable one)" }],
|
|
61757
62396
|
examples: ["overlane run claim", "overlane run claim T003"],
|
|
61758
62397
|
effect: "write",
|
|
61759
|
-
...
|
|
62398
|
+
...common9,
|
|
61760
62399
|
keywords: ["take task", "lease task", "grab", "assign", "pick up task", "get a task"],
|
|
61761
62400
|
result: RunClaimResult,
|
|
61762
62401
|
handler: async (inv) => claimTask(inv.deps, { positionals: inv.positionals, dryRun: inv.dryRun })
|
|
@@ -61773,7 +62412,7 @@ var runDecideCommand = defineCommand({
|
|
|
61773
62412
|
],
|
|
61774
62413
|
examples: ['overlane run decide --question "Which date library?" --decision "Use the built-in Intl" --evidence "package.json has no date library"'],
|
|
61775
62414
|
effect: "write",
|
|
61776
|
-
...
|
|
62415
|
+
...common9,
|
|
61777
62416
|
keywords: ["record decision", "question", "unblocked", "owner override", "judgement call", "log choice", "do not ask", "decide"],
|
|
61778
62417
|
result: RunDecideResult,
|
|
61779
62418
|
handler: async (inv) => decide(inv.deps, { question: textFlag(inv, "question"), decision: textFlag(inv, "decision"), evidence: listFlag(inv, "evidence"), task: textFlag(inv, "task"), dryRun: inv.dryRun })
|
|
@@ -61785,7 +62424,7 @@ var runEndCommand = defineCommand({
|
|
|
61785
62424
|
flags: [{ name: "reason", type: "string", required: true, enum: RUN_STOP_REASONS, description: "Why the run ended" }],
|
|
61786
62425
|
examples: ["overlane run end --reason nothing_runnable", "overlane run end --reason error"],
|
|
61787
62426
|
effect: "write",
|
|
61788
|
-
...
|
|
62427
|
+
...common9,
|
|
61789
62428
|
keywords: ["finish run", "stop", "wrap up", "close run", "release leases", "done with run", "end the run"],
|
|
61790
62429
|
result: RunEndResult,
|
|
61791
62430
|
handler: async (inv) => endRun(inv.deps, { reason: textFlag(inv, "reason"), dryRun: inv.dryRun })
|
|
@@ -61797,7 +62436,7 @@ var runStatusCommand = defineCommand({
|
|
|
61797
62436
|
flags: [EXECUTOR],
|
|
61798
62437
|
examples: ["overlane run status"],
|
|
61799
62438
|
effect: "read",
|
|
61800
|
-
...
|
|
62439
|
+
...common9,
|
|
61801
62440
|
keywords: ["policy", "budget", "limits", "how much left", "remaining", "state of run", "is it paused", "run policy"],
|
|
61802
62441
|
result: RunStatusResult,
|
|
61803
62442
|
handler: async (inv) => runStatus(inv.deps, { executor: textFlag(inv, "executor") })
|
|
@@ -61808,7 +62447,7 @@ var runPauseCommand = defineCommand({
|
|
|
61808
62447
|
description: "Sets the project's run policy to paused. Every run then stops at its next check (`STOP paused`). Undo with `overlane run resume`. Safe to repeat.",
|
|
61809
62448
|
examples: ["overlane run pause", "overlane run pause --dry-run"],
|
|
61810
62449
|
effect: "write",
|
|
61811
|
-
...
|
|
62450
|
+
...common9,
|
|
61812
62451
|
keywords: ["pause", "halt", "freeze", "stop all", "emergency brake", "disable autonomous runs", "policy", "no new runs", "stop agents", "turn off", "suspend"],
|
|
61813
62452
|
result: RunPolicyChangeResult,
|
|
61814
62453
|
handler: async (inv) => setPolicyStatus(inv.deps, "paused", inv.dryRun)
|
|
@@ -61819,7 +62458,7 @@ var runResumeCommand = defineCommand({
|
|
|
61819
62458
|
description: "Sets the project's run policy back to active so runs can start and tasks can be claimed again. Safe to repeat.",
|
|
61820
62459
|
examples: ["overlane run resume", "overlane run resume --dry-run"],
|
|
61821
62460
|
effect: "write",
|
|
61822
|
-
...
|
|
62461
|
+
...common9,
|
|
61823
62462
|
keywords: ["unpause", "re-enable", "continue autonomous", "reactivate", "policy active", "turn on", "restart runs", "lift the pause"],
|
|
61824
62463
|
result: RunPolicyChangeResult,
|
|
61825
62464
|
handler: async (inv) => setPolicyStatus(inv.deps, "active", inv.dryRun)
|
|
@@ -61829,7 +62468,7 @@ var runCommands = [runStartCommand, runNextCommand, runClaimCommand, runDecideCo
|
|
|
61829
62468
|
// ../cli/src/task/queue.ts
|
|
61830
62469
|
init_src();
|
|
61831
62470
|
init_zod();
|
|
61832
|
-
import { randomUUID as
|
|
62471
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
61833
62472
|
import { mkdirSync as mkdirSync8, renameSync as renameSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
61834
62473
|
import { dirname as dirname8, join as join23 } from "node:path";
|
|
61835
62474
|
var TASK_POLICY_PATH = join23(".harness", "task-policy.json");
|
|
@@ -61849,7 +62488,7 @@ var TaskQueueResult = TaskQueue;
|
|
|
61849
62488
|
var TaskPrioritiseResult = withDryRun(external_exports.object({ ...PrioritiseResult.shape, next: external_exports.string() }));
|
|
61850
62489
|
var TaskPolicyResult = external_exports.object({ enforcement: TaskEnforcement, reason: external_exports.string().optional(), changedBy: external_exports.string().optional(), updatedAt: external_exports.string().optional(), localFile: external_exports.string() });
|
|
61851
62490
|
var TaskPolicySetResult = withDryRun(TaskPolicyResult);
|
|
61852
|
-
var
|
|
62491
|
+
var requestId8 = () => `cli-${randomUUID9()}`;
|
|
61853
62492
|
function priorityOf(value, fallback) {
|
|
61854
62493
|
const parsed = TaskPriority.safeParse(value ?? fallback);
|
|
61855
62494
|
if (!parsed.success) throw new UsageError(`--priority must be one of ${TASK_PRIORITIES.join(", ")}`);
|
|
@@ -61888,7 +62527,7 @@ async function prioritiseTask(deps, input2) {
|
|
|
61888
62527
|
const name2 = detectExecutorName(deps.env);
|
|
61889
62528
|
let request;
|
|
61890
62529
|
try {
|
|
61891
|
-
request = PrioritiseRequest.parse({ requestId:
|
|
62530
|
+
request = PrioritiseRequest.parse({ requestId: requestId8(), priority, top: input2.top, origin: name2 === "terminal" ? "user" : "agent", ...input2.reason === void 0 ? {} : { reason: input2.reason }, executor: executorFor(name2) });
|
|
61892
62531
|
} catch (error62) {
|
|
61893
62532
|
throw new UsageError(String(error62));
|
|
61894
62533
|
}
|
|
@@ -61917,7 +62556,7 @@ async function newTask(deps, input2) {
|
|
|
61917
62556
|
const begun = data;
|
|
61918
62557
|
const project = await connectedProject(deps, "task");
|
|
61919
62558
|
const name2 = detectExecutorName(deps.env);
|
|
61920
|
-
const request = PrioritiseRequest.parse({ requestId:
|
|
62559
|
+
const request = PrioritiseRequest.parse({ requestId: requestId8(), priority, top: input2.top, origin: name2 === "terminal" ? "user" : "agent", executor: executorFor(name2) });
|
|
61921
62560
|
try {
|
|
61922
62561
|
const ranked = await serviceCall(deps, project.serviceUrl, project.token)(PrioritiseResult, "POST", taskQueuePaths.prioritise(project.binding.tenantId, project.binding.projectId, begun.taskId), request);
|
|
61923
62562
|
say(deps, `Ranked ${begun.taskId} ${ranked.priority}${input2.top ? " (first)" : ""}.`);
|
|
@@ -61938,7 +62577,7 @@ async function setPolicy(deps, input2) {
|
|
|
61938
62577
|
const enforcement = TaskEnforcement.safeParse(input2.enforcement);
|
|
61939
62578
|
if (!enforcement.success) throw new UsageError(`set needs ${TASK_ENFORCEMENT.join(" or ")}`);
|
|
61940
62579
|
const name2 = detectExecutorName(deps.env);
|
|
61941
|
-
const parsed = SetTaskPolicyRequest.safeParse({ requestId:
|
|
62580
|
+
const parsed = SetTaskPolicyRequest.safeParse({ requestId: requestId8(), enforcement: enforcement.data, ...input2.reason === void 0 ? {} : { reason: input2.reason }, executor: executorFor(name2) });
|
|
61942
62581
|
if (!parsed.success) throw new UsageError(parsed.error.issues.map((issue2) => issue2.message).join("; "));
|
|
61943
62582
|
if (input2.dryRun) {
|
|
61944
62583
|
const project2 = await offlineProject(deps, "task");
|
|
@@ -61965,7 +62604,7 @@ async function startExisting(deps, taskId, dryRun) {
|
|
|
61965
62604
|
}
|
|
61966
62605
|
|
|
61967
62606
|
// ../cli/src/commands/queue.ts
|
|
61968
|
-
var
|
|
62607
|
+
var common10 = { needsAuth: true, needsNetwork: true };
|
|
61969
62608
|
var PRIORITIES2 = ["P0", "P1", "P2", "P3"];
|
|
61970
62609
|
var taskNewCommand = defineCommand({
|
|
61971
62610
|
path: ["task", "new"],
|
|
@@ -61981,7 +62620,7 @@ var taskNewCommand = defineCommand({
|
|
|
61981
62620
|
],
|
|
61982
62621
|
examples: ['overlane task new "Fix login redirect"', 'overlane task new "Hotfix the build" --priority P0 --top'],
|
|
61983
62622
|
effect: "write",
|
|
61984
|
-
...
|
|
62623
|
+
...common10,
|
|
61985
62624
|
keywords: ["new task", "create task", "no active task", "blocked no task", "start work", "need a task", "begin", "quick task"],
|
|
61986
62625
|
result: TaskNewResult,
|
|
61987
62626
|
handler: async (inv) => newTask(inv.deps, {
|
|
@@ -62000,7 +62639,7 @@ var taskNextCommand = defineCommand({
|
|
|
62000
62639
|
description: "Picks the best ready or paused task: P0 before P3, then rank, then milestone and dependency order. When this working copy holds a task and the next one outranks it, says so (preempt) and prints the commands to checkpoint and switch; the preempted task comes back through this command afterwards.",
|
|
62001
62640
|
examples: ["overlane task next"],
|
|
62002
62641
|
effect: "read",
|
|
62003
|
-
...
|
|
62642
|
+
...common10,
|
|
62004
62643
|
keywords: ["what next", "next task", "priority", "what should i work on", "pick work", "resume after", "queue"],
|
|
62005
62644
|
result: TaskNextResult,
|
|
62006
62645
|
handler: async (inv) => taskNext(inv.deps)
|
|
@@ -62011,7 +62650,7 @@ var taskQueueCommand = defineCommand({
|
|
|
62011
62650
|
description: "Lists ready, running, paused and blocked tasks by priority, then rank, then plan order, with each task's priority.",
|
|
62012
62651
|
examples: ["overlane task queue"],
|
|
62013
62652
|
effect: "read",
|
|
62014
|
-
...
|
|
62653
|
+
...common10,
|
|
62015
62654
|
keywords: ["priority list", "ranking", "order", "backlog", "what is queued", "p0"],
|
|
62016
62655
|
result: TaskQueueResult,
|
|
62017
62656
|
handler: async (inv) => taskQueue(inv.deps)
|
|
@@ -62028,7 +62667,7 @@ var taskPrioritiseCommand = defineCommand({
|
|
|
62028
62667
|
],
|
|
62029
62668
|
examples: ["overlane task prioritise task-7 --priority P0 --top", 'overlane task prioritise task-9 --priority P2 --reason "user said later"'],
|
|
62030
62669
|
effect: "write",
|
|
62031
|
-
...
|
|
62670
|
+
...common10,
|
|
62032
62671
|
keywords: ["reprioritize", "reprioritise", "bump", "urgent", "move to top", "rank", "lower priority", "p0", "p1", "p2", "p3"],
|
|
62033
62672
|
result: TaskPrioritiseResult,
|
|
62034
62673
|
handler: async (inv) => prioritiseTask(inv.deps, { taskId: inv.positionals[0], priority: textFlag(inv, "priority"), top: boolFlag(inv, "top"), reason: textFlag(inv, "reason"), dryRun: inv.dryRun })
|
|
@@ -62039,7 +62678,7 @@ var taskPolicyCommand = defineCommand({
|
|
|
62039
62678
|
description: "Reads the project's task requirement (default `required`: edits and mutating shell commands are refused without an active task) and writes it to .harness/task-policy.json for the hooks.",
|
|
62040
62679
|
examples: ["overlane task policy"],
|
|
62041
62680
|
effect: "read",
|
|
62042
|
-
...
|
|
62681
|
+
...common10,
|
|
62043
62682
|
keywords: ["enforcement", "require task", "task gate", "relax", "blocked", "policy"],
|
|
62044
62683
|
result: TaskPolicyResult,
|
|
62045
62684
|
handler: async (inv) => showPolicy2(inv.deps)
|
|
@@ -62052,7 +62691,7 @@ var taskPolicySetCommand = defineCommand({
|
|
|
62052
62691
|
flags: [{ name: "reason", type: "string", value: "TEXT", description: "Why the rule is relaxed (required for relaxed)" }],
|
|
62053
62692
|
examples: ["overlane task policy set required", 'overlane task policy set relaxed --reason "docs-only repository"'],
|
|
62054
62693
|
effect: "write",
|
|
62055
|
-
...
|
|
62694
|
+
...common10,
|
|
62056
62695
|
keywords: ["relax", "turn off task requirement", "require tasks", "allow edits without task", "enforcement"],
|
|
62057
62696
|
result: TaskPolicySetResult,
|
|
62058
62697
|
handler: async (inv) => setPolicy(inv.deps, { enforcement: inv.positionals[0], reason: textFlag(inv, "reason"), dryRun: inv.dryRun })
|
|
@@ -62097,14 +62736,14 @@ var TaskHandoffResult = withDryRun(
|
|
|
62097
62736
|
);
|
|
62098
62737
|
|
|
62099
62738
|
// ../cli/src/commands/task.ts
|
|
62100
|
-
var
|
|
62739
|
+
var common11 = { needsAuth: true, needsNetwork: true };
|
|
62101
62740
|
var taskListCommand = defineCommand({
|
|
62102
62741
|
path: ["task", "list"],
|
|
62103
62742
|
summary: "List the project's tasks and their states",
|
|
62104
62743
|
description: "Lists every task of the connected project with its state, pause reason, version, lease holder, checks and latest checkpoint.",
|
|
62105
62744
|
examples: ["overlane task list"],
|
|
62106
62745
|
effect: "read",
|
|
62107
|
-
...
|
|
62746
|
+
...common11,
|
|
62108
62747
|
keywords: ["tasks", "show all tasks", "see tasks", "backlog", "what tasks exist", "work items"],
|
|
62109
62748
|
result: TaskListResult,
|
|
62110
62749
|
handler: async (inv) => listTasks(inv.deps)
|
|
@@ -62122,7 +62761,7 @@ var taskStartCommand = defineCommand({
|
|
|
62122
62761
|
],
|
|
62123
62762
|
examples: ["overlane task start task-7", 'overlane task start --outcome "Add CSV export" --criterion "export works" --check unit_tests:L2 --path "src/**"', 'overlane task start --outcome "Fix login" --criterion "login passes" --path "src/auth/**" --dry-run'],
|
|
62124
62763
|
effect: "write",
|
|
62125
|
-
...
|
|
62764
|
+
...common11,
|
|
62126
62765
|
keywords: ["begin", "create task", "new task", "open", "claim new", "work item", "contract", "acceptance criteria", "start working"],
|
|
62127
62766
|
result: TaskStartResult,
|
|
62128
62767
|
handler: async (inv) => inv.positionals[0] !== void 0 ? startExisting(inv.deps, inv.positionals[0], inv.dryRun) : startTask(inv.deps, { outcome: textFlag(inv, "outcome"), criteria: listFlag(inv, "criterion"), paths: listFlag(inv, "path"), checks: listFlag(inv, "check"), dryRun: inv.dryRun })
|
|
@@ -62133,7 +62772,7 @@ var taskStatusCommand = defineCommand({
|
|
|
62133
62772
|
description: "Shows the held task from the service: state, lease, acceptance criteria, checks, evidence count and the latest checkpoint. Says so when nothing is held or the lease was lost.",
|
|
62134
62773
|
examples: ["overlane task status"],
|
|
62135
62774
|
effect: "read",
|
|
62136
|
-
...
|
|
62775
|
+
...common11,
|
|
62137
62776
|
keywords: ["current task", "what am i working on", "lease", "active task", "progress", "held task"],
|
|
62138
62777
|
result: TaskStatusResult,
|
|
62139
62778
|
handler: async (inv) => taskStatus(inv.deps)
|
|
@@ -62149,7 +62788,7 @@ var taskCheckpointCommand = defineCommand({
|
|
|
62149
62788
|
],
|
|
62150
62789
|
examples: ['overlane task checkpoint --summary "Parser done" --next "Write the tests"', 'overlane task checkpoint --summary "Out of budget" --next "Resume" --pause quota'],
|
|
62151
62790
|
effect: "write",
|
|
62152
|
-
...
|
|
62791
|
+
...common11,
|
|
62153
62792
|
keywords: ["save", "progress", "pause", "stop work", "park", "quota", "limit reached", "remember place", "snapshot", "save state", "out of budget"],
|
|
62154
62793
|
result: TaskCheckpointResult,
|
|
62155
62794
|
handler: async (inv) => checkpointTask(inv.deps, { summary: textFlag(inv, "summary"), next: textFlag(inv, "next"), pause: textFlag(inv, "pause"), dryRun: inv.dryRun })
|
|
@@ -62161,7 +62800,7 @@ var taskResumeCommand = defineCommand({
|
|
|
62161
62800
|
args: [{ name: "task-id", required: true, description: "The task to resume" }],
|
|
62162
62801
|
examples: ["overlane task resume task-1"],
|
|
62163
62802
|
effect: "write",
|
|
62164
|
-
...
|
|
62803
|
+
...common11,
|
|
62165
62804
|
keywords: ["continue", "pick up", "restart", "reclaim", "after pause", "take over", "carry on"],
|
|
62166
62805
|
result: TaskResumeResult,
|
|
62167
62806
|
handler: async (inv) => resumeTask(inv.deps, { taskId: inv.positionals[0], dryRun: inv.dryRun })
|
|
@@ -62172,7 +62811,7 @@ var taskSubmitCommand = defineCommand({
|
|
|
62172
62811
|
description: "Asks for verification at HEAD. The task is verified only when evidence at or above each required check's level exists for that commit: L2 comes from CI on the pushed commit, L1 from `overlane task evidence`.",
|
|
62173
62812
|
examples: ["overlane task submit", "overlane task submit --dry-run"],
|
|
62174
62813
|
effect: "write",
|
|
62175
|
-
...
|
|
62814
|
+
...common11,
|
|
62176
62815
|
keywords: ["finish", "done", "complete", "verify", "ready for review", "request verification", "hand in", "turn in"],
|
|
62177
62816
|
result: TaskSubmitResult,
|
|
62178
62817
|
handler: async (inv) => submitTask(inv.deps, { dryRun: inv.dryRun })
|
|
@@ -62188,7 +62827,7 @@ var taskEvidenceCommand = defineCommand({
|
|
|
62188
62827
|
],
|
|
62189
62828
|
examples: ["overlane task evidence --level L1 -- pnpm test"],
|
|
62190
62829
|
effect: "write",
|
|
62191
|
-
...
|
|
62830
|
+
...common11,
|
|
62192
62831
|
keywords: ["tests", "prove", "record test result", "verification", "run checks", "L1", "attest", "run the tests and record"],
|
|
62193
62832
|
result: TaskEvidenceResult,
|
|
62194
62833
|
handler: async (inv) => recordEvidence(inv.deps, { level: textFlag(inv, "level"), task: textFlag(inv, "task"), words: inv.positionals, dryRun: inv.dryRun })
|
|
@@ -62204,7 +62843,7 @@ var taskHandoffCommand = defineCommand({
|
|
|
62204
62843
|
],
|
|
62205
62844
|
examples: ["overlane task handoff --to codex", 'overlane task handoff --to claude --summary "API done" --next "Add tests"'],
|
|
62206
62845
|
effect: "write",
|
|
62207
|
-
...
|
|
62846
|
+
...common11,
|
|
62208
62847
|
keywords: ["hand off", "transfer", "give to", "switch agent", "other agent", "codex", "claude", "pass the task", "delegate", "move work", "swap agents"],
|
|
62209
62848
|
result: TaskHandoffResult,
|
|
62210
62849
|
handler: async (inv) => handoffTask(inv.deps, { summary: textFlag(inv, "summary"), next: textFlag(inv, "next"), to: textFlag(inv, "to"), dryRun: inv.dryRun })
|
|
@@ -62235,7 +62874,8 @@ function coreCommands() {
|
|
|
62235
62874
|
...memoryCommands,
|
|
62236
62875
|
...libCommands,
|
|
62237
62876
|
...reviewCommands,
|
|
62238
|
-
...guardCommands
|
|
62877
|
+
...guardCommands,
|
|
62878
|
+
...billingCommands
|
|
62239
62879
|
];
|
|
62240
62880
|
}
|
|
62241
62881
|
function createRegistry(extra = []) {
|