@useshifu/coding-harness 0.3.35 → 0.3.37

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.
@@ -0,0 +1,11 @@
1
+ function deadlineError() {
2
+ return Object.assign(new Error("The sync run deadline was reached; unfinished work remains pending."), { code: "SHIFU_RUN_DEADLINE" });
3
+ }
4
+
5
+ function requestTimeout(deadlineAt = Infinity, maximumMs = 30_000) {
6
+ const remaining = deadlineAt - Date.now();
7
+ if (!(remaining > 0)) throw deadlineError();
8
+ return Math.min(maximumMs, Math.ceil(remaining));
9
+ }
10
+
11
+ module.exports = { deadlineError, requestTimeout };
@@ -0,0 +1,32 @@
1
+ const TOKEN_PATTERNS = [
2
+ /\bcs_sk_[a-f0-9]{16}_[a-f0-9]{64}\b/,
3
+ /-----BEGIN (?:RSA |EC |DSA |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/,
4
+ /\bgh[pousr]_[A-Za-z0-9_]{36,255}\b/,
5
+ /\bgithub_pat_[A-Za-z0-9_]{40,255}\b/,
6
+ /\bghs_[0-9]+_[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/,
7
+ /\bsk-(?:(?:proj|svcacct)-)?[A-Za-z0-9_-]{40,}\b/,
8
+ /\bxox[bp]-(?:[0-9]{8,}-){2,3}[A-Za-z0-9]{20,}\b/,
9
+ ];
10
+ const AWS_KEY = /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g;
11
+ const BEARER = /\bauthorization(?:\\*["'])?\s*[:=]\s*(?:\\*["'])?\s*bearer[ \t]+([A-Za-z0-9._~+/-]{32,}={0,2})/gi;
12
+ const CONNECTION = /\b(?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s:/@"']*:([^\s/@"']+)@[^\s"'<>]+/gi;
13
+ const PLACEHOLDERS = new Set(["password", "your_password", "your-password", "your_token", "your-token", "replace_me", "replace-me", "changeme", "change_me", "example", "example_password", "redacted", "private_secret"]);
14
+
15
+ function placeholder(value) {
16
+ try { value = decodeURIComponent(value); } catch {}
17
+ return PLACEHOLDERS.has(value.toLowerCase()) || /^(?:[*xX]+|<[^>]+>|\$\{[^}]+\}|\$[A-Z_][A-Z0-9_]*|\{\{[^}]+\}\})$/.test(value);
18
+ }
19
+
20
+ // This detects recognizable credential formats, not every confidential detail.
21
+ function assertNoCredentials(value) {
22
+ let text;
23
+ try { text = typeof value === "string" ? value : Buffer.isBuffer(value) ? value.toString("utf8") : JSON.stringify(value) || ""; }
24
+ catch { throw Object.assign(new Error("Credential inspection could not complete."), { code: "SHIFU_CREDENTIAL_CHECK_FAILED" }); }
25
+ if (TOKEN_PATTERNS.some((pattern) => pattern.test(text)) ||
26
+ [...text.matchAll(AWS_KEY)].some(([key]) => key !== "AKIAIOSFODNN7EXAMPLE") ||
27
+ [...text.matchAll(BEARER), ...text.matchAll(CONNECTION)].some((match) => !placeholder(match[1]))) {
28
+ throw Object.assign(new Error("Credential-like content was detected. Remove credentials before processing."), { code: "SHIFU_CREDENTIAL_DETECTED" });
29
+ }
30
+ }
31
+
32
+ module.exports = { assertNoCredentials };
@@ -7,16 +7,16 @@ function toggle(value, name) {
7
7
  return value === "on";
8
8
  }
9
9
 
10
- async function chooseSetupOptions(config, { option = () => undefined, ask } = {}) {
10
+ async function chooseSetupOptions(config, { option = () => undefined, ask, includeHistory = true } = {}) {
11
11
  const preferences = normalizeContextPreferences(config?.contextPreferences);
12
12
  const growth = toggle(option("--growth-feedback"), "growth feedback");
13
13
  const alignment = toggle(option("--decision-alignment"), "decision alignment");
14
14
  const days = option("--backfill-days");
15
- let initialBackfill = days === undefined ? config?.initialBackfill : createInitialBackfill(days);
15
+ let initialBackfill = !includeHistory || days === undefined ? config?.initialBackfill : createInitialBackfill(days);
16
16
  if (growth !== undefined) preferences.growthFeedback = growth;
17
17
  if (alignment !== undefined) preferences.decisionAlignment = alignment;
18
18
  if (ask) {
19
- if (initialBackfill === undefined) {
19
+ if (includeHistory && initialBackfill === undefined) {
20
20
  const answer = (await ask("Initial history: [1] Last 15 days (recommended), [2] Last 30 days, [3] Custom days, [4] Start from now. Choose [1]: ")).trim();
21
21
  if (!["", "1", "2", "3", "4"].includes(answer)) throw new Error("Choose history option 1, 2, 3 or 4. Nothing was changed.");
22
22
  const selectedDays = answer === "3" ? (await ask("How many days? ")).trim() : answer === "2" ? 30 : answer === "4" ? 0 : 15;
@@ -32,7 +32,6 @@ async function chooseSetupOptions(config, { option = () => undefined, ask } = {}
32
32
  preferences[key] = !["off", "no", "n"].includes(answer);
33
33
  }
34
34
  }
35
- if (!config && initialBackfill === undefined) initialBackfill = createInitialBackfill(15);
36
35
  return { contextPreferences: preferences, ...(initialBackfill === undefined ? {} : { initialBackfill }) };
37
36
  }
38
37