hippo-memory 1.61.0 → 1.63.0
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/README.md +37 -53
- package/dist/agent-memories/apply.d.ts +3 -1
- package/dist/agent-memories/apply.js +23 -1
- package/dist/agent-memories/claude-code.d.ts +4 -1
- package/dist/agent-memories/claude-code.js +53 -9
- package/dist/agent-memories/report.d.ts +1 -0
- package/dist/agent-memories/report.js +2 -2
- package/dist/agent-memories/sync.d.ts +3 -3
- package/dist/agent-memories/sync.js +46 -24
- package/dist/agent-memories/types.d.ts +0 -2
- package/dist/ambient-store.d.ts +4 -4
- package/dist/ambient-store.js +4 -3
- package/dist/api/assemble.d.ts +7 -10
- package/dist/api/assemble.js +62 -66
- package/dist/api/audit.d.ts +2 -2
- package/dist/api/audit.js +2 -2
- package/dist/api/auth.d.ts +6 -6
- package/dist/api/auth.js +5 -7
- package/dist/api/context-select.d.ts +50 -0
- package/dist/api/context-select.js +342 -0
- package/dist/api/context-types.d.ts +12 -17
- package/dist/api/context.d.ts +5 -4
- package/dist/api/context.js +208 -535
- package/dist/api/dormant.js +1 -1
- package/dist/api/drill-down.d.ts +4 -4
- package/dist/api/drill-down.js +56 -41
- package/dist/api/outcome.d.ts +8 -13
- package/dist/api/outcome.js +13 -17
- package/dist/api/promote.d.ts +5 -8
- package/dist/api/promote.js +55 -66
- package/dist/api/quarantine.js +3 -2
- package/dist/api/recall-types.d.ts +43 -55
- package/dist/api/recall.d.ts +3 -3
- package/dist/api/recall.js +310 -456
- package/dist/api/remember.d.ts +2 -2
- package/dist/api/sleep.d.ts +7 -35
- package/dist/api/sleep.js +206 -220
- package/dist/api/tokens.d.ts +2 -2
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +6 -10
- package/dist/api/types.js +2 -4
- package/dist/audit-prune.d.ts +4 -6
- package/dist/audit-prune.js +3 -5
- package/dist/audit.js +11 -33
- package/dist/auth.d.ts +8 -9
- package/dist/auth.js +5 -7
- package/dist/autolearn.d.ts +1 -1
- package/dist/autolearn.js +1 -1
- package/dist/availability.js +3 -5
- package/dist/capture/command.d.ts +5 -4
- package/dist/capture/command.js +8 -22
- package/dist/capture/compact.d.ts +2 -2
- package/dist/capture/compact.js +11 -15
- package/dist/capture/extract.js +37 -115
- package/dist/capture-error.d.ts +1 -1
- package/dist/capture-error.js +1 -1
- package/dist/churn-git.d.ts +1 -1
- package/dist/churn-git.js +1 -1
- package/dist/cli/audit.js +3 -4
- package/dist/cli/auth.js +3 -6
- package/dist/cli/briefs.js +324 -306
- package/dist/cli/context.js +44 -34
- package/dist/cli/continuity.js +283 -271
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +43 -58
- package/dist/cli/dag.js +5 -9
- package/dist/cli/decisions.js +334 -345
- package/dist/cli/explain.js +68 -61
- package/dist/cli/goals.js +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/maintenance.js +62 -51
- package/dist/cli/playbooks.js +391 -379
- package/dist/cli/projects.js +11 -6
- package/dist/cli/recall.js +30 -44
- package/dist/cli/remember.js +118 -87
- package/dist/cli/session-hooks.js +106 -115
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +267 -250
- package/dist/cli/shared.js +3 -3
- package/dist/cli/slack.js +1 -1
- package/dist/cli/sleep.js +27 -1
- package/dist/cli/status.d.ts +4 -4
- package/dist/cli/status.js +80 -76
- package/dist/cli/transfer.js +88 -107
- package/dist/cli/usage.js +9 -6
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -9
- package/dist/compaction-record.d.ts +2 -2
- package/dist/compaction-record.js +89 -68
- package/dist/compare.d.ts +11 -16
- package/dist/compare.js +11 -16
- package/dist/config.d.ts +19 -18
- package/dist/config.js +90 -67
- package/dist/connectors/github/backfill.d.ts +2 -2
- package/dist/connectors/github/backfill.js +8 -15
- package/dist/connectors/github/cli-impl.js +3 -8
- package/dist/connectors/github/deletion.d.ts +5 -12
- package/dist/connectors/github/deletion.js +5 -12
- package/dist/connectors/github/dlq.d.ts +6 -9
- package/dist/connectors/github/dlq.js +2 -3
- package/dist/connectors/github/ingest.d.ts +5 -7
- package/dist/connectors/github/ingest.js +8 -12
- package/dist/connectors/github/octokit-client.d.ts +3 -5
- package/dist/connectors/github/octokit-client.js +5 -6
- package/dist/connectors/github/signature.d.ts +9 -39
- package/dist/connectors/github/signature.js +9 -39
- package/dist/connectors/github/tenant-routing.d.ts +1 -1
- package/dist/connectors/github/tenant-routing.js +1 -1
- package/dist/connectors/github/transform.js +2 -2
- package/dist/connectors/github/types.d.ts +2 -10
- package/dist/connectors/github/types.js +1 -3
- package/dist/connectors/slack/deletion.d.ts +3 -8
- package/dist/connectors/slack/deletion.js +3 -8
- package/dist/connectors/slack/dlq.d.ts +1 -1
- package/dist/connectors/slack/ingest.d.ts +1 -1
- package/dist/connectors/slack/ingest.js +7 -16
- package/dist/connectors/slack/signature.d.ts +1 -1
- package/dist/connectors/slack/tenant-routing.d.ts +3 -5
- package/dist/connectors/slack/tenant-routing.js +3 -5
- package/dist/connectors/slack/transform.d.ts +5 -6
- package/dist/connectors/slack/transform.js +5 -6
- package/dist/connectors/slack/types.d.ts +2 -6
- package/dist/connectors/slack/types.js +1 -3
- package/dist/connectors/slack/web-client.js +10 -3
- package/dist/connectors/slack/workspaces.d.ts +3 -5
- package/dist/connectors/slack/workspaces.js +3 -5
- package/dist/consolidate/conflicts.js +3 -14
- package/dist/consolidate/decay.js +9 -29
- package/dist/consolidate/llm-passes.js +4 -5
- package/dist/consolidate/merge.js +8 -23
- package/dist/consolidate/run.d.ts +1 -8
- package/dist/consolidate/run.js +3 -25
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/traces.js +9 -21
- package/dist/customer-notes.d.ts +5 -7
- package/dist/customer-notes.js +82 -76
- package/dist/dag.d.ts +10 -21
- package/dist/dag.js +189 -203
- package/dist/db/continuity.js +2 -2
- package/dist/db/migrations/v14.js +1 -1
- package/dist/db/migrations/v15.js +1 -2
- package/dist/db/migrations/v16.js +3 -4
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +1 -1
- package/dist/db/migrations/v20.js +1 -1
- package/dist/db/migrations/v21.js +2 -6
- package/dist/db/migrations/v22.js +2 -4
- package/dist/db/migrations/v23.js +1 -1
- package/dist/db/migrations/v24.js +4 -6
- package/dist/db/migrations/v25.js +2 -3
- package/dist/db/migrations/v26.js +3 -3
- package/dist/db/migrations/v27.js +2 -10
- package/dist/db/migrations/v28.js +5 -8
- package/dist/db/migrations/v29.js +3 -4
- package/dist/db/migrations/v30.js +2 -2
- package/dist/db/migrations/v31.js +1 -1
- package/dist/db/migrations/v32.js +1 -1
- package/dist/db/migrations/v33.js +3 -3
- package/dist/db/migrations/v34.js +1 -1
- package/dist/db/migrations/v35.js +3 -4
- package/dist/db/migrations/v36.js +3 -4
- package/dist/db/migrations/v37.js +5 -5
- package/dist/db/migrations/v38.js +7 -8
- package/dist/db/migrations/v39.js +1 -1
- package/dist/db/migrations/v40.js +4 -16
- package/dist/db/migrations/v41.js +3 -4
- package/dist/db/migrations/v42.js +3 -4
- package/dist/db/migrations/v45.js +1 -1
- package/dist/db/migrations/v46.js +1 -1
- package/dist/db/migrations/v47.js +1 -1
- package/dist/db/migrations/v48.js +1 -1
- package/dist/decisions.d.ts +2 -2
- package/dist/decisions.js +97 -80
- package/dist/dedupe.js +86 -61
- package/dist/delivery-recorder.js +154 -135
- package/dist/doctor.js +129 -110
- package/dist/dormant.js +1 -4
- package/dist/embedding-provider.d.ts +4 -8
- package/dist/embedding-provider.js +4 -8
- package/dist/embeddings.js +55 -47
- package/dist/env.d.ts +1 -1
- package/dist/env.js +12 -12
- package/dist/escape.d.ts +5 -0
- package/dist/escape.js +10 -0
- package/dist/eval-stats.d.ts +1 -2
- package/dist/eval-stats.js +1 -2
- package/dist/eval-suite.js +27 -21
- package/dist/extract.js +4 -9
- package/dist/failure-log.d.ts +3 -3
- package/dist/failure-log.js +1 -1
- package/dist/forward-claim-detector.d.ts +2 -4
- package/dist/forward-claim-detector.js +6 -11
- package/dist/goals.d.ts +3 -3
- package/dist/goals.js +103 -91
- package/dist/graph/read.d.ts +2 -2
- package/dist/graph/read.js +5 -6
- package/dist/graph/types.d.ts +8 -8
- package/dist/graph/write.d.ts +7 -14
- package/dist/graph/write.js +16 -23
- package/dist/graph-extract.d.ts +7 -8
- package/dist/graph-extract.js +62 -72
- package/dist/graph-recall.d.ts +2 -2
- package/dist/graph-recall.js +55 -49
- package/dist/graph-stream.d.ts +5 -6
- package/dist/graph-stream.js +66 -57
- package/dist/graph-view.d.ts +2 -2
- package/dist/graph-view.js +7 -7
- package/dist/half-life-migration.d.ts +1 -2
- package/dist/half-life-migration.js +2 -3
- package/dist/hooks/codex-session.js +1 -1
- package/dist/hooks/codex-wrapper.d.ts +1 -1
- package/dist/hooks/codex-wrapper.js +3 -2
- package/dist/hooks/json-hooks.d.ts +2 -2
- package/dist/hooks/json-hooks.js +5 -4
- package/dist/hooks/opencode.d.ts +1 -1
- package/dist/hooks/opencode.js +5 -4
- package/dist/hooks/shared.d.ts +3 -7
- package/dist/hooks/shared.js +1 -8
- package/dist/http-util.d.ts +2 -3
- package/dist/http-util.js +3 -0
- package/dist/importers/core.d.ts +2 -9
- package/dist/importers/core.js +15 -30
- package/dist/importers/sources.js +2 -1
- package/dist/importers/vault.js +2 -20
- package/dist/incidents.d.ts +1 -1
- package/dist/incidents.js +46 -39
- package/dist/instruction-detect.d.ts +1 -1
- package/dist/instruction-detect.js +1 -1
- package/dist/invalidation.d.ts +3 -0
- package/dist/invalidation.js +160 -114
- package/dist/json.d.ts +5 -0
- package/dist/json.js +4 -0
- package/dist/judgment.js +1 -2
- package/dist/local-embedding.js +1 -1
- package/dist/mcp/admin-tools.js +7 -17
- package/dist/mcp/format.js +1 -1
- package/dist/mcp/framing.js +3 -6
- package/dist/mcp/protocol.d.ts +2 -5
- package/dist/mcp/protocol.js +1 -3
- package/dist/mcp/recall-tools.js +12 -15
- package/dist/mcp/request.js +4 -3
- package/dist/mcp/session-state.js +2 -3
- package/dist/mcp/stdio.js +2 -1
- package/dist/mcp/tools.js +9 -6
- package/dist/memory-value-weights.d.ts +5 -8
- package/dist/memory-value-weights.js +5 -8
- package/dist/memory-value.d.ts +13 -13
- package/dist/memory-value.js +26 -37
- package/dist/memory.d.ts +20 -22
- package/dist/memory.js +24 -48
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +3 -2
- package/dist/owner-validation.d.ts +4 -5
- package/dist/owner-validation.js +4 -5
- package/dist/physics.d.ts +4 -4
- package/dist/physics.js +7 -9
- package/dist/policies.d.ts +9 -10
- package/dist/policies.js +96 -81
- package/dist/postinstall.js +3 -6
- package/dist/predictions/planning-fallacy.d.ts +9 -14
- package/dist/predictions/planning-fallacy.js +10 -16
- package/dist/predictions/store.d.ts +15 -23
- package/dist/predictions/store.js +36 -33
- package/dist/processes.d.ts +2 -7
- package/dist/processes.js +88 -72
- package/dist/project-briefs.d.ts +2 -3
- package/dist/project-briefs.js +141 -118
- package/dist/project-identity.d.ts +22 -9
- package/dist/project-identity.js +47 -12
- package/dist/project-merge.d.ts +28 -5
- package/dist/project-merge.js +213 -46
- package/dist/project-remote.d.ts +12 -0
- package/dist/project-remote.js +138 -0
- package/dist/prompt-recall.js +1 -2
- package/dist/rate-limit.d.ts +1 -1
- package/dist/rate-limit.js +1 -1
- package/dist/raw-archive.d.ts +9 -0
- package/dist/raw-archive.js +70 -53
- package/dist/recall-history.d.ts +19 -20
- package/dist/recall-history.js +24 -42
- package/dist/recall-pipeline.js +4 -28
- package/dist/recall-scope.d.ts +7 -8
- package/dist/recall-scope.js +7 -8
- package/dist/recall-trace.d.ts +5 -9
- package/dist/recall-trace.js +6 -10
- package/dist/refine-llm.d.ts +1 -1
- package/dist/refine-llm.js +2 -2
- package/dist/reject-flow.d.ts +3 -4
- package/dist/reject-flow.js +122 -117
- package/dist/rejection.d.ts +5 -6
- package/dist/rejection.js +7 -15
- package/dist/rerankers/clef.d.ts +1 -1
- package/dist/rerankers/jev.d.ts +1 -2
- package/dist/rerankers/jev.js +4 -5
- package/dist/rerankers/llm.d.ts +1 -2
- package/dist/rerankers/llm.js +1 -2
- package/dist/rerankers/types.d.ts +1 -2
- package/dist/rrf.d.ts +2 -2
- package/dist/rrf.js +2 -2
- package/dist/search/bm25-search.d.ts +1 -1
- package/dist/search/bm25-search.js +2 -1
- package/dist/search/boosts.js +2 -1
- package/dist/search/hybrid.d.ts +1 -1
- package/dist/search/hybrid.js +2 -1
- package/dist/search/physics-search.d.ts +1 -1
- package/dist/search/physics-search.js +2 -1
- package/dist/search/types.d.ts +2 -0
- package/dist/search/types.js +3 -1
- package/dist/secret-detect.d.ts +4 -5
- package/dist/secret-detect.js +6 -10
- package/dist/server/auth.js +5 -5
- package/dist/server/client-ip.js +1 -1
- package/dist/server/cursor.js +2 -1
- package/dist/server/mcp-http.js +4 -4
- package/dist/server/request.d.ts +3 -6
- package/dist/server/request.js +6 -7
- package/dist/server/routes/admin.js +5 -4
- package/dist/server/routes/customer-notes.js +6 -5
- package/dist/server/routes/decisions.js +4 -3
- package/dist/server/routes/incidents.js +7 -5
- package/dist/server/routes/memories.js +7 -7
- package/dist/server/routes/policies.js +3 -2
- package/dist/server/routes/predictions.js +12 -15
- package/dist/server/routes/processes.js +3 -2
- package/dist/server/routes/project-briefs.js +8 -7
- package/dist/server/routes/recall.js +95 -93
- package/dist/server/routes/skills.js +6 -5
- package/dist/server/types.d.ts +1 -1
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +7 -14
- package/dist/server-detect.js +72 -58
- package/dist/server.d.ts +2 -2
- package/dist/server.js +131 -117
- package/dist/shared.d.ts +26 -17
- package/dist/shared.js +102 -104
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js +88 -72
- package/dist/store/audit-event.d.ts +2 -2
- package/dist/store/audit-event.js +1 -1
- package/dist/store/candidates.d.ts +2 -2
- package/dist/store/candidates.js +4 -3
- package/dist/store/conflicts.js +30 -22
- package/dist/store/delete-and-batch.d.ts +11 -14
- package/dist/store/delete-and-batch.js +40 -91
- package/dist/store/entry-reads.d.ts +17 -25
- package/dist/store/entry-reads.js +59 -40
- package/dist/store/entry-row.d.ts +6 -24
- package/dist/store/entry-row.js +6 -24
- package/dist/store/entry-writes.d.ts +6 -7
- package/dist/store/entry-writes.js +13 -11
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +7 -10
- package/dist/store/index-and-stats.d.ts +2 -6
- package/dist/store/index-and-stats.js +4 -10
- package/dist/store/mirrors.d.ts +6 -19
- package/dist/store/mirrors.js +14 -39
- package/dist/store/open.js +9 -31
- package/dist/store/rows.d.ts +5 -11
- package/dist/store/rows.js +6 -11
- package/dist/store/search-rows.d.ts +17 -34
- package/dist/store/search-rows.js +34 -56
- package/dist/store/sessions.d.ts +4 -5
- package/dist/store/sessions.js +5 -6
- package/dist/store/summaries.d.ts +13 -17
- package/dist/store/summaries.js +26 -70
- package/dist/support-bundle.js +4 -8
- package/dist/tenant.d.ts +1 -5
- package/dist/token-ledger.d.ts +1 -1
- package/dist/token-ledger.js +3 -5
- package/dist/trace.js +1 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/working-memory.d.ts +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/capture/extract.js
CHANGED
|
@@ -12,24 +12,13 @@ import { duplicateKey } from '../same-text.js';
|
|
|
12
12
|
import { isContentWorthStoring } from '../audit.js';
|
|
13
13
|
// Sentence-level patterns
|
|
14
14
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// `
|
|
21
|
-
//
|
|
22
|
-
// group 2's own reach is widened to {1,500} because the true stopping point
|
|
23
|
-
// is now found by content, not counted characters. Keeping the keyword in
|
|
24
|
-
// its own group (rather than folding it into one bigger capture) matters:
|
|
25
|
-
// `boundToClause` must scan for a clause boundary only in group 2, never in
|
|
26
|
-
// group 1 — several keywords end in their own colon ("error:", "rule:",
|
|
27
|
-
// "decision:") which is not a clause boundary in the prose sense and would
|
|
28
|
-
// wrongly truncate the capture down to just the keyword if scanned.
|
|
29
|
-
// `PREFERENCE_PATTERNS[0]` is the one exception — its two-capture-group
|
|
30
|
-
// shape means something different (two content spans either side of
|
|
31
|
-
// "instead of"/"over"/"not") and is a separate, backlogged defect (see
|
|
32
|
-
// docs/plans/2026-08-23-df2-capture-anchoring.md); left as-is.
|
|
15
|
+
// Each pattern carries TWO capture groups: group 1 is the discriminating keyword (plus its
|
|
16
|
+
// trailing separator, verbatim), group 2 the content after it, so a negation like "never" survives
|
|
17
|
+
// ("Never use X" must not store as "use X"). `extractFromPatterns` joins group1 + a clause-bounded
|
|
18
|
+
// group2 (`boundToClause`), so group 2 may reach {1,500}. The keyword keeps its own group because
|
|
19
|
+
// keywords like "error:" end in a colon that is not a prose clause boundary.
|
|
20
|
+
// `PREFERENCE_PATTERNS[0]` is the exception: its two groups are the content spans either side of
|
|
21
|
+
// "instead of"/"over"/"not"; left as-is.
|
|
33
22
|
const DECISION_PATTERNS = [
|
|
34
23
|
/(?:we(?:'ve| have)?|i(?:'ve| have)?|let's)\s+(decid(?:ed|e)\s+(?:to\s+)?)(.{1,500})/i,
|
|
35
24
|
/(?:let's|we(?:'ll| will| should)?)\s+((?:go with|do|use|try|build|implement|switch to)\s+)(.{1,500})/i,
|
|
@@ -49,9 +38,8 @@ const ERROR_PATTERNS = [
|
|
|
49
38
|
/((?:the (?:issue|problem|fix) (?:is|was))\s+)(.{1,500})/i,
|
|
50
39
|
/((?:don't forget|easy to miss):\s*)(.{1,500})/i,
|
|
51
40
|
];
|
|
52
|
-
// PREFERENCE_PATTERNS[0] keeps its
|
|
53
|
-
//
|
|
54
|
-
// extractFromPatterns' reference check against this exact array element.
|
|
41
|
+
// PREFERENCE_PATTERNS[0] keeps its match[1]-only, unbounded shape; extractFromPatterns
|
|
42
|
+
// checks for this exact array element.
|
|
55
43
|
const PREFERENCE_PATTERNS = [
|
|
56
44
|
/(?:prefer|use)\s+(.{5,100})\s+(?:instead of|over|not)\s+(.{3,100})/i,
|
|
57
45
|
/((?:don't use|avoid|skip)\s+)(.{1,500})/i,
|
|
@@ -72,52 +60,20 @@ export function splitSentences(text) {
|
|
|
72
60
|
.map((s) => s.trim())
|
|
73
61
|
.filter((s) => s.length > 5);
|
|
74
62
|
}
|
|
75
|
-
/**
|
|
76
|
-
* T2 (DF2): bound a keyword+content capture to its clause instead of a fixed
|
|
77
|
-
* character count. `full` is `keywordPrefix + content` (already concatenated
|
|
78
|
-
* so the 200-char ceiling below applies to the whole stored string, not just
|
|
79
|
-
* the part after the keyword); `searchFrom` is `keywordPrefix.length`, so the
|
|
80
|
-
* clause/terminator scan only ever looks INSIDE `content` — several keywords
|
|
81
|
-
* end in their own colon ("error:", "rule:", "decision:") which must never
|
|
82
|
-
* be mistaken for a clause boundary in the prose that follows.
|
|
83
|
-
*
|
|
84
|
-
* Stops at the first `,`/`;`/`:` followed by whitespace, or at a sentence
|
|
85
|
-
* terminator `[.!?]` followed by whitespace or end-of-string — whichever
|
|
86
|
-
* comes first — and never past `maxLen` chars total.
|
|
87
|
-
*
|
|
88
|
-
* The whitespace requirement on the terminator is load-bearing: a bare
|
|
89
|
-
* `[.!?]` would split inside a token like `.env` / `capture.ts` / `v1.35.0`,
|
|
90
|
-
* turning a full clause into a fragment that then fails the write gate and
|
|
91
|
-
* is silently dropped (measured in the plan). The `maxLen` ceiling is also
|
|
92
|
-
* load-bearing: without it, a clause-free span can run past the 500-char
|
|
93
|
-
* gate in `extractFromPatterns` and the whole match is dropped, where today
|
|
94
|
-
* it is truncated and stored.
|
|
95
|
-
*/
|
|
96
|
-
/**
|
|
97
|
-
* Does a plausible CLOSING single quote appear after `from`? Mirror of the
|
|
98
|
-
* opener rule in `boundToClause`: a closer sits tight against the literal it
|
|
99
|
-
* ends (non-whitespace before) and is followed by whitespace, punctuation, or
|
|
100
|
-
* end-of-string - never by a letter, which is what makes "user's" an
|
|
101
|
-
* apostrophe rather than a partner.
|
|
102
|
-
*/
|
|
103
63
|
function isLetterOrDigit(ch) {
|
|
104
64
|
return ch !== undefined && /[\p{L}\p{N}]/u.test(ch);
|
|
105
65
|
}
|
|
66
|
+
/** The last plausible CLOSING single quote, or -1. Mirror of the opener rule in `boundToClause`: a closer sits tight
|
|
67
|
+
* against its literal and is never followed by a letter, which is what makes "user's" an apostrophe. */
|
|
106
68
|
function lastCloserIndex(full) {
|
|
107
|
-
// ONE pass, not one per apostrophe
|
|
108
|
-
//
|
|
109
|
-
// elisions ("keep 'em", "wait 'til", ...) made extraction quadratic and
|
|
110
|
-
// could stall a moderately sized capture. Codex P2, r7.
|
|
69
|
+
// ONE pass, not one per apostrophe: a rescan per apostrophe goes quadratic
|
|
70
|
+
// on a transcript full of elisions ("keep 'em", "wait 'til", ...).
|
|
111
71
|
//
|
|
112
|
-
// A quote CLOSES THE SIDE IT IS TIGHT AGAINST
|
|
113
|
-
// neighbours
|
|
114
|
-
// same following character and opposite roles -
|
|
72
|
+
// A quote CLOSES THE SIDE IT IS TIGHT AGAINST, so the test needs both
|
|
73
|
+
// neighbours: these two have the same following character and opposite roles -
|
|
115
74
|
// "preserve 'a, b'-style" next '-' -> CLOSER, content on the left
|
|
116
75
|
// "then run '--force," next '-' -> OPENER, content on the right
|
|
117
|
-
// so no forward-only rule can separate them.
|
|
118
|
-
// exactly that and broke in both directions at once (codex P1+P2, r10):
|
|
119
|
-
// it missed closers before token-joining punctuation and accepted
|
|
120
|
-
// "'.env" as a closer because a dot happened to be in its class.
|
|
76
|
+
// so no forward-only rule can separate them.
|
|
121
77
|
//
|
|
122
78
|
// never a closer next is a letter/digit "user's", "keep 'em"
|
|
123
79
|
// closer prev is non-whitespace "'a, b' to", "'a, b'-style"
|
|
@@ -137,11 +93,10 @@ function lastCloserIndex(full) {
|
|
|
137
93
|
// "tight against content" excludes an OPENING delimiter: in
|
|
138
94
|
// "call parse('--force" the paren is non-whitespace but the quote after
|
|
139
95
|
// it is an opener, and treating it as a closer let an earlier elision
|
|
140
|
-
// pair across the clause boundary.
|
|
96
|
+
// pair across the clause boundary.
|
|
141
97
|
const tightBefore = prev !== undefined && !/[\s([{]/.test(prev);
|
|
142
98
|
const endsAfter = next === undefined || /\s/.test(next);
|
|
143
|
-
// Punctuation splits in two
|
|
144
|
-
// revisions kept rediscovering piecemeal:
|
|
99
|
+
// Punctuation splits in two:
|
|
145
100
|
// , ; : ! ? ) ] } never join tokens - they end the literal whatever
|
|
146
101
|
// follows, so "'echo a, b ';then" closes at the ;
|
|
147
102
|
// . - _ / @ # DO join tokens - "'.env" and "'--force" continue a
|
|
@@ -156,17 +111,12 @@ function lastCloserIndex(full) {
|
|
|
156
111
|
}
|
|
157
112
|
return -1;
|
|
158
113
|
}
|
|
114
|
+
/** Cuts `full` (keyword + content) at the first prose `,;:` or `[.!?]` followed by whitespace, scanning from `searchFrom` so a keyword's
|
|
115
|
+
* own colon never counts; the whitespace rule keeps `.env` whole and `maxLen` truncates a long span the 500-char gate would drop. */
|
|
159
116
|
function boundToClause(full, searchFrom, maxLen = 200) {
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
// Depth-awareness is not a nicety here: hippo memories are full of code, and
|
|
163
|
-
// a naive scan reintroduces the exact fragment defect this whole change
|
|
164
|
-
// exists to remove. Measured before this guard existed:
|
|
117
|
+
// Depth-awareness matters because memories are full of code; a naive scan cuts
|
|
165
118
|
// "Always call build(x, y) before deploy." -> "Always call build(x"
|
|
166
|
-
//
|
|
167
|
-
// Both then PASS the write gate, because they contain code punctuation and
|
|
168
|
-
// so read as "specific" — a malformed fragment stored with high confidence.
|
|
169
|
-
// Codex review finding (P1) on this branch.
|
|
119
|
+
// and the fragment PASSES the write gate, since code punctuation reads as "specific".
|
|
170
120
|
//
|
|
171
121
|
// So: a separator only ends the clause at bracket depth zero and outside
|
|
172
122
|
// quotes. Unbalanced closers are tolerated (depth floors at 0) because
|
|
@@ -222,15 +172,8 @@ function boundToClause(full, searchFrom, maxLen = 200) {
|
|
|
222
172
|
return bounded;
|
|
223
173
|
}
|
|
224
174
|
function closesQuote(full, i, quote) {
|
|
225
|
-
// Closing uses the SAME shape test as opening
|
|
226
|
-
//
|
|
227
|
-
// the close accepted any bare "'" - so the apostrophe in a possessive
|
|
228
|
-
// INSIDE a literal closed it early:
|
|
229
|
-
// "Always pass 'user's a, b list' to the parser."
|
|
230
|
-
// -> "Always pass 'user's a" (master kept the whole literal)
|
|
231
|
-
// a mid-literal fragment that then PASSES the write gate, which is
|
|
232
|
-
// precisely the defect this branch exists to remove. Found by the
|
|
233
|
-
// ship-gate review after every earlier gate missed it.
|
|
175
|
+
// Closing uses the SAME shape test as opening, else a possessive INSIDE a literal closes it early:
|
|
176
|
+
// "Always pass 'user's a, b list' to the parser." -> "Always pass 'user's a"
|
|
234
177
|
return full[i] === quote && (quote !== "'" || !isLetterOrDigit(full[i + 1]));
|
|
235
178
|
}
|
|
236
179
|
function opensSingleQuote(full, i, lastCloser) {
|
|
@@ -242,7 +185,6 @@ function opensSingleQuote(full, i, lastCloser) {
|
|
|
242
185
|
// restart..." never leaves quote mode, bounding disabled entirely
|
|
243
186
|
// treat no ' as a quote -> "Always pass 'a, b' to the parser."
|
|
244
187
|
// cuts at the comma and stores "Always pass 'a"
|
|
245
|
-
// Both were codex P1s on this branch, in consecutive rounds.
|
|
246
188
|
//
|
|
247
189
|
// Discriminator: a ' OPENS a literal only at a word boundary - preceded
|
|
248
190
|
// by start/whitespace/open-bracket AND followed by non-whitespace. An
|
|
@@ -257,7 +199,7 @@ function opensSingleQuote(full, i, lastCloser) {
|
|
|
257
199
|
// have no closer, so the scanner never leaves quote mode and bounding
|
|
258
200
|
// is disabled for the rest of the capture. Requiring an actual closing
|
|
259
201
|
// quote later in the string replaces a guess with a checkable fact -
|
|
260
|
-
// an elided form simply has no partner.
|
|
202
|
+
// an elided form simply has no partner.
|
|
261
203
|
// ...and the partner must LOOK like a closer, not merely be another
|
|
262
204
|
// apostrophe. Distance cannot separate the two cases - both put a `'`
|
|
263
205
|
// far downstream:
|
|
@@ -268,7 +210,7 @@ function opensSingleQuote(full, i, lastCloser) {
|
|
|
268
210
|
// elision, disabling bounding for the rest of the capture
|
|
269
211
|
// So apply the SAME shape rule already used to open a literal, mirrored:
|
|
270
212
|
// a closer has non-whitespace before it and whitespace/punctuation (not
|
|
271
|
-
// a letter) after. "user's" fails it on both counts.
|
|
213
|
+
// a letter) after. "user's" fails it on both counts.
|
|
272
214
|
return atBoundary && lastCloser > i;
|
|
273
215
|
}
|
|
274
216
|
function cleanExtract(raw) {
|
|
@@ -276,7 +218,7 @@ function cleanExtract(raw) {
|
|
|
276
218
|
.replace(/^[:\s-]+/, '')
|
|
277
219
|
.replace(/[.!?,;:\s]+$/, '')
|
|
278
220
|
.trim();
|
|
279
|
-
//
|
|
221
|
+
// Trailing cleanup: clause-bounding can cut inside a parenthetical and
|
|
280
222
|
// leave an unmatched trailing ')' (e.g. "...(two had never got entries),"
|
|
281
223
|
// bounds to "never got entries)"). Strip a trailing ')' ONLY while closes
|
|
282
224
|
// outnumber opens in the string so far — a balanced parenthetical like
|
|
@@ -316,51 +258,31 @@ function extractFromPatterns(sentence, patterns, category, tag) {
|
|
|
316
258
|
if (match) {
|
|
317
259
|
let bounded;
|
|
318
260
|
if (pat === PREFERENCE_PATTERNS[0]) {
|
|
319
|
-
// PREFERENCE_PATTERNS[0]
|
|
320
|
-
// comment at its definition) — its match[1] keeps its pre-DF2,
|
|
321
|
-
// unbounded shape rather than going through clause-bounding.
|
|
261
|
+
// PREFERENCE_PATTERNS[0] skips clause-bounding (see comment at its definition).
|
|
322
262
|
bounded = match[1] ?? match[0];
|
|
323
263
|
}
|
|
324
264
|
else {
|
|
325
265
|
// group1 = keyword + separator (verbatim, never clause-bounded);
|
|
326
266
|
// group2 = the content that follows it (clause-bounded below).
|
|
327
267
|
//
|
|
328
|
-
//
|
|
268
|
+
// The keyword is kept only when it carries SEMANTIC SIGN, a
|
|
329
269
|
// negation or modality ("never", "must not", "do not ever",
|
|
330
|
-
// "always")
|
|
331
|
-
// point of T1. A LABEL keyword ("decision:", "rule:", "error:",
|
|
270
|
+
// "always"), because dropping those inverts the meaning. A LABEL keyword ("decision:", "rule:", "error:",
|
|
332
271
|
// "important:") carries no sign: it only names the category, which
|
|
333
272
|
// is already recorded in `category`/`tags`, so prefixing it onto the
|
|
334
273
|
// content is duplication that also breaks value-keyed matching
|
|
335
|
-
// (
|
|
274
|
+
// (the rejected-value digest hashes the bare content).
|
|
336
275
|
// Discriminator: a label ends in its own colon, or is a "the X is"
|
|
337
276
|
// phrase.
|
|
338
277
|
const rawPrefix = match[1] ?? '';
|
|
339
|
-
// ONLY colon-terminated labels are dropped
|
|
340
|
-
//
|
|
341
|
-
// rejected outright - so "The plan is to ship on Friday" and "The fix
|
|
342
|
-
// was to bump the pool timeout" stored NOTHING, where every prior
|
|
343
|
-
// version stored them. Silent loss on two of the highest-traffic
|
|
344
|
-
// patterns, and invisible: an absent memory leaves no trace. The AT1
|
|
345
|
-
// rejected-value evidence only ever involved colon labels
|
|
346
|
-
// ("decision: "), so the narrower rule keeps that guarantee.
|
|
278
|
+
// ONLY colon-terminated labels are dropped: dropping "the X is/was" leaves a residue starting
|
|
279
|
+
// with "to ", which isFragment rejects, so "The plan is to ship on Friday" would store nothing.
|
|
347
280
|
const isLabelPrefix = /:\s*$/.test(rawPrefix);
|
|
348
281
|
const keywordPrefix = isLabelPrefix ? '' : rawPrefix;
|
|
349
|
-
// Scan the UNTRUNCATED remainder, not match[2]
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
// blindness built into the scanner's INPUT, not a bad predicate, so
|
|
354
|
-
// no further predicate could have fixed it. boundToClause already
|
|
355
|
-
// caps its OUTPUT at maxLen, so widening the input costs nothing and
|
|
356
|
-
// makes pairing decidable on the whole sentence. Codex P2, round 5.
|
|
357
|
-
// Group 2's REAL offset, read from the regex engine. Deriving it as
|
|
358
|
-
// `match.index + rawPrefix.length` assumes group 1 starts the match,
|
|
359
|
-
// but DECISION_PATTERNS carry an uncaptured subject ("we ", "let's ")
|
|
360
|
-
// ahead of it - so the offset landed inside the keyword and the
|
|
361
|
-
// widened slice duplicated text: "We decided to pin..." stored as
|
|
362
|
-
// "decided to to pin...". Real corruption of the commonest decision
|
|
363
|
-
// capture, shipped in the previous commit. Codex P1, r6.
|
|
282
|
+
// Scan the UNTRUNCATED remainder, not match[2]: a quoted literal whose closer sits past the
|
|
283
|
+
// 500-char group cap would read as prose; boundToClause caps its OUTPUT, so this costs nothing.
|
|
284
|
+
// Group 2's REAL offset from the regex engine: DECISION_PATTERNS carry an uncaptured subject
|
|
285
|
+
// ("we ", "let's ") ahead of group 1, so `match.index + rawPrefix.length` lands inside the keyword.
|
|
364
286
|
const contentStart = match.indices?.[2]?.[0] ?? -1;
|
|
365
287
|
const afterKeyword = contentStart >= 0 ? sentence.slice(contentStart) : (match[2] ?? match[0]);
|
|
366
288
|
const keywordStart = match.indices?.[1]?.[0] ?? -1;
|
package/dist/capture-error.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { JsonValue } from './
|
|
1
|
+
import type { JsonValue } from './json.js';
|
|
2
2
|
/** Why a failure was not stored, or `stored`. */
|
|
3
3
|
export type CaptureErrorOutcome = 'stored' | 'duplicate' | 'skipped-interrupt' | 'skipped-routine' | 'skipped-invalid';
|
|
4
4
|
/** Which routine check skipped a failure; the log keeps it so declines can be told apart from empty searches. */
|
package/dist/capture-error.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// `hippo capture-error`, run by the Claude Code PostToolUseFailure hook: routine failures and repeats are not
|
|
2
2
|
// stored, because error memories decay slowly and would crowd out real lessons; what is stored stays `observed`
|
|
3
|
-
// until outcome feedback confirms it. Every failure, stored or not, goes to the failure log
|
|
3
|
+
// until outcome feedback confirms it. Every failure, stored or not, goes to the failure log.
|
|
4
4
|
import { createMemory } from './memory.js';
|
|
5
5
|
import { writeEntry } from './store/entry-writes.js';
|
|
6
6
|
import { loadContentsWithTag } from './store/entry-reads.js';
|
package/dist/churn-git.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Git subprocess helpers for
|
|
1
|
+
/** Git subprocess helpers for churn-staleness (src/invalidation.ts). */
|
|
2
2
|
/** A real git failure (not git grep's expected exit-1-no-match). Callers abort the whole run on this. */
|
|
3
3
|
export declare class GitReadError extends Error {
|
|
4
4
|
}
|
package/dist/churn-git.js
CHANGED
package/dist/cli/audit.js
CHANGED
|
@@ -9,7 +9,7 @@ import { pruneAuditLog, parseOlderThanFlag } from '../audit-prune.js';
|
|
|
9
9
|
import { printError } from './output.js';
|
|
10
10
|
import { requireInit, resolveAuthRoot } from './shared.js';
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
|
-
// Audit log subcommands (
|
|
12
|
+
// Audit log subcommands (`hippo audit list`)
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
const VALID_AUDIT_OPS = new Set(AUDIT_OPS);
|
|
15
15
|
function formatAuditRow(ev) {
|
|
@@ -23,8 +23,7 @@ function cmdAuditList(hippoRoot, flags) {
|
|
|
23
23
|
const tenantId = resolveTenantId({});
|
|
24
24
|
const opFlag = typeof flags['op'] === 'string' ? flags['op'] : undefined;
|
|
25
25
|
if (opFlag && !VALID_AUDIT_OPS.has(opFlag)) {
|
|
26
|
-
//
|
|
27
|
-
// was hand-maintained and had drifted — missed 'auth_revoke' and 'outcome').
|
|
26
|
+
// Built from the Set so the message cannot drift from the valid ops.
|
|
28
27
|
const expected = Array.from(VALID_AUDIT_OPS).join(' | ');
|
|
29
28
|
printError(`Unknown --op value: ${opFlag}. Expected one of: ${expected}.`);
|
|
30
29
|
process.exit(1);
|
|
@@ -115,7 +114,7 @@ function cmdAuditLog(hippoRoot, args, flags) {
|
|
|
115
114
|
process.exit(1);
|
|
116
115
|
}
|
|
117
116
|
export function handleAudit({ hippoRoot, args, flags }) {
|
|
118
|
-
// `audit list` and `audit prune` ->
|
|
117
|
+
// `audit list` and `audit prune` -> audit-log subcommands.
|
|
119
118
|
// Other forms (no sub, --fix) keep the existing memory-quality auditor
|
|
120
119
|
// for backwards compatibility.
|
|
121
120
|
if (args[0] === 'list' || args[0] === 'prune') {
|
package/dist/cli/auth.js
CHANGED
|
@@ -6,16 +6,14 @@ import { resolveTenantId } from '../tenant.js';
|
|
|
6
6
|
import { printError } from './output.js';
|
|
7
7
|
import { resolveAuthRoot } from './shared.js';
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
|
-
// Auth subcommands
|
|
9
|
+
// Auth subcommands
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
function cmdAuthCreate(hippoRoot, flags) {
|
|
12
12
|
const root = resolveAuthRoot(hippoRoot, flags);
|
|
13
13
|
const tenantFlag = typeof flags['tenant'] === 'string' ? flags['tenant'] : undefined;
|
|
14
14
|
const labelFlag = typeof flags['label'] === 'string' ? flags['label'] : undefined;
|
|
15
15
|
const asJson = Boolean(flags['json']);
|
|
16
|
-
//
|
|
17
|
-
// sub-1. Accepts 'admin' | 'member' only; anything else exits 1 with a
|
|
18
|
-
// typed error so a typo doesn't silently default to admin.
|
|
16
|
+
// Accepts 'admin' | 'member' only; anything else exits 1 so a typo doesn't silently default to admin.
|
|
19
17
|
const roleFlag = typeof flags['role'] === 'string' ? flags['role'] : undefined;
|
|
20
18
|
let role = 'admin';
|
|
21
19
|
if (roleFlag !== undefined) {
|
|
@@ -57,7 +55,6 @@ function formatKeyRow(item) {
|
|
|
57
55
|
const label = item.label ?? '-';
|
|
58
56
|
const created = item.createdAt;
|
|
59
57
|
const revoked = item.revokedAt ?? '-';
|
|
60
|
-
// v1.12.3: role column surfaced
|
|
61
58
|
return `${item.keyId} ${item.tenantId} ${item.role} ${label} ${created} ${revoked}`;
|
|
62
59
|
}
|
|
63
60
|
function cmdAuthList(hippoRoot, flags) {
|
|
@@ -111,7 +108,7 @@ function cmdAuthRevoke(hippoRoot, keyId, flags) {
|
|
|
111
108
|
}
|
|
112
109
|
console.log(`Revoked ${keyId} at ${revokedAt}`);
|
|
113
110
|
}
|
|
114
|
-
/**
|
|
111
|
+
/** `hippo auth grant|ungrant <key_id> <scope>`, routed through api so the tenant, restricted-scope and audit checks live in one place. */
|
|
115
112
|
function cmdAuthScopeGrant(hippoRoot, keyId, scope, grant, flags) {
|
|
116
113
|
const ctx = keyContext(resolveAuthRoot(hippoRoot, flags), keyId);
|
|
117
114
|
try {
|