@lore-co/cli 0.2.14 → 0.2.16

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.
Files changed (74) hide show
  1. package/README.md +78 -4
  2. package/dist/capture-scope.d.ts +12 -0
  3. package/dist/capture-scope.d.ts.map +1 -0
  4. package/dist/capture-scope.js +45 -0
  5. package/dist/capture-scope.js.map +1 -0
  6. package/dist/cli.d.ts +7 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +126 -38
  9. package/dist/cli.js.map +1 -1
  10. package/dist/command-help.d.ts +2 -1
  11. package/dist/command-help.d.ts.map +1 -1
  12. package/dist/command-help.js +4 -1
  13. package/dist/command-help.js.map +1 -1
  14. package/dist/connect-project.d.ts +15 -0
  15. package/dist/connect-project.d.ts.map +1 -0
  16. package/dist/connect-project.js +87 -0
  17. package/dist/connect-project.js.map +1 -0
  18. package/dist/connections.d.ts +3 -1
  19. package/dist/connections.d.ts.map +1 -1
  20. package/dist/connections.js +6 -1
  21. package/dist/connections.js.map +1 -1
  22. package/dist/devin-cli.d.ts.map +1 -1
  23. package/dist/devin-cli.js +14 -6
  24. package/dist/devin-cli.js.map +1 -1
  25. package/dist/devin.d.ts.map +1 -1
  26. package/dist/devin.js +5 -2
  27. package/dist/devin.js.map +1 -1
  28. package/dist/generated-assets.d.ts +5 -4
  29. package/dist/generated-assets.d.ts.map +1 -1
  30. package/dist/generated-assets.js +5 -4
  31. package/dist/generated-assets.js.map +1 -1
  32. package/dist/host.d.ts.map +1 -1
  33. package/dist/host.js +5 -5
  34. package/dist/host.js.map +1 -1
  35. package/dist/reliability-store.d.ts +5 -0
  36. package/dist/reliability-store.d.ts.map +1 -1
  37. package/dist/reliability-store.js +9 -1
  38. package/dist/reliability-store.js.map +1 -1
  39. package/dist/remember.d.ts.map +1 -1
  40. package/dist/remember.js +8 -1
  41. package/dist/remember.js.map +1 -1
  42. package/dist/retrieval-task.d.ts +20 -0
  43. package/dist/retrieval-task.d.ts.map +1 -0
  44. package/dist/retrieval-task.js +78 -0
  45. package/dist/retrieval-task.js.map +1 -0
  46. package/dist/runtime-redaction.d.ts +2 -0
  47. package/dist/runtime-redaction.d.ts.map +1 -0
  48. package/dist/runtime-redaction.js +69 -0
  49. package/dist/runtime-redaction.js.map +1 -0
  50. package/dist/runtime.d.ts +2 -2
  51. package/dist/runtime.d.ts.map +1 -1
  52. package/dist/runtime.js +129 -89
  53. package/dist/runtime.js.map +1 -1
  54. package/dist/self-host.d.ts +2 -1
  55. package/dist/self-host.d.ts.map +1 -1
  56. package/dist/self-host.js +4 -3
  57. package/dist/self-host.js.map +1 -1
  58. package/dist/signed-snapshot.d.ts.map +1 -1
  59. package/dist/signed-snapshot.js +2 -0
  60. package/dist/signed-snapshot.js.map +1 -1
  61. package/dist/skill-command.d.ts +20 -0
  62. package/dist/skill-command.d.ts.map +1 -0
  63. package/dist/skill-command.js +215 -0
  64. package/dist/skill-command.js.map +1 -0
  65. package/dist/skill-guidance.d.ts +2 -0
  66. package/dist/skill-guidance.d.ts.map +1 -0
  67. package/dist/skill-guidance.js +7 -0
  68. package/dist/skill-guidance.js.map +1 -0
  69. package/dist/skills.d.ts +16 -0
  70. package/dist/skills.d.ts.map +1 -0
  71. package/dist/skills.js +126 -0
  72. package/dist/skills.js.map +1 -0
  73. package/dist/update.js +3 -3
  74. package/package.json +7 -3
