@integrity-labs/agt-cli 0.28.343 → 0.28.345

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.
@@ -6835,14 +6835,18 @@ var FRESH_HEARTBEAT_THRESHOLD_MS = 2 * 60 * 1e3;
6835
6835
  // ../../packages/core/dist/claude-code-usage/banner-parser.js
6836
6836
  var SEP = /[\s·\-–—]+/.source;
6837
6837
  var SUBJECT = /(?:You(?:['’]ve|\s+have)?\s+)?/.source;
6838
- var RESET_DATE = /[A-Za-z]{3,9}\s+\d{1,2}(?:\s*,\s*\d{1,2}(?::\d{2})?\s*(?:am|pm)(?:\s*\(?UTC\)?)?)?/.source;
6838
+ var TIME_OF_DAY = /\d{1,2}(?::\d{2})?\s*(?:am|pm)(?:\s*\(?UTC\)?)?/.source;
6839
+ var RESET_DATE = `(?:[A-Za-z]{3,9}\\s+\\d{1,2}(?:\\s*,\\s*${TIME_OF_DAY})?|${TIME_OF_DAY})`;
6839
6840
  var BANNER_PATTERNS = [
6840
6841
  // Percentage form — pct in group 1, reset in group 2.
6841
6842
  new RegExp(`${SUBJECT}used\\s+(\\d{1,3})%\\s+of\\s+your\\s+weekly\\s+limit${SEP}resets\\s+(${RESET_DATE})`, "i"),
6842
- // Saturated form (ENG-5434) — no pct, reset in group 1. Wrapped to keep
6843
- // the per-pattern shape consistent with the percentage form: the parser
6844
- // checks group 1 for a digit string and treats a missing one as pct=100.
6845
- new RegExp(`${SUBJECT}hit\\s+your\\s+limit${SEP}resets\\s+(${RESET_DATE})`, "i")
6843
+ // Saturated form (ENG-5434, extended by ENG-7904) — no pct, reset in group 1.
6844
+ // An optional qualifier word ("weekly", "5-hour", …) may sit between "your"
6845
+ // and "limit"; matching it keeps the parser resilient to CC's phrasing drift.
6846
+ // Wrapped to keep the per-pattern shape consistent with the percentage form:
6847
+ // the parser checks group 1 for a digit string and treats a missing one as
6848
+ // pct=100.
6849
+ new RegExp(`${SUBJECT}hit\\s+your\\s+(?:[a-z0-9-]+\\s+)?limit${SEP}resets\\s+(${RESET_DATE})`, "i")
6846
6850
  ];
6847
6851
  function parseUsageBanner(text, now = /* @__PURE__ */ new Date()) {
6848
6852
  let bestIndex = -1;
@@ -6890,8 +6894,31 @@ var MONTHS = [
6890
6894
  "dec"
6891
6895
  ];
6892
6896
  var TIME_TAIL = /,\s*(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?\s*$/i;
6897
+ var TIME_ONLY = /^(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?$/i;
6898
+ var MS_PER_DAY = 24 * 60 * 60 * 1e3;
6899
+ function parseAmPm(hourStr, minStr, ampm) {
6900
+ const rawHour = Number.parseInt(hourStr, 10);
6901
+ if (!Number.isFinite(rawHour) || rawHour < 1 || rawHour > 12)
6902
+ return null;
6903
+ let minute = 0;
6904
+ if (minStr) {
6905
+ minute = Number.parseInt(minStr, 10);
6906
+ if (!Number.isFinite(minute) || minute < 0 || minute > 59)
6907
+ return null;
6908
+ }
6909
+ const isPm = ampm.toLowerCase() === "pm";
6910
+ return { hour: rawHour % 12 + (isPm ? 12 : 0), minute };
6911
+ }
6893
6912
  function parseResetDateTime(humanDate, now) {
6894
6913
  const trimmed = humanDate.trim();
6914
+ const timeOnly = trimmed.match(TIME_ONLY);
6915
+ if (timeOnly) {
6916
+ const hm = parseAmPm(timeOnly[1], timeOnly[2], timeOnly[3]);
6917
+ if (!hm)
6918
+ return null;
6919
+ const todayAt = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), hm.hour, hm.minute);
6920
+ return new Date(todayAt <= now.getTime() ? todayAt + MS_PER_DAY : todayAt);
6921
+ }
6895
6922
  const timeMatch = trimmed.match(TIME_TAIL);
6896
6923
  const dateOnly = timeMatch ? trimmed.slice(0, timeMatch.index).trim() : trimmed;
6897
6924
  const parts = dateOnly.split(/\s+/);
@@ -6906,16 +6933,11 @@ function parseResetDateTime(humanDate, now) {
6906
6933
  let hour = 0;
6907
6934
  let minute = 0;
6908
6935
  if (timeMatch) {
6909
- const rawHour = Number.parseInt(timeMatch[1], 10);
6910
- if (!Number.isFinite(rawHour) || rawHour < 1 || rawHour > 12)
6936
+ const hm = parseAmPm(timeMatch[1], timeMatch[2], timeMatch[3]);
6937
+ if (!hm)
6911
6938
  return null;
6912
- if (timeMatch[2]) {
6913
- minute = Number.parseInt(timeMatch[2], 10);
6914
- if (!Number.isFinite(minute) || minute < 0 || minute > 59)
6915
- return null;
6916
- }
6917
- const isPm = timeMatch[3].toLowerCase() === "pm";
6918
- hour = rawHour % 12 + (isPm ? 12 : 0);
6939
+ hour = hm.hour;
6940
+ minute = hm.minute;
6919
6941
  }
6920
6942
  const baseYear = now.getUTCFullYear();
6921
6943
  let resolved = null;
@@ -7162,6 +7184,17 @@ function attributeTranscriptUsageByRun(jsonl) {
7162
7184
  return { perRunModel: [...agg.values()], runIds: [...runIds] };
7163
7185
  }
7164
7186
 
7187
+ // ../../packages/core/dist/claude-code-usage/usage-limit-marker.js
7188
+ var USAGE_LIMIT_MARKER_FILENAME = "claude-usage-limit.json";
7189
+ var USAGE_LIMIT_MARKER_VERSION = 1;
7190
+ function serializeUsageLimitMarker(limitedUntil) {
7191
+ const marker = {
7192
+ version: USAGE_LIMIT_MARKER_VERSION,
7193
+ limited_until: limitedUntil.toISOString()
7194
+ };
7195
+ return JSON.stringify(marker);
7196
+ }
7197
+
7165
7198
  // ../../packages/core/dist/loops/kanban-check.js
7166
7199
  var KANBAN_CHECK_COMMAND = "kanban_list \u2014 pick up any actionable items if you are free.";
7167
7200
  var KANBAN_NUDGE_ACTIONABLE_STATUSES = ["todo", "in_progress"];
@@ -8141,6 +8174,18 @@ var FLAG_REGISTRY = [
8141
8174
  // flipping it on is worth an explicit confirm (ADR-0022 §4).
8142
8175
  sensitive: true
8143
8176
  },
8177
+ {
8178
+ key: "email-guard-enforce-enabled",
8179
+ description: "Platform enable-gate for the email-domain guardrail ENFORCE stage (ENG-5827 / A5, migrated to a flag under ENG-7899 / ADR-0022). When ON for an org, an org (or scope) at email_guard_stage=enforce actually BLOCKS sends to non-allowed domains: the rollout UI unlocks the Enforce option and PUT /email-guard accepts enforce. When OFF (default) a per-org enforce stage degrades to observe-only (would_block, never blocks) and the UI shows Enforce as not yet available. Ungates a control that blocks real customer email, so flip on per org only once block-spike alerting (ENG-5847) is firing. Evaluated per-org. Operator override: env EMAIL_DOMAIN_ENFORCE_ENABLED (an explicitly-set value wins over the flag; highest precedence per host). Ships dark.",
8180
+ flagType: "boolean",
8181
+ // Declared safe value is `false` (enforce degrades to observe-only = today's behaviour).
8182
+ // A flag-DB read error degrades here, so a flags outage can never silently start blocking
8183
+ // real email - the fail-closed direction for a blocking compliance control.
8184
+ defaultValue: false,
8185
+ // Flipping it on ARMS a control that blocks real customer email, so it is a
8186
+ // deliberate, audited per-org flip (ADR-0022 §4).
8187
+ sensitive: true
8188
+ },
8144
8189
  {
8145
8190
  key: "slack-reply-binding",
8146
8191
  description: "Slack reply-target binding (ENG-7396 / WS2, cross-thread reply routing): the model names which inbound it answers (inbound_id) and the server resolves the destination from its own verified record. shadow = classify + count only, routing unchanged; warn = same routing plus a tool-result note so the model self-corrects; enforce = route a bound reply to the registry thread and REJECT a reply whose target matches no inbound this process delivered. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_SLACK_REPLY_BINDING spawn env (the operator/canary override, ADR-0022). Ships shadow.",
@@ -10038,6 +10083,8 @@ export {
10038
10083
  sumTranscriptUsageInWindow,
10039
10084
  isEmptyTotals,
10040
10085
  attributeTranscriptUsageByRun,
10086
+ USAGE_LIMIT_MARKER_FILENAME,
10087
+ serializeUsageLimitMarker,
10041
10088
  KANBAN_CHECK_COMMAND,
10042
10089
  KANBAN_NUDGE_ACTIONABLE_STATUSES,
10043
10090
  isSystemInjectedContent,
@@ -10102,4 +10149,4 @@ export {
10102
10149
  stopAllSessionsAndWait,
10103
10150
  getProjectDir
10104
10151
  };
10105
- //# sourceMappingURL=chunk-7OBFGSQS.js.map
10152
+ //# sourceMappingURL=chunk-O5IINJDB.js.map