hippo-memory 1.40.0 → 1.42.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 +8 -4
- package/dist/card.d.ts +3 -1
- package/dist/card.d.ts.map +1 -1
- package/dist/card.js +4 -1
- package/dist/card.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +106 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/rerankers/cross-encoder.d.ts +1 -8
- package/dist/rerankers/cross-encoder.d.ts.map +1 -1
- package/dist/rerankers/cross-encoder.js +58 -52
- package/dist/rerankers/cross-encoder.js.map +1 -1
- package/dist/rerankers/index.d.ts.map +1 -1
- package/dist/rerankers/index.js +2 -0
- package/dist/rerankers/index.js.map +1 -1
- package/dist/rerankers/jev.d.ts +9 -0
- package/dist/rerankers/jev.d.ts.map +1 -0
- package/dist/rerankers/jev.js +116 -0
- package/dist/rerankers/jev.js.map +1 -0
- package/dist/rerankers/types.d.ts +7 -4
- package/dist/rerankers/types.d.ts.map +1 -1
- package/dist/src/card.js +4 -1
- package/dist/src/card.js.map +1 -1
- package/dist/src/cli.js +106 -24
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/rerankers/cross-encoder.js +58 -52
- package/dist/src/rerankers/cross-encoder.js.map +1 -1
- package/dist/src/rerankers/index.js +2 -0
- package/dist/src/rerankers/index.js.map +1 -1
- package/dist/src/rerankers/jev.js +116 -0
- package/dist/src/rerankers/jev.js.map +1 -0
- package/dist/src/store.js +122 -22
- package/dist/src/store.js.map +1 -1
- package/dist/src/version.js +2 -15
- package/dist/src/version.js.map +1 -1
- package/dist/store.d.ts +14 -8
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +122 -22
- package/dist/store.js.map +1 -1
- package/dist/version.d.ts +2 -15
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -15
- package/dist/version.js.map +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/README.md
CHANGED
|
@@ -622,10 +622,12 @@ hippo watch "npm run build"
|
|
|
622
622
|
| `hippo card create --title "..."` | Create a work-queue card (`--repo`, `--contract`, `--budget`, repeatable `--depends-on <id>`) |
|
|
623
623
|
| `hippo card show <id>` | Show a card, its deps, runs, comments and latest handoff |
|
|
624
624
|
| `hippo card list [--status <status>]` | List cards, newest-updated first |
|
|
625
|
-
| `hippo card claim <id> --runtime <name>` | Claim a ready or blocked card |
|
|
626
|
-
| `hippo card
|
|
627
|
-
| `hippo card
|
|
628
|
-
| `hippo card
|
|
625
|
+
| `hippo card claim <id> --runtime <name>` | Claim a ready or blocked card; prints its run id and the time its 4-hour lease expires |
|
|
626
|
+
| `hippo card heartbeat <id> --run <n>` | Extend a claimed card's lease |
|
|
627
|
+
| `hippo card block <id> --reason "<why>" [--run <n>]` | Block a running card; the reason is recorded as a comment |
|
|
628
|
+
| `hippo card review <id> [--run <n>]` | Move a running card to review |
|
|
629
|
+
| `hippo card complete <id> --outcome <success\|failure\|partial> [--run <n>]` | Complete a card in review: `success` marks it done and promotes children whose parents are all done; `failure` or `partial` shelves it |
|
|
630
|
+
| `hippo card reclaim` | Sweep every card whose lease has passed and return it to ready |
|
|
629
631
|
| `hippo card comment <id> --body "..."` | Add a comment to a card |
|
|
630
632
|
| `hippo wm push --scope <s> --content "..."` | Push to working memory |
|
|
631
633
|
| `hippo wm read --scope <s>` | Read working memory entries |
|
|
@@ -635,6 +637,8 @@ hippo watch "npm run build"
|
|
|
635
637
|
| `hippo dashboard --port <n>` | Use custom port |
|
|
636
638
|
| `hippo mcp` | Start MCP server (stdio transport) |
|
|
637
639
|
|
|
640
|
+
On `heartbeat`, `block`, `review` and `complete`, a given `--run` is checked against the card's live run and the command is refused, unchanged, if the two do not match.
|
|
641
|
+
|
|
638
642
|
---
|
|
639
643
|
|
|
640
644
|
## Framework Integrations
|
package/dist/card.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export type CardStatus = 'backlog' | 'ready' | 'running' | 'blocked' | 'review' | 'done' | 'shelved';
|
|
3
3
|
/** Narrows a raw string, such as a CLI flag value, to a CardStatus. */
|
|
4
4
|
export declare function isCardStatus(v: string): v is CardStatus;
|
|
5
|
-
/** A card row; leaseUntil and heartbeatAt are
|
|
5
|
+
/** A card row; leaseUntil and heartbeatAt are null unless the card is running, and a card claimed under 1.40.0 runs with both null until a heartbeat sets them. */
|
|
6
6
|
export interface Card {
|
|
7
7
|
id: string;
|
|
8
8
|
title: string;
|
|
@@ -42,4 +42,6 @@ export type CardTransitions = {
|
|
|
42
42
|
};
|
|
43
43
|
/** transitionCard checks every status write against this map. */
|
|
44
44
|
export declare const CARD_TRANSITIONS: CardTransitions;
|
|
45
|
+
/** How long a claim or a heartbeat keeps a running card's lease before reclaimExpiredCards may return it to ready. */
|
|
46
|
+
export declare const CARD_LEASE_MS: number;
|
|
45
47
|
//# sourceMappingURL=card.d.ts.map
|
package/dist/card.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AACA,gGAAgG;AAChG,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAIrG,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,UAAU,CAEvD;AAED,
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AACA,gGAAgG;AAChG,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAIrG,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,UAAU,CAEvD;AAED,mKAAmK;AACnK,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mDAAmD;AACnD,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,UAAU,GAAG,SAAS,UAAU,EAAE;CAAE,CAAC;AAEpF,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,EAAE,eAQ9B,CAAC;AAGF,sHAAsH;AACtH,eAAO,MAAM,aAAa,QAAqB,CAAC"}
|
package/dist/card.js
CHANGED
|
@@ -7,10 +7,13 @@ export function isCardStatus(v) {
|
|
|
7
7
|
export const CARD_TRANSITIONS = {
|
|
8
8
|
backlog: ['ready'],
|
|
9
9
|
ready: ['running'],
|
|
10
|
-
running: ['blocked', 'review'],
|
|
10
|
+
running: ['blocked', 'review', 'ready'],
|
|
11
11
|
blocked: ['running'],
|
|
12
12
|
review: ['done', 'shelved'],
|
|
13
13
|
done: [],
|
|
14
14
|
shelved: [],
|
|
15
15
|
};
|
|
16
|
+
// SHORTCUT: one fixed lease for every claim; add a per-claim lease when the W3 dispatcher heartbeats on a timer.
|
|
17
|
+
/** How long a claim or a heartbeat keeps a running card's lease before reclaimExpiredCards may return it to ready. */
|
|
18
|
+
export const CARD_LEASE_MS = 4 * 60 * 60 * 1000;
|
|
16
19
|
//# sourceMappingURL=card.js.map
|
package/dist/card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAIA,MAAM,aAAa,GAA0B,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAErH,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AA0CD,iEAAiE;AACjE,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC,OAAO,CAAC;IAClB,KAAK,EAAE,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAIA,MAAM,aAAa,GAA0B,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAErH,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AA0CD,iEAAiE;AACjE,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC,OAAO,CAAC;IAClB,KAAK,EAAE,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC;IACvC,OAAO,EAAE,CAAC,SAAS,CAAC;IACpB,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF,iHAAiH;AACjH,sHAAsH;AACtH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* hippo snapshot <save|show|clear>
|
|
14
14
|
* hippo session <log|show|latest|resume|complete>
|
|
15
15
|
* hippo handoff <create|latest|show>
|
|
16
|
-
* hippo card <create|show|list|claim|block|review|complete|comment>
|
|
16
|
+
* hippo card <create|show|list|claim|heartbeat|block|review|complete|reclaim|comment>
|
|
17
17
|
* hippo current <show>
|
|
18
18
|
* hippo forget <id> [--archive --reason "<why>"]
|
|
19
19
|
* hippo reject <id>|--value "<text>" --reason "<why>"
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA2BH,OAAO,EAWL,WAAW,EAEZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA2BH,OAAO,EAWL,WAAW,EAEZ,MAAM,aAAa,CAAC;AA6HrB,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AA4ChC,kFAAkF;AAClF,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAuJD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,CAwCjI;AAqxED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,MAAqB,GAAG,MAAM,CAyF3F;AAyGD;;;GAGG;AACH,oHAAoH;AACpH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAuD/D;AAigHD,oHAAoH;AACpH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,EACtF,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,MAAkB,GAC1B,IAAI,CA8BN"}
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* hippo snapshot <save|show|clear>
|
|
14
14
|
* hippo session <log|show|latest|resume|complete>
|
|
15
15
|
* hippo handoff <create|latest|show>
|
|
16
|
-
* hippo card <create|show|list|claim|block|review|complete|comment>
|
|
16
|
+
* hippo card <create|show|list|claim|heartbeat|block|review|complete|reclaim|comment>
|
|
17
17
|
* hippo current <show>
|
|
18
18
|
* hippo forget <id> [--archive --reason "<why>"]
|
|
19
19
|
* hippo reject <id>|--value "<text>" --reason "<why>"
|
|
@@ -38,7 +38,7 @@ import { execFileSync, execSync, spawn } from 'child_process';
|
|
|
38
38
|
import { installJsonHooks, uninstallJsonHooks, resolveJsonHookPaths, detectInstalledTools, defaultSleepLogPath, ensureCodexWrapperInstalled, installCodexWrapper, isCodexWrapperInstalled, repairCodexWrapperIfInstalled, uninstallCodexWrapper, resolveCodexSessionTranscript, resolveCodexWrapperPaths, installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath, } from './hooks.js';
|
|
39
39
|
import { createMemory, calculateStrength, calculateRewardFactor, deriveHalfLife, resolveConfidence, confidenceFacets, confidenceLabel, computeSchemaFit, Layer, } from './memory.js';
|
|
40
40
|
import { detectSecret } from './secret-detect.js';
|
|
41
|
-
import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadRecallSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, closeTaskSnapshotsForSession, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, stampHandoffOutcome, writeSessionEndHandoff, createCard, loadCard, listCards, loadCardDeps, loadCardRuns, loadCardComments, claimCard, blockCard, reviewCard, completeCard, addCardComment, loadLatestHandoffForCard, } from './store.js';
|
|
41
|
+
import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadRecallSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, closeTaskSnapshotsForSession, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, stampHandoffOutcome, writeSessionEndHandoff, createCard, loadCard, listCards, loadCardDeps, loadCardRuns, loadCardComments, claimCard, heartbeatCard, blockCard, reviewCard, completeCard, reclaimExpiredCards, addCardComment, loadLatestHandoffForCard, } from './store.js';
|
|
42
42
|
import { rejectValue, unrejectValue, listRejectionsForTenant } from './reject-flow.js';
|
|
43
43
|
import { RejectedValueError } from './rejection.js';
|
|
44
44
|
import { isHandoffOutcome, formatHandoffEvidenceLine } from './handoff.js';
|
|
@@ -117,6 +117,7 @@ import { multihopSearch } from './multihop.js';
|
|
|
117
117
|
import { graphExpandRecall, MAX_HOPS, DEFAULT_MAX_NEIGHBORS } from './graph-recall.js';
|
|
118
118
|
import { DEFAULT_GRAPH_STREAM_WEIGHT } from './graph-stream.js';
|
|
119
119
|
import { getReranker } from './rerankers/index.js';
|
|
120
|
+
import { JEV_DEFAULT_TOP_K } from './rerankers/jev.js';
|
|
120
121
|
import { computeSalience } from './salience.js';
|
|
121
122
|
import { renderAmbientSummary } from './ambient.js';
|
|
122
123
|
import { validateOwner, isStrictOwnerEnv } from './owner-validation.js';
|
|
@@ -1213,10 +1214,10 @@ async function cmdRecall(hippoRoot, query, flags) {
|
|
|
1213
1214
|
// --reranker <name> is set, look up the reranker fn from the registry
|
|
1214
1215
|
// (src/rerankers/index.ts) and apply it to the top-K candidates. The
|
|
1215
1216
|
// reranker reorders (and may rescale) results; the post-budget set is
|
|
1216
|
-
// returned. Default off; opt-in via --reranker <cross-encoder|llm>. The
|
|
1217
|
+
// returned. Default off; opt-in via --reranker <cross-encoder|jev|llm>. The
|
|
1217
1218
|
// structurally similar --rerank-utility block above is the OFC MVP and is
|
|
1218
1219
|
// independent — both can run in the same recall, with --rerank-utility
|
|
1219
|
-
// applied first. Available rerankers: cross-encoder, llm (see
|
|
1220
|
+
// applied first. Available rerankers: cross-encoder, jev, llm (see
|
|
1220
1221
|
// src/rerankers/index.ts). The Track 1 `features` reranker was removed in
|
|
1221
1222
|
// v1.9.1 per the F10 HARD RETRACTION; it is no longer a valid value.
|
|
1222
1223
|
const rerankerName = flags['reranker'] !== undefined ? String(flags['reranker']).trim() : '';
|
|
@@ -1225,7 +1226,7 @@ async function cmdRecall(hippoRoot, query, flags) {
|
|
|
1225
1226
|
if (rerankerFn) {
|
|
1226
1227
|
const topK = flags['reranker-top-k'] !== undefined
|
|
1227
1228
|
? parseInt(String(flags['reranker-top-k']), 10)
|
|
1228
|
-
: 50;
|
|
1229
|
+
: rerankerName === 'jev' ? JEV_DEFAULT_TOP_K : 50;
|
|
1229
1230
|
const head = results.slice(0, topK);
|
|
1230
1231
|
const tail = results.slice(topK);
|
|
1231
1232
|
const rerankInput = head.map((r, i) => ({ ...r, preRerankRank: i + 1 }));
|
|
@@ -4034,6 +4035,10 @@ function printCard(hippoRoot, tenantId, card) {
|
|
|
4034
4035
|
console.log(`- Status: ${card.status}`);
|
|
4035
4036
|
if (card.assigneeRuntime)
|
|
4036
4037
|
console.log(`- Assignee: ${card.assigneeRuntime}`);
|
|
4038
|
+
if (card.leaseUntil)
|
|
4039
|
+
console.log(`- Lease until: ${card.leaseUntil}`);
|
|
4040
|
+
if (card.heartbeatAt)
|
|
4041
|
+
console.log(`- Heartbeat: ${card.heartbeatAt}`);
|
|
4037
4042
|
if (card.repo)
|
|
4038
4043
|
console.log(`- Repo: ${card.repo}`);
|
|
4039
4044
|
if (card.contract)
|
|
@@ -4050,7 +4055,7 @@ function printCard(hippoRoot, tenantId, card) {
|
|
|
4050
4055
|
if (runs.length > 0) {
|
|
4051
4056
|
console.log('\n### Runs');
|
|
4052
4057
|
for (const run of runs) {
|
|
4053
|
-
console.log(`- ${run.runtime} started ${run.started}${run.ended ? ` ended ${run.ended} (${run.outcome})` : ' (open)'}`);
|
|
4058
|
+
console.log(`- run ${run.id}: ${run.runtime} started ${run.started}${run.ended ? ` ended ${run.ended} (${run.outcome})` : ' (open)'}`);
|
|
4054
4059
|
}
|
|
4055
4060
|
}
|
|
4056
4061
|
const comments = loadCardComments(hippoRoot, tenantId, card.id);
|
|
@@ -4080,14 +4085,34 @@ function cardStringFlag(flags, key) {
|
|
|
4080
4085
|
}
|
|
4081
4086
|
return v.trim();
|
|
4082
4087
|
}
|
|
4088
|
+
// A too-large --run would silently round to a different id (mirrors parsePositiveIncidentId).
|
|
4089
|
+
function cardRunFlag(flags) {
|
|
4090
|
+
const raw = cardStringFlag(flags, 'run');
|
|
4091
|
+
if (raw === undefined)
|
|
4092
|
+
return undefined;
|
|
4093
|
+
const n = Number(raw);
|
|
4094
|
+
if (!/^\d+$/.test(raw) || !Number.isSafeInteger(n) || n <= 0) {
|
|
4095
|
+
console.error(`Invalid --run: "${raw}" (expected a positive integer).`);
|
|
4096
|
+
process.exit(1);
|
|
4097
|
+
}
|
|
4098
|
+
return n;
|
|
4099
|
+
}
|
|
4100
|
+
// Reads after the store already refused, so this only explains the refusal, never changes it.
|
|
4101
|
+
function cardRefusal(hippoRoot, tenantId, id) {
|
|
4102
|
+
const card = loadCard(hippoRoot, tenantId, id);
|
|
4103
|
+
const liveRun = loadCardRuns(hippoRoot, tenantId, id).find((r) => !r.ended);
|
|
4104
|
+
return `status ${card?.status ?? 'unknown'}, live run ${liveRun?.id ?? 'none'}`;
|
|
4105
|
+
}
|
|
4083
4106
|
const CARD_SUBCOMMAND_FLAGS = {
|
|
4084
4107
|
create: ['title', 'repo', 'contract', 'budget', 'depends-on'],
|
|
4085
4108
|
show: ['json'],
|
|
4086
4109
|
list: ['status', 'json'],
|
|
4087
4110
|
claim: ['runtime', 'session'],
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4111
|
+
heartbeat: ['run'],
|
|
4112
|
+
block: ['reason', 'run'],
|
|
4113
|
+
review: ['run'],
|
|
4114
|
+
complete: ['outcome', 'run'],
|
|
4115
|
+
reclaim: new Array(),
|
|
4091
4116
|
comment: ['body', 'author'],
|
|
4092
4117
|
};
|
|
4093
4118
|
function cmdCard(hippoRoot, args, flags) {
|
|
@@ -4205,7 +4230,29 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4205
4230
|
console.error(`Could not claim card ${id} (not ready/blocked, or already claimed).`);
|
|
4206
4231
|
process.exit(1);
|
|
4207
4232
|
}
|
|
4208
|
-
console.log(`Claimed card ${card.id} for ${runtime}`);
|
|
4233
|
+
console.log(`Claimed card ${card.id} for ${runtime} (run ${card.runId}, lease until ${card.leaseUntil})`);
|
|
4234
|
+
return;
|
|
4235
|
+
}
|
|
4236
|
+
if (subcommand === 'heartbeat') {
|
|
4237
|
+
const id = args[1];
|
|
4238
|
+
const runId = cardRunFlag(flags);
|
|
4239
|
+
if (!id || runId === undefined) {
|
|
4240
|
+
console.error('Usage: hippo card heartbeat <id> --run <n>');
|
|
4241
|
+
process.exit(1);
|
|
4242
|
+
}
|
|
4243
|
+
let card;
|
|
4244
|
+
try {
|
|
4245
|
+
card = heartbeatCard(hippoRoot, tenantId, id, runId);
|
|
4246
|
+
}
|
|
4247
|
+
catch (error) {
|
|
4248
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
4249
|
+
process.exit(1);
|
|
4250
|
+
}
|
|
4251
|
+
if (!card) {
|
|
4252
|
+
console.error(`Could not heartbeat card ${id} (${cardRefusal(hippoRoot, tenantId, id)}).`);
|
|
4253
|
+
process.exit(1);
|
|
4254
|
+
}
|
|
4255
|
+
console.log(`Heartbeat card ${card.id}: lease until ${card.leaseUntil}`);
|
|
4209
4256
|
return;
|
|
4210
4257
|
}
|
|
4211
4258
|
if (subcommand === 'block') {
|
|
@@ -4215,16 +4262,18 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4215
4262
|
console.error(CARD_BLOCK_REASON_REQUIRED);
|
|
4216
4263
|
process.exit(1);
|
|
4217
4264
|
}
|
|
4265
|
+
const runId = cardRunFlag(flags);
|
|
4218
4266
|
let card;
|
|
4219
4267
|
try {
|
|
4220
|
-
card = blockCard(hippoRoot, tenantId, id, reason);
|
|
4268
|
+
card = blockCard(hippoRoot, tenantId, id, reason, runId);
|
|
4221
4269
|
}
|
|
4222
4270
|
catch (error) {
|
|
4223
4271
|
console.error(error instanceof Error ? error.message : String(error));
|
|
4224
4272
|
process.exit(1);
|
|
4225
4273
|
}
|
|
4226
4274
|
if (!card) {
|
|
4227
|
-
|
|
4275
|
+
const why = runId === undefined ? 'not running' : cardRefusal(hippoRoot, tenantId, id);
|
|
4276
|
+
console.error(`Could not block card ${id} (${why}).`);
|
|
4228
4277
|
process.exit(1);
|
|
4229
4278
|
}
|
|
4230
4279
|
console.log(`Blocked card ${card.id}`);
|
|
@@ -4233,19 +4282,21 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4233
4282
|
if (subcommand === 'review') {
|
|
4234
4283
|
const id = args[1];
|
|
4235
4284
|
if (!id) {
|
|
4236
|
-
console.error('Usage: hippo card review <id>');
|
|
4285
|
+
console.error('Usage: hippo card review <id> [--run <n>]');
|
|
4237
4286
|
process.exit(1);
|
|
4238
4287
|
}
|
|
4288
|
+
const runId = cardRunFlag(flags);
|
|
4239
4289
|
let card;
|
|
4240
4290
|
try {
|
|
4241
|
-
card = reviewCard(hippoRoot, tenantId, id);
|
|
4291
|
+
card = reviewCard(hippoRoot, tenantId, id, runId);
|
|
4242
4292
|
}
|
|
4243
4293
|
catch (error) {
|
|
4244
4294
|
console.error(error instanceof Error ? error.message : String(error));
|
|
4245
4295
|
process.exit(1);
|
|
4246
4296
|
}
|
|
4247
4297
|
if (!card) {
|
|
4248
|
-
|
|
4298
|
+
const why = runId === undefined ? 'not running' : cardRefusal(hippoRoot, tenantId, id);
|
|
4299
|
+
console.error(`Could not move card ${id} to review (${why}).`);
|
|
4249
4300
|
process.exit(1);
|
|
4250
4301
|
}
|
|
4251
4302
|
console.log(`Card ${card.id} moved to review`);
|
|
@@ -4255,19 +4306,21 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4255
4306
|
const id = args[1];
|
|
4256
4307
|
const outcomeRaw = flags['outcome'];
|
|
4257
4308
|
if (!id || !isHandoffOutcome(outcomeRaw)) {
|
|
4258
|
-
console.error('Usage: hippo card complete <id> --outcome <success|failure|partial>');
|
|
4309
|
+
console.error('Usage: hippo card complete <id> --outcome <success|failure|partial> [--run <n>]');
|
|
4259
4310
|
process.exit(1);
|
|
4260
4311
|
}
|
|
4312
|
+
const runId = cardRunFlag(flags);
|
|
4261
4313
|
let result;
|
|
4262
4314
|
try {
|
|
4263
|
-
result = completeCard(hippoRoot, tenantId, id, outcomeRaw);
|
|
4315
|
+
result = completeCard(hippoRoot, tenantId, id, outcomeRaw, runId);
|
|
4264
4316
|
}
|
|
4265
4317
|
catch (error) {
|
|
4266
4318
|
console.error(error instanceof Error ? error.message : String(error));
|
|
4267
4319
|
process.exit(1);
|
|
4268
4320
|
}
|
|
4269
4321
|
if (!result) {
|
|
4270
|
-
|
|
4322
|
+
const why = runId === undefined ? 'not in review' : cardRefusal(hippoRoot, tenantId, id);
|
|
4323
|
+
console.error(`Could not complete card ${id} (${why}).`);
|
|
4271
4324
|
process.exit(1);
|
|
4272
4325
|
}
|
|
4273
4326
|
console.log(`Completed card ${result.card.id} (status: ${result.card.status})`);
|
|
@@ -4276,13 +4329,28 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4276
4329
|
}
|
|
4277
4330
|
return;
|
|
4278
4331
|
}
|
|
4332
|
+
if (subcommand === 'reclaim') {
|
|
4333
|
+
if (args.length > 1) {
|
|
4334
|
+
console.error('Usage: hippo card reclaim (sweeps every expired lease; use hippo card block <id> for one card)');
|
|
4335
|
+
process.exit(1);
|
|
4336
|
+
}
|
|
4337
|
+
const ids = reclaimExpiredCards(hippoRoot, tenantId);
|
|
4338
|
+
if (ids.length === 0) {
|
|
4339
|
+
console.log('No expired leases.');
|
|
4340
|
+
return;
|
|
4341
|
+
}
|
|
4342
|
+
for (const id of ids) {
|
|
4343
|
+
console.log(`Reclaimed card ${id} (now ready)`);
|
|
4344
|
+
}
|
|
4345
|
+
return;
|
|
4346
|
+
}
|
|
4279
4347
|
if (subcommand === 'comment') {
|
|
4280
4348
|
const id = args[1];
|
|
4281
4349
|
if (!id) {
|
|
4282
4350
|
console.error('Usage: hippo card comment <id> --body "..." [--author <name>]');
|
|
4283
4351
|
process.exit(1);
|
|
4284
4352
|
}
|
|
4285
|
-
// Only show and comment look the card up directly; claim/block/review/complete throw from the store instead.
|
|
4353
|
+
// Only show and comment look the card up directly; claim/heartbeat/block/review/complete throw from the store instead.
|
|
4286
4354
|
const card = loadCard(hippoRoot, tenantId, id);
|
|
4287
4355
|
if (!card) {
|
|
4288
4356
|
console.error(`No card found with id ${id}.`);
|
|
@@ -4298,7 +4366,7 @@ function cmdCard(hippoRoot, args, flags) {
|
|
|
4298
4366
|
console.log(`Added comment ${comment.id} to card ${id}`);
|
|
4299
4367
|
return;
|
|
4300
4368
|
}
|
|
4301
|
-
console.error('Usage: hippo card <create|show|list|claim|block|review|complete|comment>');
|
|
4369
|
+
console.error('Usage: hippo card <create|show|list|claim|heartbeat|block|review|complete|reclaim|comment>');
|
|
4302
4370
|
process.exit(1);
|
|
4303
4371
|
}
|
|
4304
4372
|
// ---------------------------------------------------------------------------
|
|
@@ -8047,11 +8115,17 @@ Commands:
|
|
|
8047
8115
|
where cost_factor = min(0.3, tokens / 10000). Re-sorts
|
|
8048
8116
|
results by utility. Default off. RESEARCH.md §PFC.OFC.
|
|
8049
8117
|
--reranker <name> Apply a reranker pass after retrieval
|
|
8050
|
-
(cross-encoder|llm). Looks up the named
|
|
8118
|
+
(cross-encoder|jev|llm). Looks up the named
|
|
8051
8119
|
reranker from src/rerankers/index.ts and re-orders
|
|
8052
8120
|
the top-K candidates. Default unset (no reranker).
|
|
8053
|
-
|
|
8054
|
-
|
|
8121
|
+
jev calls the hosted TypeSafe Jev API: it needs
|
|
8122
|
+
TYPESAFE_API_KEY, sends the query and candidate
|
|
8123
|
+
text to that API, costs about 0.0004 USD a recall,
|
|
8124
|
+
and falls back to cross-encoder on any failure.
|
|
8125
|
+
See docs/evals/2026-09-19-jev-reranker.md and
|
|
8126
|
+
docs/plans/2026-05-10-f6-reranker-hardening.md.
|
|
8127
|
+
--reranker-top-k <n> Cap candidates passed to the reranker (default 50;
|
|
8128
|
+
40 for jev).
|
|
8055
8129
|
--goal <tag> dlPFC goal-conditioned recall: memories tagged with
|
|
8056
8130
|
the goal tag get a 1.5x score boost and results are
|
|
8057
8131
|
re-sorted. Default off. RESEARCH.md §PFC.dlPFC.
|
|
@@ -8224,14 +8298,20 @@ Commands:
|
|
|
8224
8298
|
--json Output as JSON
|
|
8225
8299
|
card list List cards, newest-updated first
|
|
8226
8300
|
--status <status> Filter by status
|
|
8227
|
-
card claim <id> Claim a ready or blocked card
|
|
8301
|
+
card claim <id> Claim a ready or blocked card; prints its run id and lease
|
|
8228
8302
|
--runtime <name> Claiming runtime (required)
|
|
8229
8303
|
--session <id> Session ID
|
|
8304
|
+
card heartbeat <id> Extend a running card's lease
|
|
8305
|
+
--run <n> Your run id, as card claim printed it (required)
|
|
8230
8306
|
card block <id> Block a running card
|
|
8231
8307
|
--reason "<why>" Reason recorded as a card comment (required)
|
|
8308
|
+
--run <n> Refuse unless <n> is the card's live run
|
|
8232
8309
|
card review <id> Move a running card to review
|
|
8310
|
+
--run <n> Refuse unless <n> is the card's live run
|
|
8233
8311
|
card complete <id> Complete a card in review
|
|
8234
8312
|
--outcome <o> success | failure | partial (required)
|
|
8313
|
+
--run <n> Refuse unless <n> is the card's live run
|
|
8314
|
+
card reclaim Return every running card whose lease has expired to ready
|
|
8235
8315
|
card comment <id> Add a comment to a card
|
|
8236
8316
|
--body <text> Comment body (required)
|
|
8237
8317
|
--author <name> Comment author (default: cli)
|
|
@@ -8463,6 +8543,8 @@ Examples:
|
|
|
8463
8543
|
hippo card create --title "Add cards table" --repo hippo --depends-on card_abc
|
|
8464
8544
|
hippo card claim card_abc --runtime codex
|
|
8465
8545
|
hippo card complete card_abc --outcome success
|
|
8546
|
+
hippo card heartbeat card_abc --run 7
|
|
8547
|
+
hippo card reclaim
|
|
8466
8548
|
hippo embed --status
|
|
8467
8549
|
hippo watch "npm run build"
|
|
8468
8550
|
hippo learn --git --days 30
|