@@ -0,0 +1,69 @@
1
+ const NON_SECRET_TOKEN_VALUES = new Set([
2
+ "available",
3
+ "configured",
4
+ "generated",
5
+ "optional",
6
+ "placeholder",
7
+ "redacted",
8
+ "required",
9
+ "undefined",
10
+ ]);
11
+ function redactedCredential(value) {
12
+ // Preserve markers from earlier token rules and repeated redaction passes.
13
+ if (/^\[REDACTED(?::[A-Z_]+|_[A-Z_]+)?\][.,!?]*$/u.test(value)) {
14
+ return value;
15
+ }
16
+ const trailing = /[.,!?]+$/u.exec(value)?.[0] ?? "";
17
+ return `[REDACTED:CREDENTIAL]${trailing}`;
18
+ }
19
+ // This standalone runtime cannot import @lore-co/core after it is copied to
20
+ // ~/.lore. Keep these rules aligned with core/redaction.ts through parity tests.
21
+ // Match invisible characters inside tokens without changing ordinary text;
22
+ // real whitespace still separates token bodies and adjacent lines.
23
+ const TOKEN_GAP = "(?:\\p{Cf}|(?!\\s)\\p{Cc})*";
24
+ const tokenPrefix = (prefix) => Array.from(prefix, (character) => character.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")).join(TOKEN_GAP);
25
+ const tokenBody = (characters, minimum, maximum) => `${characters}(?:${TOKEN_GAP}${characters}){${minimum - 1},${maximum === undefined ? "" : maximum - 1}}`;
26
+ const providerToken = (prefix, characters, minimum, maximum) => tokenPrefix(prefix) + TOKEN_GAP + tokenBody(characters, minimum, maximum);
27
+ const AUTHORIZATION_TOKEN_PATTERN = new RegExp([
28
+ `\\b(${tokenPrefix("Bearer")}|${tokenPrefix("Basic")})`,
29
+ "[\\s\\p{Cc}\\p{Cf}]+",
30
+ tokenBody(/[A-Za-z0-9._~+\/=-]/u.source, 8),
31
+ ].join(""), "giu");
32
+ const JWT_TOKEN_PATTERN = new RegExp(`\\b${tokenPrefix("eyJ")}${TOKEN_GAP}${tokenBody("[A-Za-z0-9_-]", 8)}(?:${TOKEN_GAP}\\.${TOKEN_GAP}${tokenBody("[A-Za-z0-9_-]", 8)}){2}\\b`, "gu");
33
+ const PROVIDER_TOKEN_PATTERN = new RegExp(`\\b(?:${[
34
+ ...["sk-", "glpat-", "npm_", "pypi-"].map((prefix) => providerToken(prefix, "[A-Za-z0-9_-]", 16)),
35
+ ...["sk_live_", "sk_test_", "rk_live_", "rk_test_", "whsec_"].map((prefix) => providerToken(prefix, "[A-Za-z0-9]", 16)),
36
+ ...["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"].map((prefix) => providerToken(prefix, "[A-Za-z0-9_]", 20)),
37
+ ...["xoxb-", "xoxa-", "xoxp-", "xoxr-", "xoxs-"].map((prefix) => providerToken(prefix, "[A-Za-z0-9-]", 10)),
38
+ providerToken("AIza", "[A-Za-z0-9_-]", 20),
39
+ providerToken("AKIA", "[0-9A-Z]", 16, 16),
40
+ ].join("|")})\\b`, "gu");
41
+ export function redactSecrets(text) {
42
+ return text
43
+ .replace(/-----BEGIN (?:RSA |EC |OPENSSH |DSA |ENCRYPTED )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA |ENCRYPTED )?PRIVATE KEY-----/gu, "[REDACTED:PRIVATE_KEY]")
44
+ .replace(AUTHORIZATION_TOKEN_PATTERN, (_match, scheme) => `${scheme.replace(/[\p{Cc}\p{Cf}]/gu, "")} [REDACTED:AUTHORIZATION]`)
45
+ .replace(/\b((?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|redis|amqps?):\/\/[^:\s/@]+:)[^@\s/]+@/giu, (_match, prefix) => `${prefix}[REDACTED:PASSWORD]@`)
46
+ .replace(JWT_TOKEN_PATTERN, "[REDACTED:JWT]")
47
+ .replace(PROVIDER_TOKEN_PATTERN, "[REDACTED:API_KEY]")
48
+ .replace(/(["']?)\b((?:(?:[A-Za-z][A-Za-z0-9]*[_-])*(?:api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|private[_-]?key|connection[_-]?(?:string|url)|database[_-]?url|token|secret|password|passwd|credential)|[A-Za-z][A-Za-z0-9]*(?:token|secret|password|passwd|credential|apiKey|privateKey|connectionString|databaseUrl)))\b\1(\s*[:=]\s*)(["']?)([^\s,"'};]{4,})\4/giu, (_match, keyQuote, name, separator, valueQuote, value) => `${keyQuote}${name}${keyQuote}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`)
49
+ .replace(/(["']?)\b(api[ _-]?key|access[ _-]?token|auth[ _-]?token|client[ _-]?secret|private[ _-]?key|verification[ _-]?token|password|passwd|secret|credential)\b\1(\s+(?:is|was|equals?)\s+)(["']?)([^\s,"'};]{4,})\4/giu, (_match, keyQuote, name, separator, valueQuote, value) => `${keyQuote}${name}${keyQuote}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`)
50
+ .replace(/\b(token|credential)\b(\s+(?:is|was|equals?)\s+)(["']?)([^\s,"'};]{8,})\3/giu, (match, name, separator, valueQuote, value) => {
51
+ const normalized = value
52
+ .replace(/^["']|["']$/gu, "")
53
+ .replace(/[.,!?]+$/gu, "");
54
+ const knownPlaceholder = NON_SECRET_TOKEN_VALUES.has(normalized.toLowerCase());
55
+ const classes = [
56
+ /[a-z]/u,
57
+ /[A-Z]/u,
58
+ /[0-9]/u,
59
+ /[^A-Za-z0-9]/u,
60
+ ].filter((pattern) => pattern.test(normalized)).length;
61
+ return !knownPlaceholder &&
62
+ (normalized.length >= 16 ||
63
+ (normalized.length >= 10 && classes >= 2))
64
+ ? `${name}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`
65
+ : match;
66
+ })
67
+ .replace(/\b((?:set-)?cookie\s*:\s*)[^\r\n]+/giu, (_match, prefix) => `${prefix}[REDACTED:AUTHORIZATION]`);
68
+ }
69
+ //# sourceMappingURL=runtime-redaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-redaction.js","sourceRoot":"","sources":["../src/runtime-redaction.ts"],"names":[],"mappings":"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"}
package/dist/runtime.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { redactSecrets } from "./runtime-redaction.js";
1
2
  export declare const COMMAND_HOOK_AGENT_NAMES: readonly ["codex", "claude", "copilot-cli", "copilot-vscode", "cursor", "polytoken"];
2
3
  export type CommandHookAgentName = (typeof COMMAND_HOOK_AGENT_NAMES)[number];
3
4
  /** @deprecated Use CommandHookAgentName for native command-hook integrations. */
@@ -17,6 +18,7 @@ export interface TurnRequest {
17
18
  agent: CommandHookAgentName;
18
19
  sessionId: string;
19
20
  retainedReceiptIds?: string[];
21
+ task?: string;
20
22
  previousAssistant: {
21
23
  content: string;
22
24
  id?: string;
@@ -115,7 +117,6 @@ export interface LineageMetadata {
115
117
  * be attributed to the machine that produced them.
116
118
  */
117
119
  export declare function readLineageMetadata(home?: string, environment?: NodeJS.ProcessEnv): Promise<LineageMetadata>;
118
- export declare function redactSecrets(text: string): string;
119
120
  export declare function createTurnRequest(input: HookInput, agent: CommandHookAgentName, pending: PendingAssistantMessage, now: Date, lineage?: LineageMetadata): Promise<TurnRequest | null>;
120
121
  interface GuardTrigger {
121
122
  action: "edit" | "commit" | "deploy" | "command";
@@ -133,5 +134,4 @@ export declare function handleHookEvent(value: unknown, agent: CommandHookAgentN
133
134
  export declare function getCursorContext(sessionId: string, prompt: string, options?: HookRuntimeOptions): Promise<string>;
134
135
  export declare function completeCursorResponse(sessionId: string, response: string, options?: HookRuntimeOptions): Promise<void>;
135
136
  export declare function runHook(args?: readonly string[]): Promise<void>;
136
- export {};
137
137
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
package/dist/runtime.js CHANGED
@@ -1,6 +1,11 @@
1
+ import { redactSecrets } from "./runtime-redaction.js";
2
+ export { redactSecrets } from "./runtime-redaction.js";
1
3
  import { createHash, randomUUID } from "node:crypto";
4
+ import { CAPTURE_CONFLICT_MESSAGES } from "@lore-co/core/capture-conflict";
2
5
  import { approachGuidance } from "./approach-guidance.js";
6
+ import { skillGuidance } from "./skill-guidance.js";
3
7
  import { retainedContextTexts, retainedReceiptIds, rememberDeliveredContext } from "./retained-context.js";
8
+ import { clearRetrievalTask, resolveRetrievalTask } from "./retrieval-task.js";
4
9
  import { access, chmod, mkdir, readFile, stat, } from "node:fs/promises";
5
10
  import { constants as fsConstants, realpathSync } from "node:fs";
6
11
  import { execFile as execFileCallback } from "node:child_process";
@@ -8,7 +13,7 @@ import { dirname, parse, relative, resolve } from "node:path";
8
13
  import { homedir } from "node:os";
9
14
  import { fileURLToPath, pathToFileURL } from "node:url";
10
15
  import { promisify } from "node:util";
11
- import { boundedUtf8Text, repositoryScopeFromGitRoot, } from "./repository.js";
16
+ import { boundedUtf8Text, defaultGitPushBranches, repositoryScopeFromGitRoot, } from "./repository.js";
12
17
  import { ReliabilityStore, ReliabilityStoreError, atomicWriteJson as durableAtomicWriteJson, classifyRetryFailure, createIntegrationInvocationAttempt, durableUnlink, recordLocalGuardMetric, recordLocalRetrievalMetric, } from "./reliability-store.js";
13
18
  import { writeInvocationAttemptBounded, writeInvocationCompletionBounded, } from "./invocation-health-writer.js";
14
19
  import { SignedSnapshotError, verifySignedSnapshot, } from "./signed-snapshot.js";
@@ -58,24 +63,6 @@ const RELIABILITY_REASON_CODES = new Set([
58
63
  "invalid_response",
59
64
  "integration_unsupported",
60
65
  ]);
61
- const NON_SECRET_TOKEN_VALUES = new Set([
62
- "available",
63
- "configured",
64
- "generated",
65
- "optional",
66
- "placeholder",
67
- "redacted",
68
- "required",
69
- "undefined",
70
- ]);
71
- function redactedCredential(value) {
72
- // Preserve markers from earlier token rules and repeated redaction passes.
73
- if (/^\[REDACTED(?::[A-Z_]+|_[A-Z_]+)?\][.,!?]*$/u.test(value)) {
74
- return value;
75
- }
76
- const trailing = /[.,!?]+$/u.exec(value)?.[0] ?? "";
77
- return `[REDACTED:CREDENTIAL]${trailing}`;
78
- }
79
66
  const execFile = promisify(execFileCallback);
80
67
  function homeDirectory(override) {
81
68
  return override ?? process.env.LORE_HOME ?? process.env.HOME ?? homedir();
@@ -339,52 +326,6 @@ function deterministicUuid(value) {
339
326
  joined.slice(20, 32),
340
327
  ].join("-");
341
328
  }
342
- // This standalone runtime cannot import @lore-co/core after it is copied to
343
- // ~/.lore. Keep these rules aligned with core/redaction.ts through parity tests.
344
- // Match invisible characters inside tokens without changing ordinary text;
345
- // real whitespace still separates token bodies and adjacent lines.
346
- const TOKEN_GAP = "(?:\\p{Cf}|(?!\\s)\\p{Cc})*";
347
- const tokenPrefix = (prefix) => Array.from(prefix, (character) => character.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")).join(TOKEN_GAP);
348
- const tokenBody = (characters, minimum, maximum) => `${characters}(?:${TOKEN_GAP}${characters}){${minimum - 1},${maximum === undefined ? "" : maximum - 1}}`;
349
- const providerToken = (prefix, characters, minimum, maximum) => tokenPrefix(prefix) + TOKEN_GAP + tokenBody(characters, minimum, maximum);
350
- const AUTHORIZATION_TOKEN_PATTERN = new RegExp(`\\b(${tokenPrefix("Bearer")}|${tokenPrefix("Basic")})[\\s\\p{Cc}\\p{Cf}]+${tokenBody("[A-Za-z0-9._~+/=-]", 8)}`, "giu");
351
- const JWT_TOKEN_PATTERN = new RegExp(`\\b${tokenPrefix("eyJ")}${TOKEN_GAP}${tokenBody("[A-Za-z0-9_-]", 8)}(?:${TOKEN_GAP}\\.${TOKEN_GAP}${tokenBody("[A-Za-z0-9_-]", 8)}){2}\\b`, "gu");
352
- const PROVIDER_TOKEN_PATTERN = new RegExp(`\\b(?:${[
353
- ...["sk-", "glpat-", "npm_", "pypi-"].map((prefix) => providerToken(prefix, "[A-Za-z0-9_-]", 16)),
354
- ...["sk_live_", "sk_test_", "rk_live_", "rk_test_", "whsec_"].map((prefix) => providerToken(prefix, "[A-Za-z0-9]", 16)),
355
- ...["ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"].map((prefix) => providerToken(prefix, "[A-Za-z0-9_]", 20)),
356
- ...["xoxb-", "xoxa-", "xoxp-", "xoxr-", "xoxs-"].map((prefix) => providerToken(prefix, "[A-Za-z0-9-]", 10)),
357
- providerToken("AIza", "[A-Za-z0-9_-]", 20),
358
- providerToken("AKIA", "[0-9A-Z]", 16, 16),
359
- ].join("|")})\\b`, "gu");
360
- export function redactSecrets(text) {
361
- return text
362
- .replace(/-----BEGIN (?:RSA |EC |OPENSSH |DSA |ENCRYPTED )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA |ENCRYPTED )?PRIVATE KEY-----/gu, "[REDACTED:PRIVATE_KEY]")
363
- .replace(AUTHORIZATION_TOKEN_PATTERN, (_match, scheme) => `${scheme.replace(/[\p{Cc}\p{Cf}]/gu, "")} [REDACTED:AUTHORIZATION]`)
364
- .replace(/\b((?:postgres(?:ql)?|mysql|mariadb|mongodb(?:\+srv)?|redis|amqps?):\/\/[^:\s/@]+:)[^@\s/]+@/giu, (_match, prefix) => `${prefix}[REDACTED:PASSWORD]@`)
365
- .replace(JWT_TOKEN_PATTERN, "[REDACTED:JWT]")
366
- .replace(PROVIDER_TOKEN_PATTERN, "[REDACTED:API_KEY]")
367
- .replace(/(["']?)\b((?:(?:[A-Za-z][A-Za-z0-9]*[_-])*(?:api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|private[_-]?key|connection[_-]?(?:string|url)|database[_-]?url|token|secret|password|passwd|credential)|[A-Za-z][A-Za-z0-9]*(?:token|secret|password|passwd|credential|apiKey|privateKey|connectionString|databaseUrl)))\b\1(\s*[:=]\s*)(["']?)([^\s,"'};]{4,})\4/giu, (_match, keyQuote, name, separator, valueQuote, value) => `${keyQuote}${name}${keyQuote}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`)
368
- .replace(/(["']?)\b(api[ _-]?key|access[ _-]?token|auth[ _-]?token|client[ _-]?secret|private[ _-]?key|verification[ _-]?token|password|passwd|secret|credential)\b\1(\s+(?:is|was|equals?)\s+)(["']?)([^\s,"'};]{4,})\4/giu, (_match, keyQuote, name, separator, valueQuote, value) => `${keyQuote}${name}${keyQuote}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`)
369
- .replace(/\b(token|credential)\b(\s+(?:is|was|equals?)\s+)(["']?)([^\s,"'};]{8,})\3/giu, (match, name, separator, valueQuote, value) => {
370
- const normalized = value
371
- .replace(/^["']|["']$/gu, "")
372
- .replace(/[.,!?]+$/gu, "");
373
- const knownPlaceholder = NON_SECRET_TOKEN_VALUES.has(normalized.toLowerCase());
374
- const classes = [
375
- /[a-z]/u,
376
- /[A-Z]/u,
377
- /[0-9]/u,
378
- /[^A-Za-z0-9]/u,
379
- ].filter((pattern) => pattern.test(normalized)).length;
380
- return !knownPlaceholder &&
381
- (normalized.length >= 16 ||
382
- (normalized.length >= 10 && classes >= 2))
383
- ? `${name}${separator}${valueQuote}${redactedCredential(value)}${valueQuote}`
384
- : match;
385
- })
386
- .replace(/\b((?:set-)?cookie\s*:\s*)[^\r\n]+/giu, (_match, prefix) => `${prefix}[REDACTED:AUTHORIZATION]`);
387
- }
388
329
  async function atomicWriteJson(path, value) {
389
330
  await mkdir(dirname(path), { recursive: true, mode: 0o700 });
390
331
  await chmod(dirname(path), 0o700);
@@ -703,17 +644,38 @@ function contextDeliveriesUrl(apiUrl) {
703
644
  }
704
645
  class RuntimeHttpError extends Error {
705
646
  httpStatus;
706
- constructor(message, httpStatus) {
647
+ retryable;
648
+ constructor(message, httpStatus, retryable) {
707
649
  super(message);
708
650
  this.name = "RuntimeHttpError";
709
651
  this.httpStatus = httpStatus;
710
- }
711
- }
712
- async function boundedResponseJson(response) {
652
+ this.retryable = retryable;
653
+ }
654
+ }
655
+ async function captureHttpError(response, operation) {
656
+ // Keep only known diagnostic fields: an upstream error body may contain
657
+ // captured text, secrets, or HTML. A request ID lets support find server logs.
658
+ const body = await boundedResponseJson(response, 8_192).catch(() => null);
659
+ const reason = isObject(body) && typeof body.reason === "string" &&
660
+ Object.hasOwn(CAPTURE_CONFLICT_MESSAGES, body.reason) ? body.reason : undefined;
661
+ const legacyMessages = new Set([
662
+ "Connector event ID was reused with a different observation",
663
+ "Connector event ID was reused with a different request",
664
+ "Connector event ID is already used by another event type",
665
+ ]);
666
+ const detail = reason === undefined
667
+ ? isObject(body) && typeof body.message === "string" && legacyMessages.has(body.message) ? body.message : undefined
668
+ : `${reason}: ${CAPTURE_CONFLICT_MESSAGES[reason]}`;
669
+ const requestId = response.headers.get("x-request-id") ?? (isObject(body) ? body.requestId : undefined);
670
+ const reference = typeof requestId === "string" && /^[a-zA-Z0-9._:-]{1,128}$/u.test(requestId)
671
+ ? ` (request ${requestId})` : "";
672
+ return new RuntimeHttpError(`${operation} failed with HTTP ${response.status}${detail ? `: ${detail}` : ""}${reference}`, response.status, response.status === 409 && isObject(body) && body.retryable === true ? true : undefined);
673
+ }
674
+ async function boundedResponseJson(response, maxBytes = MAX_RESPONSE_BYTES) {
713
675
  const declaredLength = response.headers.get("content-length");
714
676
  if (declaredLength !== null &&
715
677
  Number.isFinite(Number(declaredLength)) &&
716
- Number(declaredLength) > MAX_RESPONSE_BYTES) {
678
+ Number(declaredLength) > maxBytes) {
717
679
  await response.body?.cancel();
718
680
  throw new Error("Lore response exceeds the reliability size limit");
719
681
  }
@@ -730,7 +692,7 @@ async function boundedResponseJson(response) {
730
692
  break;
731
693
  }
732
694
  bytes += chunk.value.byteLength;
733
- if (bytes > MAX_RESPONSE_BYTES) {
695
+ if (bytes > maxBytes) {
734
696
  await reader.cancel();
735
697
  throw new Error("Lore response exceeds the reliability size limit");
736
698
  }
@@ -839,6 +801,10 @@ function deliveryFromResponse(value) {
839
801
  : memorySummaries(value.memories);
840
802
  return {
841
803
  context: boundedContext(context),
804
+ ...(typeof value.relatedContext === "string" ? { relatedContext: redactSecrets(value.relatedContext).slice(0, 2_500) }
805
+ : isObject(value.context) && typeof value.context.relatedContext === "string" ? { relatedContext: redactSecrets(value.context.relatedContext).slice(0, 2_500) } : {}),
806
+ ...(typeof value.skillContext === "string" && value.skillContext.length <= 72_000 ? { skillContext: redactSecrets(value.skillContext) }
807
+ : isObject(value.context) && typeof value.context.skillContext === "string" && value.context.skillContext.length <= 72_000 ? { skillContext: redactSecrets(value.context.skillContext) } : {}),
842
808
  completeContext: context.length <= MAX_CONTEXT_CHARS,
843
809
  ...(receiptId === undefined ? {} : { receiptId }),
844
810
  learned,
@@ -891,6 +857,8 @@ function deliveryFromSignedContext(payload, expectedRequest) {
891
857
  }
892
858
  return deliveryFromResponse({
893
859
  context: payload.context,
860
+ relatedContext: payload.relatedContext,
861
+ skillContext: payload.skillContext,
894
862
  receipt: { id: payload.receiptId },
895
863
  memories: payload.memories,
896
864
  hits: payload.hits,
@@ -1137,6 +1105,8 @@ async function postTurn(config, request, fetchImplementation, store) {
1137
1105
  const response = await fetchImplementation(turnsUrl(config.apiUrl), {
1138
1106
  method: "POST",
1139
1107
  headers: {
1108
+ "x-lore-context": "related-work-v1",
1109
+ "x-lore-skills": "skills-v1",
1140
1110
  accept: runtimeAccept(config),
1141
1111
  authorization: `Bearer ${config.token}`,
1142
1112
  "content-type": "application/json",
@@ -1152,7 +1122,7 @@ async function postTurn(config, request, fetchImplementation, store) {
1152
1122
  return postTurn(config, compatible, fetchImplementation, store);
1153
1123
  }
1154
1124
  if (!response.ok) {
1155
- throw new RuntimeHttpError(`Lore turn request failed with HTTP ${response.status}`, response.status);
1125
+ throw await captureHttpError(response, "Lore turn request");
1156
1126
  }
1157
1127
  const value = await protocolResponseJson(response);
1158
1128
  if (config.version === 1) {
@@ -1202,7 +1172,7 @@ async function postTurn(config, request, fetchImplementation, store) {
1202
1172
  task: {
1203
1173
  agent: request.agent,
1204
1174
  ...(request.scope === undefined ? {} : { scope: request.scope }),
1205
- task: request.currentUser.content.trim(),
1175
+ task: request.task ?? request.currentUser.content.trim(),
1206
1176
  },
1207
1177
  });
1208
1178
  await store
@@ -1248,7 +1218,7 @@ async function postPromptObservation(config, request, fetchImplementation, _stor
1248
1218
  signal: AbortSignal.timeout(config.timeoutMs ?? 2_500),
1249
1219
  });
1250
1220
  if (!response.ok) {
1251
- throw new RuntimeHttpError(`Lore prompt observation failed with HTTP ${response.status}`, response.status);
1221
+ throw await captureHttpError(response, "Lore prompt observation");
1252
1222
  }
1253
1223
  const value = await protocolResponseJson(response);
1254
1224
  if (config.version === 1) {
@@ -1284,6 +1254,8 @@ async function getPromptContext(config, agent, sessionId, sourceEventId, prompt,
1284
1254
  const response = await fetchImplementation(contextDeliveriesUrl(config.apiUrl), {
1285
1255
  method: "POST",
1286
1256
  headers: {
1257
+ "x-lore-context": "related-work-v1",
1258
+ "x-lore-skills": "skills-v1",
1287
1259
  accept: runtimeAccept(config),
1288
1260
  authorization: `Bearer ${config.token}`,
1289
1261
  "content-type": "application/json",
@@ -1414,6 +1386,7 @@ async function getCachedPromptContext(config, prompt, gitContext, store, now, re
1414
1386
  }
1415
1387
  return {
1416
1388
  context: retained.includes(String(selected.payload.receiptId)) ? "" : selected.context,
1389
+ skillContext: "Lore is using saved learning context. Enabled skills could not be checked and saved skill instructions have not been reapplied. Reconnect to Lore before relying on skills for this task.",
1417
1390
  learned: [],
1418
1391
  delivered: [],
1419
1392
  reliability: {
@@ -1501,6 +1474,35 @@ async function retrievalNotice(delivery, sessionId, store, now) {
1501
1474
  function queueDirectory(home) {
1502
1475
  return resolve(loreDirectory(home), "queue");
1503
1476
  }
1477
+ async function stableCapture(store, queued) {
1478
+ // Hook retries reconstruct timestamps, diffs, and lineage. Freeze the first
1479
+ // request so the same source event always replays identical capture bytes,
1480
+ // including after its outbox acknowledgement or a process restart. Retain
1481
+ // just the latest request per session/kind, not an unbounded event journal.
1482
+ const sourceEventId = queued.request.eventId;
1483
+ const key = `native-capture:${queued.kind}:${queued.request.agent}:${sha256(queued.request.sessionId)}`;
1484
+ const pending = (await store.listOutbox()).find(entry => entry.idempotencyKey === sourceEventId);
1485
+ const original = pending ? queuedRequest(pending.payload) : null;
1486
+ const state = await store.updateState(key, current => {
1487
+ const previous = isObject(current) && current.sourceEventId === sourceEventId ? queuedRequest(current.queued) : original;
1488
+ if (previous && previous.kind === queued.kind) {
1489
+ if (previous.request.idempotencyKey !== queued.request.idempotencyKey) {
1490
+ throw new ReliabilityStoreError("IDEMPOTENCY_CONFLICT", "A captured source event changed; its original recording was retained");
1491
+ }
1492
+ return { sourceEventId, queued: previous };
1493
+ }
1494
+ // Hosts without prompt IDs can legitimately say "continue" again after a
1495
+ // different prompt. Their content hash is only useful for consecutive retry
1496
+ // detection; it must not be a session-wide event identity.
1497
+ const request = queued.kind === "prompt" && queued.request.promptId === undefined
1498
+ ? { ...queued.request, eventId: randomUUID() } : queued.request;
1499
+ return { sourceEventId, queued: { ...queued, request } };
1500
+ });
1501
+ const saved = isObject(state) ? queuedRequest(state.queued) : null;
1502
+ if (saved === null || saved.kind !== queued.kind)
1503
+ throw new Error("Saved capture request is invalid");
1504
+ return saved;
1505
+ }
1504
1506
  async function enqueueCapture(store, queued) {
1505
1507
  return (await store.enqueue({
1506
1508
  kind: queued.kind,
@@ -1904,6 +1906,7 @@ async function offlineGuard(config, store, request, now, previouslyEnforced, all
1904
1906
  ...(typeof request.repo === "string" ? { repo: request.repo } : {}),
1905
1907
  ...(typeof request.path === "string" ? { path: request.path } : {}),
1906
1908
  ...(typeof request.command === "string" ? { command: request.command } : {}),
1909
+ ...(Array.isArray(request.defaultPushBranches) ? { defaultPushBranches: request.defaultPushBranches.filter((branch) => typeof branch === "string") } : {}),
1907
1910
  ...(Array.isArray(request.files) ? { files: request.files.filter((file) => typeof file === "string") } : {}),
1908
1911
  }) !== null) : [];
1909
1912
  return {
@@ -1976,6 +1979,12 @@ async function handleGuardEvent(input, agent, config, sessionId, options, now) {
1976
1979
  const startedAt = Date.now();
1977
1980
  let result;
1978
1981
  const guardRequest = {
1982
+ ...await (async () => {
1983
+ const args = isObject(input.tool_input) ? input.tool_input : {};
1984
+ const changesContext = ["cwd", "workdir", "working_directory", "env", "environment"].some(key => args[key] !== undefined);
1985
+ const defaultPushBranches = changesContext ? undefined : await defaultGitPushBranches(trigger.command, cwd);
1986
+ return defaultPushBranches ? { defaultPushBranches } : {};
1987
+ })(),
1979
1988
  connector: "lore-cli",
1980
1989
  agent,
1981
1990
  sessionId,
@@ -2103,6 +2112,9 @@ export async function handleHookEvent(value, agent, options = {}) {
2103
2112
  const access = await checkLoreAccess(stringField(input.cwd), options.home, config, options.fetch ?? globalThis.fetch);
2104
2113
  if (!access.allowed) {
2105
2114
  await clearPending(agent, sessionId, options.home, config.connectionId);
2115
+ await runtimeStore(config, options.home).then(store => clearRetrievalTask(store, {
2116
+ agent, sessionId, connectionKey: credentialReliabilityWorkspaceKey(config),
2117
+ })).catch(() => undefined);
2106
2118
  // A policy outage must not silently bypass an already enforced Guard.
2107
2119
  if (eventName === "PreToolUse" && access.reason === "Workspace repository settings are unavailable") {
2108
2120
  const prior = await readGuardState(agent, sessionId, options.home, config.connectionId).catch(() => null);
@@ -2239,8 +2251,10 @@ async function cursorSession(sessionId, options) {
2239
2251
  throw new Error("Start a new Cursor conversation to register this Lore session.");
2240
2252
  }
2241
2253
  const access = await checkLoreAccess(stringField(state.cwd), options.home, config, options.fetch ?? globalThis.fetch);
2242
- if (!access.allowed)
2254
+ if (!access.allowed) {
2255
+ await clearRetrievalTask(store, { agent: "cursor", sessionId, connectionKey: credentialReliabilityWorkspaceKey(config) }).catch(() => undefined);
2243
2256
  throw new Error(`Lore is off: ${access.reason}.`);
2257
+ }
2244
2258
  return { config, store, state, cwd: stringField(state.cwd) };
2245
2259
  }
2246
2260
  export async function getCursorContext(sessionId, prompt, options = {}) {
@@ -2292,11 +2306,17 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2292
2306
  notices.push("Lore retained a capture locally, but upload is blocked by authentication. Run lore connect again.");
2293
2307
  }
2294
2308
  else if (result?.state === "dead") {
2295
- notices.push("Lore retained a capture as a dead letter because the server response was incompatible. Run lore doctor.");
2309
+ notices.push("Lore retained a rejected or incompatible capture locally for diagnosis. Run lore doctor.");
2296
2310
  }
2297
2311
  };
2312
+ const terminal = (result, eventId) => result?.idempotencyKey === eventId && (result.state === "dead" || result.state === "auth-blocked");
2298
2313
  try {
2299
- noticeForFlush(await flushOne(config, fetchImplementation, store));
2314
+ const flushed = await flushOne(config, fetchImplementation, store);
2315
+ noticeForFlush(flushed);
2316
+ // A retained terminal failure still occupies capacity. Give the next item
2317
+ // one upload attempt before enqueueing, including when the queue was full.
2318
+ if (flushed?.state === "dead")
2319
+ noticeForFlush(await flushOne(config, fetchImplementation, store));
2300
2320
  }
2301
2321
  catch {
2302
2322
  notices.push("Lore retained queued captures locally, but replay could not run. Run lore doctor.");
@@ -2327,18 +2347,30 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2327
2347
  };
2328
2348
  const lineage = await readLineageMetadata(options.home, options.environment ?? process.env);
2329
2349
  let delivery = emptyDelivery();
2350
+ const retrievalTask = (repo) => resolveRetrievalTask(store, {
2351
+ agent, sessionId, connectionKey: credentialReliabilityWorkspaceKey(config),
2352
+ cwd: stringField(input.cwd), repo,
2353
+ }, prompt, now, pending?.cwd === stringField(input.cwd) && pending
2354
+ ? { content: pending.assistantMessage, capturedAt: pending.capturedAt } : undefined);
2330
2355
  if (pending !== null) {
2331
2356
  let receivedTurnContext = false;
2332
- const request = await createTurnRequest(input, agent, pending, now, lineage);
2357
+ let request = await createTurnRequest(input, agent, pending, now, lineage);
2333
2358
  if (request === null) {
2334
2359
  return undefined;
2335
2360
  }
2361
+ const task = await retrievalTask(request.scope?.repo);
2362
+ if (task !== request.currentUser.content.trim())
2363
+ request.task = task;
2336
2364
  if (retained.length)
2337
2365
  request.retainedReceiptIds = retained;
2338
2366
  let enqueued = false;
2339
2367
  try {
2340
- await enqueueCapture(store, { kind: "turn", request });
2341
- enqueued = true;
2368
+ request = (await stableCapture(store, { kind: "turn", request })).request;
2369
+ const saved = await enqueueCapture(store, { kind: "turn", request });
2370
+ enqueued = saved.state === "ready" || saved.state === "in-flight";
2371
+ if (saved.state === "dead" || saved.state === "auth-blocked") {
2372
+ noticeForFlush({ idempotencyKey: saved.idempotencyKey, state: saved.state });
2373
+ }
2342
2374
  await rememberImages(request.eventId).catch(() => undefined);
2343
2375
  await clearPending(agent, sessionId, options.home, config.connectionId);
2344
2376
  }
@@ -2360,7 +2392,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2360
2392
  receivedTurnContext = delivery.reliability?.status !== "failed" &&
2361
2393
  delivery.reliability?.source !== "none";
2362
2394
  }
2363
- else {
2395
+ else if (!terminal(flushed, request.eventId)) {
2364
2396
  notices.push("Lore saved this capture locally; server upload is pending.");
2365
2397
  }
2366
2398
  }
@@ -2370,7 +2402,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2370
2402
  }
2371
2403
  if (retrieve && !receivedTurnContext) {
2372
2404
  try {
2373
- delivery = await getPromptContextWithFallback(config, agent, sessionId, request.eventId, prompt, {
2405
+ delivery = await getPromptContextWithFallback(config, agent, sessionId, request.eventId, task, {
2374
2406
  ...(request.scope === undefined ? {} : { scope: request.scope }),
2375
2407
  learningScope: request.learningScope,
2376
2408
  ...(request.diff === undefined ? {} : { diff: request.diff }),
@@ -2399,15 +2431,20 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2399
2431
  }
2400
2432
  else {
2401
2433
  const gitContext = await collectGitContext(stringField(input.cwd));
2402
- const observation = createPromptObservationRequest(input, agent, sessionId, now, gitContext, lineage);
2434
+ const task = await retrievalTask(gitContext.scope?.repo);
2435
+ let observation = createPromptObservationRequest(input, agent, sessionId, now, gitContext, lineage);
2403
2436
  if (observation === null) {
2404
2437
  return undefined;
2405
2438
  }
2406
2439
  let enqueued = false;
2407
2440
  try {
2408
2441
  if (capture) {
2409
- await enqueueCapture(store, { kind: "prompt", request: observation });
2410
- enqueued = true;
2442
+ observation = (await stableCapture(store, { kind: "prompt", request: observation })).request;
2443
+ const saved = await enqueueCapture(store, { kind: "prompt", request: observation });
2444
+ enqueued = saved.state === "ready" || saved.state === "in-flight";
2445
+ if (saved.state === "dead" || saved.state === "auth-blocked") {
2446
+ noticeForFlush({ idempotencyKey: saved.idempotencyKey, state: saved.state });
2447
+ }
2411
2448
  await rememberImages(observation.eventId).catch(() => undefined);
2412
2449
  }
2413
2450
  }
@@ -2421,8 +2458,8 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2421
2458
  try {
2422
2459
  const flushed = await flushOne(config, fetchImplementation, store);
2423
2460
  noticeForFlush(flushed);
2424
- if (flushed?.idempotencyKey !== observation.eventId ||
2425
- flushed.state !== "acknowledged") {
2461
+ if (!terminal(flushed, observation.eventId) &&
2462
+ (flushed?.idempotencyKey !== observation.eventId || flushed.state !== "acknowledged")) {
2426
2463
  notices.push("Lore saved this capture locally; server upload is pending.");
2427
2464
  }
2428
2465
  }
@@ -2432,7 +2469,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2432
2469
  }
2433
2470
  if (retrieve) {
2434
2471
  try {
2435
- delivery = await getPromptContextWithFallback(config, agent, sessionId, observation.eventId, prompt, gitContext, fetchImplementation, store, now, retained);
2472
+ delivery = await getPromptContextWithFallback(config, agent, sessionId, observation.eventId, task, gitContext, fetchImplementation, store, now, retained);
2436
2473
  }
2437
2474
  catch {
2438
2475
  delivery = {
@@ -2480,7 +2517,10 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2480
2517
  const receipt = receiptMessage(config, agent, delivery);
2481
2518
  if (retrieve && delivery.completeContext)
2482
2519
  await rememberDeliveredContext(store, contextSession, delivery).catch(() => undefined);
2483
- const taskContext = [delivery.context, delivery.reliability?.status === "failed" ? undefined : approachGuidance(prompt, agent, redactSecrets(sessionId), retainedContext)].filter(Boolean).join("\n\n");
2520
+ const relatedContext = delivery.relatedContext && !retainedContext.some(text => text.includes(delivery.relatedContext))
2521
+ ? delivery.relatedContext : undefined;
2522
+ // Skills are fresh on every turn, even when learning context is retained.
2523
+ const taskContext = [delivery.skillContext, delivery.context, relatedContext, delivery.reliability?.status === "failed" ? undefined : approachGuidance(prompt, agent, redactSecrets(sessionId), retainedContext), delivery.skillContext === undefined && delivery.reliability?.status !== "failed" ? skillGuidance(retainedContext) : undefined].filter(Boolean).join("\n\n");
2484
2524
  const systemMessage = agent === "cursor" || agent === "polytoken"
2485
2525
  ? undefined
2486
2526
  : [receipt, reliabilityNotice].filter(Boolean).join(" · ") || undefined;