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/cli/playbooks.js
CHANGED
|
@@ -6,11 +6,8 @@ import * as skillsModule from '../skills.js';
|
|
|
6
6
|
import { resolveTenantId } from '../tenant.js';
|
|
7
7
|
import { printError } from './output.js';
|
|
8
8
|
import { requireInit } from './shared.js';
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// `process close 1abc` / `supersede 1abc` silently hit the wrong row; require
|
|
12
|
-
// the whole arg to be digits. (Mirrors parsePositiveIncidentId; codex P2,
|
|
13
|
-
// 2026-05-29.)
|
|
9
|
+
// parseInt alone accepts trailing junk ('1abc' -> 1), which would let `process close 1abc`
|
|
10
|
+
// silently hit the wrong row; require the whole arg to be digits.
|
|
14
11
|
function parsePositiveProcessId(idRaw) {
|
|
15
12
|
const s = String(idRaw ?? '').trim();
|
|
16
13
|
const id = parseInt(s, 10);
|
|
@@ -33,135 +30,144 @@ function collectProcessSteps(stepRaw) {
|
|
|
33
30
|
}
|
|
34
31
|
return [];
|
|
35
32
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const status = typeof statusRaw === 'string' ? statusRaw.trim() : 'all';
|
|
43
|
-
const limitRaw = flags['limit'];
|
|
44
|
-
const limit = limitRaw !== undefined ? parseInt(String(limitRaw), 10) : 100;
|
|
45
|
-
if (!Number.isFinite(limit) || limit <= 0) {
|
|
46
|
-
printError(`Invalid --limit: "${limitRaw}". Must be a positive integer.`);
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
let results;
|
|
50
|
-
if (status === 'all') {
|
|
51
|
-
results = processesModule.loadProcesses(hippoRoot, tenantId, { limit });
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
if (!processesModule.VALID_PROCESS_STATES.has(status)) {
|
|
55
|
-
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
results = processesModule.loadProcesses(hippoRoot, tenantId, {
|
|
59
|
-
status: status,
|
|
60
|
-
limit,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
if (results.length === 0) {
|
|
64
|
-
console.log('No processes.');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
console.log(`Found ${results.length} processes:\n`);
|
|
68
|
-
for (const proc of results) {
|
|
69
|
-
console.log(`#${proc.id} [${proc.status}] v${proc.version} steps=${proc.steps.length} memory=${proc.memoryId ?? '-'}`);
|
|
70
|
-
console.log(` ${proc.processName}`);
|
|
71
|
-
if (proc.changeSummary)
|
|
72
|
-
console.log(` change: ${proc.changeSummary}`);
|
|
73
|
-
}
|
|
74
|
-
return;
|
|
33
|
+
function parseListLimit(flags) {
|
|
34
|
+
const limitRaw = flags['limit'];
|
|
35
|
+
const limit = limitRaw !== undefined ? parseInt(String(limitRaw), 10) : 100;
|
|
36
|
+
if (!Number.isFinite(limit) || limit <= 0) {
|
|
37
|
+
printError(`Invalid --limit: "${limitRaw}". Must be a positive integer.`);
|
|
38
|
+
process.exit(1);
|
|
75
39
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
printError(`Process ${id} not found.`);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
console.log(`Process #${proc.id}`);
|
|
89
|
-
console.log(` name: ${proc.processName}`);
|
|
90
|
-
console.log(` status: ${proc.status}`);
|
|
91
|
-
console.log(` version: ${proc.version}`);
|
|
92
|
-
if (proc.description)
|
|
93
|
-
console.log(` description: ${proc.description}`);
|
|
94
|
-
if (proc.steps.length > 0) {
|
|
95
|
-
console.log(` steps:`);
|
|
96
|
-
proc.steps.forEach((s, i) => console.log(` ${i + 1}. ${s}`));
|
|
97
|
-
}
|
|
98
|
-
if (proc.changeSummary)
|
|
99
|
-
console.log(` change_summary: ${proc.changeSummary}`);
|
|
100
|
-
if (proc.supersededBy !== null)
|
|
101
|
-
console.log(` superseded_by: #${proc.supersededBy}`);
|
|
102
|
-
if (proc.supersededAt)
|
|
103
|
-
console.log(` superseded_at: ${proc.supersededAt}`);
|
|
104
|
-
if (proc.closedAt)
|
|
105
|
-
console.log(` closed_at: ${proc.closedAt}`);
|
|
106
|
-
if (proc.memoryId)
|
|
107
|
-
console.log(` memory: ${proc.memoryId}`);
|
|
108
|
-
console.log(` created: ${proc.createdAt}`);
|
|
109
|
-
return;
|
|
40
|
+
return limit;
|
|
41
|
+
}
|
|
42
|
+
function processList(hippoRoot, tenantId, flags) {
|
|
43
|
+
const statusRaw = flags['status'];
|
|
44
|
+
const status = typeof statusRaw === 'string' ? statusRaw.trim() : 'all';
|
|
45
|
+
const limit = parseListLimit(flags);
|
|
46
|
+
let results;
|
|
47
|
+
if (status === 'all') {
|
|
48
|
+
results = processesModule.loadProcesses(hippoRoot, tenantId, { limit });
|
|
110
49
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
printError('Usage: hippo process supersede <id> --step "<text>" [--step ...] [--change "<summary>"] [--description "<text>"]');
|
|
50
|
+
else {
|
|
51
|
+
if (!processesModule.VALID_PROCESS_STATES.has(status)) {
|
|
52
|
+
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
115
53
|
process.exit(1);
|
|
116
54
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
printError('hippo process supersede requires at least one --step "<text>" for the new version.');
|
|
121
|
-
process.exit(1);
|
|
122
|
-
}
|
|
123
|
-
// A supersession is a new version of the SAME process, so the new row reuses
|
|
124
|
-
// the predecessor's name (stable identity across versions). loadProcessById
|
|
125
|
-
// gives an early not-found before the write; saveProcess's in-SAVEPOINT
|
|
126
|
-
// preflight is the authoritative active-state check.
|
|
127
|
-
const existing = processesModule.loadProcessById(hippoRoot, tenantId, id);
|
|
128
|
-
if (!existing) {
|
|
129
|
-
printError(`Process ${id} not found.`);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
const changeRaw = flags['change'];
|
|
133
|
-
const changeSummary = typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined;
|
|
134
|
-
const descRaw = flags['description'];
|
|
135
|
-
const description = typeof descRaw === 'string' && descRaw ? descRaw : undefined;
|
|
136
|
-
const procPathTags = extractPathTags(process.cwd());
|
|
137
|
-
const created = processesModule.saveProcess(hippoRoot, tenantId, {
|
|
138
|
-
processName: existing.processName,
|
|
139
|
-
steps,
|
|
140
|
-
description,
|
|
141
|
-
changeSummary,
|
|
142
|
-
supersedesProcessId: id,
|
|
143
|
-
extraTags: procPathTags,
|
|
55
|
+
results = processesModule.loadProcesses(hippoRoot, tenantId, {
|
|
56
|
+
status: status,
|
|
57
|
+
limit,
|
|
144
58
|
});
|
|
145
|
-
console.log(`Process #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
146
|
-
if (created.memoryId)
|
|
147
|
-
console.log(` memory: ${created.memoryId}`);
|
|
148
|
-
return;
|
|
149
59
|
}
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
if (!idRaw) {
|
|
153
|
-
printError('Usage: hippo process close <id>');
|
|
154
|
-
process.exit(1);
|
|
155
|
-
}
|
|
156
|
-
const id = parsePositiveProcessId(idRaw);
|
|
157
|
-
const closed = processesModule.closeProcess(hippoRoot, tenantId, id);
|
|
158
|
-
console.log(`Process #${closed.id} closed.`);
|
|
60
|
+
if (results.length === 0) {
|
|
61
|
+
console.log('No processes.');
|
|
159
62
|
return;
|
|
160
63
|
}
|
|
64
|
+
console.log(`Found ${results.length} processes:\n`);
|
|
65
|
+
for (const proc of results) {
|
|
66
|
+
console.log(`#${proc.id} [${proc.status}] v${proc.version} steps=${proc.steps.length} memory=${proc.memoryId ?? '-'}`);
|
|
67
|
+
console.log(` ${proc.processName}`);
|
|
68
|
+
if (proc.changeSummary)
|
|
69
|
+
console.log(` change: ${proc.changeSummary}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function processGet(hippoRoot, tenantId, args) {
|
|
73
|
+
const idRaw = args[1];
|
|
74
|
+
if (!idRaw) {
|
|
75
|
+
printError('Usage: hippo process get <id>');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const id = parsePositiveProcessId(idRaw);
|
|
79
|
+
const proc = processesModule.loadProcessById(hippoRoot, tenantId, id);
|
|
80
|
+
if (!proc) {
|
|
81
|
+
printError(`Process ${id} not found.`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
console.log(`Process #${proc.id}`);
|
|
85
|
+
console.log(` name: ${proc.processName}`);
|
|
86
|
+
console.log(` status: ${proc.status}`);
|
|
87
|
+
console.log(` version: ${proc.version}`);
|
|
88
|
+
if (proc.description)
|
|
89
|
+
console.log(` description: ${proc.description}`);
|
|
90
|
+
if (proc.steps.length > 0) {
|
|
91
|
+
console.log(` steps:`);
|
|
92
|
+
proc.steps.forEach((s, i) => console.log(` ${i + 1}. ${s}`));
|
|
93
|
+
}
|
|
94
|
+
if (proc.changeSummary)
|
|
95
|
+
console.log(` change_summary: ${proc.changeSummary}`);
|
|
96
|
+
if (proc.supersededBy !== null)
|
|
97
|
+
console.log(` superseded_by: #${proc.supersededBy}`);
|
|
98
|
+
if (proc.supersededAt)
|
|
99
|
+
console.log(` superseded_at: ${proc.supersededAt}`);
|
|
100
|
+
if (proc.closedAt)
|
|
101
|
+
console.log(` closed_at: ${proc.closedAt}`);
|
|
102
|
+
if (proc.memoryId)
|
|
103
|
+
console.log(` memory: ${proc.memoryId}`);
|
|
104
|
+
console.log(` created: ${proc.createdAt}`);
|
|
105
|
+
}
|
|
106
|
+
function processSupersede(hippoRoot, tenantId, args, flags) {
|
|
107
|
+
const idRaw = args[1];
|
|
108
|
+
if (!idRaw) {
|
|
109
|
+
printError('Usage: hippo process supersede <id> --step "<text>" [--step ...] [--change "<summary>"] [--description "<text>"]');
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
const id = parsePositiveProcessId(idRaw);
|
|
113
|
+
const steps = collectProcessSteps(flags['step']);
|
|
114
|
+
if (steps.length === 0) {
|
|
115
|
+
printError('hippo process supersede requires at least one --step "<text>" for the new version.');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
// A supersession is a new version of the SAME process, so the new row reuses the predecessor's name (stable identity
|
|
119
|
+
// across versions). loadProcessById gives an early not-found before the write; saveProcess's in-SAVEPOINT preflight
|
|
120
|
+
// is the authoritative active-state check.
|
|
121
|
+
const existing = processesModule.loadProcessById(hippoRoot, tenantId, id);
|
|
122
|
+
if (!existing) {
|
|
123
|
+
printError(`Process ${id} not found.`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
const changeRaw = flags['change'];
|
|
127
|
+
const changeSummary = typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined;
|
|
128
|
+
const descRaw = flags['description'];
|
|
129
|
+
const description = typeof descRaw === 'string' && descRaw ? descRaw : undefined;
|
|
130
|
+
const procPathTags = extractPathTags(process.cwd());
|
|
131
|
+
const created = processesModule.saveProcess(hippoRoot, tenantId, {
|
|
132
|
+
processName: existing.processName,
|
|
133
|
+
steps,
|
|
134
|
+
description,
|
|
135
|
+
changeSummary,
|
|
136
|
+
supersedesProcessId: id,
|
|
137
|
+
extraTags: procPathTags,
|
|
138
|
+
});
|
|
139
|
+
console.log(`Process #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
140
|
+
if (created.memoryId)
|
|
141
|
+
console.log(` memory: ${created.memoryId}`);
|
|
142
|
+
}
|
|
143
|
+
function processClose(hippoRoot, tenantId, args) {
|
|
144
|
+
const idRaw = args[1];
|
|
145
|
+
if (!idRaw) {
|
|
146
|
+
printError('Usage: hippo process close <id>');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const id = parsePositiveProcessId(idRaw);
|
|
150
|
+
const closed = processesModule.closeProcess(hippoRoot, tenantId, id);
|
|
151
|
+
console.log(`Process #${closed.id} closed.`);
|
|
152
|
+
}
|
|
153
|
+
export function cmdProcess(hippoRoot, args, flags) {
|
|
154
|
+
requireInit(hippoRoot);
|
|
155
|
+
const tenantId = resolveTenantId({});
|
|
156
|
+
const subcommand = args[0] ?? '';
|
|
157
|
+
if (subcommand === 'list')
|
|
158
|
+
return processList(hippoRoot, tenantId, flags);
|
|
159
|
+
if (subcommand === 'get')
|
|
160
|
+
return processGet(hippoRoot, tenantId, args);
|
|
161
|
+
if (subcommand === 'supersede')
|
|
162
|
+
return processSupersede(hippoRoot, tenantId, args, flags);
|
|
163
|
+
if (subcommand === 'close')
|
|
164
|
+
return processClose(hippoRoot, tenantId, args);
|
|
161
165
|
// Default subcommand: new (create). Accept both the documented
|
|
162
166
|
// `process new "<name>"` form and the bare `process "<name>"` form: for the
|
|
163
167
|
// `new` keyword the name is args[1], otherwise args[0] IS the name.
|
|
164
|
-
|
|
168
|
+
processCreate(hippoRoot, tenantId, subcommand === 'new' ? (args[1] ?? '') : subcommand, flags);
|
|
169
|
+
}
|
|
170
|
+
function processCreate(hippoRoot, tenantId, processName, flags) {
|
|
165
171
|
if (!processName) {
|
|
166
172
|
printError('Usage: hippo process new "<name>" --step "<text>" [--step ...] [--description "<text>"]');
|
|
167
173
|
printError(' hippo process list [--status active|superseded|closed|all] [--limit N]');
|
|
@@ -184,8 +190,7 @@ export function cmdProcess(hippoRoot, args, flags) {
|
|
|
184
190
|
if (created.memoryId)
|
|
185
191
|
console.log(` memory: ${created.memoryId}`);
|
|
186
192
|
}
|
|
187
|
-
// Strict positive-integer id parse for the mutating policy subcommands
|
|
188
|
-
// parsePositiveProcessId; codex P2 class - parseInt alone accepts '1abc' -> 1).
|
|
193
|
+
// Strict positive-integer id parse for the mutating policy subcommands: parseInt alone accepts '1abc' -> 1.
|
|
189
194
|
function parsePositivePolicyId(idRaw) {
|
|
190
195
|
const s = String(idRaw ?? '').trim();
|
|
191
196
|
const id = parseInt(s, 10);
|
|
@@ -202,150 +207,154 @@ function printPolicyRow(p) {
|
|
|
202
207
|
if (p.changeSummary)
|
|
203
208
|
console.log(` change: ${p.changeSummary}`);
|
|
204
209
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const limitRaw = flags['limit'];
|
|
213
|
-
const limit = limitRaw !== undefined ? parseInt(String(limitRaw), 10) : 100;
|
|
214
|
-
if (!Number.isFinite(limit) || limit <= 0) {
|
|
215
|
-
printError(`Invalid --limit: "${limitRaw}". Must be a positive integer.`);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
let results;
|
|
219
|
-
if (status === 'all') {
|
|
220
|
-
results = policiesModule.loadPolicies(hippoRoot, tenantId, { limit });
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
if (!policiesModule.VALID_POLICY_STATES.has(status)) {
|
|
224
|
-
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
225
|
-
process.exit(1);
|
|
226
|
-
}
|
|
227
|
-
results = policiesModule.loadPolicies(hippoRoot, tenantId, {
|
|
228
|
-
status: status,
|
|
229
|
-
limit,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
if (results.length === 0) {
|
|
233
|
-
console.log('No policies.');
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
console.log(`Found ${results.length} policies:\n`);
|
|
237
|
-
for (const p of results)
|
|
238
|
-
printPolicyRow(p);
|
|
239
|
-
return;
|
|
210
|
+
function policyList(hippoRoot, tenantId, flags) {
|
|
211
|
+
const statusRaw = flags['status'];
|
|
212
|
+
const status = typeof statusRaw === 'string' ? statusRaw.trim() : 'all';
|
|
213
|
+
const limit = parseListLimit(flags);
|
|
214
|
+
let results;
|
|
215
|
+
if (status === 'all') {
|
|
216
|
+
results = policiesModule.loadPolicies(hippoRoot, tenantId, { limit });
|
|
240
217
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
printError('Usage: hippo policy asof <iso-date> [--name "<policy>"]');
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
const nameRaw = flags['name'];
|
|
248
|
-
const name = typeof nameRaw === 'string' && nameRaw ? nameRaw : undefined;
|
|
249
|
-
let results;
|
|
250
|
-
try {
|
|
251
|
-
results = policiesModule.loadPoliciesAsOf(hippoRoot, tenantId, dateRaw, { name });
|
|
252
|
-
}
|
|
253
|
-
catch (e) {
|
|
254
|
-
printError(e.message);
|
|
218
|
+
else {
|
|
219
|
+
if (!policiesModule.VALID_POLICY_STATES.has(status)) {
|
|
220
|
+
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
255
221
|
process.exit(1);
|
|
256
222
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
console.log(`Policies in force at ${dateRaw}:\n`);
|
|
262
|
-
for (const p of results)
|
|
263
|
-
printPolicyRow(p);
|
|
264
|
-
return;
|
|
223
|
+
results = policiesModule.loadPolicies(hippoRoot, tenantId, {
|
|
224
|
+
status: status,
|
|
225
|
+
limit,
|
|
226
|
+
});
|
|
265
227
|
}
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
if (!idRaw) {
|
|
269
|
-
printError('Usage: hippo policy get <id>');
|
|
270
|
-
process.exit(1);
|
|
271
|
-
}
|
|
272
|
-
const id = parsePositivePolicyId(idRaw);
|
|
273
|
-
const p = policiesModule.loadPolicyById(hippoRoot, tenantId, id);
|
|
274
|
-
if (!p) {
|
|
275
|
-
printError(`Policy ${id} not found.`);
|
|
276
|
-
process.exit(1);
|
|
277
|
-
}
|
|
278
|
-
console.log(`Policy #${p.id}`);
|
|
279
|
-
console.log(` name: ${p.policyName}`);
|
|
280
|
-
console.log(` text: ${p.policyText}`);
|
|
281
|
-
console.log(` status: ${p.status}`);
|
|
282
|
-
console.log(` version: ${p.version}`);
|
|
283
|
-
console.log(` valid_from: ${p.validFrom}`);
|
|
284
|
-
console.log(` valid_to: ${p.validTo ?? '(open-ended)'}`);
|
|
285
|
-
if (p.changeSummary)
|
|
286
|
-
console.log(` change_summary: ${p.changeSummary}`);
|
|
287
|
-
if (p.supersededBy !== null)
|
|
288
|
-
console.log(` superseded_by: #${p.supersededBy}`);
|
|
289
|
-
if (p.supersededAt)
|
|
290
|
-
console.log(` superseded_at: ${p.supersededAt}`);
|
|
291
|
-
if (p.closedAt)
|
|
292
|
-
console.log(` closed_at: ${p.closedAt}`);
|
|
293
|
-
if (p.memoryId)
|
|
294
|
-
console.log(` memory: ${p.memoryId}`);
|
|
295
|
-
console.log(` created: ${p.createdAt}`);
|
|
228
|
+
if (results.length === 0) {
|
|
229
|
+
console.log('No policies.');
|
|
296
230
|
return;
|
|
297
231
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
printError('hippo policy supersede requires --text "<rule>" for the new version.');
|
|
308
|
-
process.exit(1);
|
|
309
|
-
}
|
|
310
|
-
const existing = policiesModule.loadPolicyById(hippoRoot, tenantId, id);
|
|
311
|
-
if (!existing) {
|
|
312
|
-
printError(`Policy ${id} not found.`);
|
|
313
|
-
process.exit(1);
|
|
314
|
-
}
|
|
315
|
-
const fromRaw = flags['from'];
|
|
316
|
-
const toRaw = flags['to'];
|
|
317
|
-
const changeRaw = flags['change'];
|
|
318
|
-
try {
|
|
319
|
-
const created = policiesModule.savePolicy(hippoRoot, tenantId, {
|
|
320
|
-
policyName: existing.policyName,
|
|
321
|
-
policyText: textRaw,
|
|
322
|
-
validFrom: typeof fromRaw === 'string' && fromRaw ? fromRaw : undefined,
|
|
323
|
-
validTo: typeof toRaw === 'string' && toRaw ? toRaw : undefined,
|
|
324
|
-
changeSummary: typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined,
|
|
325
|
-
supersedesPolicyId: id,
|
|
326
|
-
extraTags: extractPathTags(process.cwd()),
|
|
327
|
-
});
|
|
328
|
-
console.log(`Policy #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
329
|
-
if (created.memoryId)
|
|
330
|
-
console.log(` memory: ${created.memoryId}`);
|
|
331
|
-
}
|
|
332
|
-
catch (e) {
|
|
333
|
-
printError(e.message);
|
|
334
|
-
process.exit(1);
|
|
335
|
-
}
|
|
336
|
-
return;
|
|
232
|
+
console.log(`Found ${results.length} policies:\n`);
|
|
233
|
+
for (const p of results)
|
|
234
|
+
printPolicyRow(p);
|
|
235
|
+
}
|
|
236
|
+
function policyAsOf(hippoRoot, tenantId, args, flags) {
|
|
237
|
+
const dateRaw = args[1];
|
|
238
|
+
if (!dateRaw) {
|
|
239
|
+
printError('Usage: hippo policy asof <iso-date> [--name "<policy>"]');
|
|
240
|
+
process.exit(1);
|
|
337
241
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
242
|
+
const nameRaw = flags['name'];
|
|
243
|
+
const name = typeof nameRaw === 'string' && nameRaw ? nameRaw : undefined;
|
|
244
|
+
let results;
|
|
245
|
+
try {
|
|
246
|
+
results = policiesModule.loadPoliciesAsOf(hippoRoot, tenantId, dateRaw, { name });
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
printError(e.message);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
if (results.length === 0) {
|
|
253
|
+
console.log(`No active policies in force at ${dateRaw}${name ? ` for "${name}"` : ''}.`);
|
|
347
254
|
return;
|
|
348
255
|
}
|
|
256
|
+
console.log(`Policies in force at ${dateRaw}:\n`);
|
|
257
|
+
for (const p of results)
|
|
258
|
+
printPolicyRow(p);
|
|
259
|
+
}
|
|
260
|
+
function policyGet(hippoRoot, tenantId, args) {
|
|
261
|
+
const idRaw = args[1];
|
|
262
|
+
if (!idRaw) {
|
|
263
|
+
printError('Usage: hippo policy get <id>');
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
const id = parsePositivePolicyId(idRaw);
|
|
267
|
+
const p = policiesModule.loadPolicyById(hippoRoot, tenantId, id);
|
|
268
|
+
if (!p) {
|
|
269
|
+
printError(`Policy ${id} not found.`);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
console.log(`Policy #${p.id}`);
|
|
273
|
+
console.log(` name: ${p.policyName}`);
|
|
274
|
+
console.log(` text: ${p.policyText}`);
|
|
275
|
+
console.log(` status: ${p.status}`);
|
|
276
|
+
console.log(` version: ${p.version}`);
|
|
277
|
+
console.log(` valid_from: ${p.validFrom}`);
|
|
278
|
+
console.log(` valid_to: ${p.validTo ?? '(open-ended)'}`);
|
|
279
|
+
if (p.changeSummary)
|
|
280
|
+
console.log(` change_summary: ${p.changeSummary}`);
|
|
281
|
+
if (p.supersededBy !== null)
|
|
282
|
+
console.log(` superseded_by: #${p.supersededBy}`);
|
|
283
|
+
if (p.supersededAt)
|
|
284
|
+
console.log(` superseded_at: ${p.supersededAt}`);
|
|
285
|
+
if (p.closedAt)
|
|
286
|
+
console.log(` closed_at: ${p.closedAt}`);
|
|
287
|
+
if (p.memoryId)
|
|
288
|
+
console.log(` memory: ${p.memoryId}`);
|
|
289
|
+
console.log(` created: ${p.createdAt}`);
|
|
290
|
+
}
|
|
291
|
+
function policySupersede(hippoRoot, tenantId, args, flags) {
|
|
292
|
+
const idRaw = args[1];
|
|
293
|
+
if (!idRaw) {
|
|
294
|
+
printError('Usage: hippo policy supersede <id> --text "<rule>" [--from <iso>] [--to <iso>] [--change "<summary>"]');
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
const id = parsePositivePolicyId(idRaw);
|
|
298
|
+
const textRaw = flags['text'];
|
|
299
|
+
if (typeof textRaw !== 'string' || !textRaw.trim()) {
|
|
300
|
+
printError('hippo policy supersede requires --text "<rule>" for the new version.');
|
|
301
|
+
process.exit(1);
|
|
302
|
+
}
|
|
303
|
+
const existing = policiesModule.loadPolicyById(hippoRoot, tenantId, id);
|
|
304
|
+
if (!existing) {
|
|
305
|
+
printError(`Policy ${id} not found.`);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
const fromRaw = flags['from'];
|
|
309
|
+
const toRaw = flags['to'];
|
|
310
|
+
const changeRaw = flags['change'];
|
|
311
|
+
try {
|
|
312
|
+
const created = policiesModule.savePolicy(hippoRoot, tenantId, {
|
|
313
|
+
policyName: existing.policyName,
|
|
314
|
+
policyText: textRaw,
|
|
315
|
+
validFrom: typeof fromRaw === 'string' && fromRaw ? fromRaw : undefined,
|
|
316
|
+
validTo: typeof toRaw === 'string' && toRaw ? toRaw : undefined,
|
|
317
|
+
changeSummary: typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined,
|
|
318
|
+
supersedesPolicyId: id,
|
|
319
|
+
extraTags: extractPathTags(process.cwd()),
|
|
320
|
+
});
|
|
321
|
+
console.log(`Policy #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
322
|
+
if (created.memoryId)
|
|
323
|
+
console.log(` memory: ${created.memoryId}`);
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
printError(e.message);
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function policyClose(hippoRoot, tenantId, args) {
|
|
331
|
+
const idRaw = args[1];
|
|
332
|
+
if (!idRaw) {
|
|
333
|
+
printError('Usage: hippo policy close <id>');
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
|
336
|
+
const id = parsePositivePolicyId(idRaw);
|
|
337
|
+
const closed = policiesModule.closePolicy(hippoRoot, tenantId, id);
|
|
338
|
+
console.log(`Policy #${closed.id} closed.`);
|
|
339
|
+
}
|
|
340
|
+
export function cmdPolicy(hippoRoot, args, flags) {
|
|
341
|
+
requireInit(hippoRoot);
|
|
342
|
+
const tenantId = resolveTenantId({});
|
|
343
|
+
const subcommand = args[0] ?? '';
|
|
344
|
+
if (subcommand === 'list')
|
|
345
|
+
return policyList(hippoRoot, tenantId, flags);
|
|
346
|
+
if (subcommand === 'asof')
|
|
347
|
+
return policyAsOf(hippoRoot, tenantId, args, flags);
|
|
348
|
+
if (subcommand === 'get')
|
|
349
|
+
return policyGet(hippoRoot, tenantId, args);
|
|
350
|
+
if (subcommand === 'supersede')
|
|
351
|
+
return policySupersede(hippoRoot, tenantId, args, flags);
|
|
352
|
+
if (subcommand === 'close')
|
|
353
|
+
return policyClose(hippoRoot, tenantId, args);
|
|
354
|
+
policyCreate(hippoRoot, tenantId, args, flags);
|
|
355
|
+
}
|
|
356
|
+
function policyCreate(hippoRoot, tenantId, args, flags) {
|
|
357
|
+
const subcommand = args[0] ?? '';
|
|
349
358
|
// Default subcommand: new (create). Accept both `policy new "<name>"` and the
|
|
350
359
|
// bare `policy "<name>"` form: for the `new` keyword the name is args[1].
|
|
351
360
|
const policyName = subcommand === 'new' ? (args[1] ?? '') : subcommand;
|
|
@@ -379,8 +388,7 @@ export function cmdPolicy(hippoRoot, args, flags) {
|
|
|
379
388
|
process.exit(1);
|
|
380
389
|
}
|
|
381
390
|
}
|
|
382
|
-
// Strict positive-integer id parse for the mutating skill subcommands
|
|
383
|
-
// parsePositivePolicyId; codex P2 class - parseInt accepts '1abc' -> 1).
|
|
391
|
+
// Strict positive-integer id parse for the mutating skill subcommands: parseInt accepts '1abc' -> 1.
|
|
384
392
|
function parsePositiveSkillId(idRaw) {
|
|
385
393
|
const s = String(idRaw ?? '').trim();
|
|
386
394
|
const id = parseInt(s, 10);
|
|
@@ -397,132 +405,136 @@ function printSkillRow(s) {
|
|
|
397
405
|
if (s.changeSummary)
|
|
398
406
|
console.log(` change: ${s.changeSummary}`);
|
|
399
407
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (!
|
|
410
|
-
printError(`Invalid --
|
|
408
|
+
function skillList(hippoRoot, tenantId, flags) {
|
|
409
|
+
const statusRaw = flags['status'];
|
|
410
|
+
const status = typeof statusRaw === 'string' ? statusRaw.trim() : 'all';
|
|
411
|
+
const limit = parseListLimit(flags);
|
|
412
|
+
let results;
|
|
413
|
+
if (status === 'all') {
|
|
414
|
+
results = skillsModule.loadSkills(hippoRoot, tenantId, { limit });
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
if (!skillsModule.VALID_SKILL_STATES.has(status)) {
|
|
418
|
+
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
411
419
|
process.exit(1);
|
|
412
420
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
if (!skillsModule.VALID_SKILL_STATES.has(status)) {
|
|
419
|
-
printError(`Invalid --status: "${status}". Must be one of: active | superseded | closed | all.`);
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
results = skillsModule.loadSkills(hippoRoot, tenantId, {
|
|
423
|
-
status: status,
|
|
424
|
-
limit,
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
if (results.length === 0) {
|
|
428
|
-
console.log('No skills.');
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
console.log(`Found ${results.length} skills:\n`);
|
|
432
|
-
for (const s of results)
|
|
433
|
-
printSkillRow(s);
|
|
434
|
-
return;
|
|
421
|
+
results = skillsModule.loadSkills(hippoRoot, tenantId, {
|
|
422
|
+
status: status,
|
|
423
|
+
limit,
|
|
424
|
+
});
|
|
435
425
|
}
|
|
436
|
-
if (
|
|
437
|
-
|
|
438
|
-
if (!md) {
|
|
439
|
-
console.log('No active skills.');
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
console.log(md);
|
|
426
|
+
if (results.length === 0) {
|
|
427
|
+
console.log('No skills.');
|
|
443
428
|
return;
|
|
444
429
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (!s) {
|
|
454
|
-
printError(`Skill ${id} not found.`);
|
|
455
|
-
process.exit(1);
|
|
456
|
-
}
|
|
457
|
-
console.log(`Skill #${s.id}`);
|
|
458
|
-
console.log(` name: ${s.skillName}`);
|
|
459
|
-
console.log(` status: ${s.status}`);
|
|
460
|
-
console.log(` version: ${s.version}`);
|
|
461
|
-
if (s.trigger)
|
|
462
|
-
console.log(` when: ${s.trigger}`);
|
|
463
|
-
console.log(` instructions: ${s.instructions}`);
|
|
464
|
-
if (s.changeSummary)
|
|
465
|
-
console.log(` change_summary: ${s.changeSummary}`);
|
|
466
|
-
if (s.supersededBy !== null)
|
|
467
|
-
console.log(` superseded_by: #${s.supersededBy}`);
|
|
468
|
-
if (s.supersededAt)
|
|
469
|
-
console.log(` superseded_at: ${s.supersededAt}`);
|
|
470
|
-
if (s.closedAt)
|
|
471
|
-
console.log(` closed_at: ${s.closedAt}`);
|
|
472
|
-
if (s.memoryId)
|
|
473
|
-
console.log(` memory: ${s.memoryId}`);
|
|
474
|
-
console.log(` created: ${s.createdAt}`);
|
|
430
|
+
console.log(`Found ${results.length} skills:\n`);
|
|
431
|
+
for (const s of results)
|
|
432
|
+
printSkillRow(s);
|
|
433
|
+
}
|
|
434
|
+
function skillExport(hippoRoot, tenantId) {
|
|
435
|
+
const md = skillsModule.exportSkills(hippoRoot, tenantId);
|
|
436
|
+
if (!md) {
|
|
437
|
+
console.log('No active skills.');
|
|
475
438
|
return;
|
|
476
439
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const instrRaw = flags['instructions'];
|
|
485
|
-
if (typeof instrRaw !== 'string' || !instrRaw.trim()) {
|
|
486
|
-
printError('hippo skill supersede requires --instructions "<text>" for the new version.');
|
|
487
|
-
process.exit(1);
|
|
488
|
-
}
|
|
489
|
-
const existing = skillsModule.loadSkillById(hippoRoot, tenantId, id);
|
|
490
|
-
if (!existing) {
|
|
491
|
-
printError(`Skill ${id} not found.`);
|
|
492
|
-
process.exit(1);
|
|
493
|
-
}
|
|
494
|
-
const trigRaw = flags['trigger'];
|
|
495
|
-
const changeRaw = flags['change'];
|
|
496
|
-
try {
|
|
497
|
-
const created = skillsModule.saveSkill(hippoRoot, tenantId, {
|
|
498
|
-
skillName: existing.skillName,
|
|
499
|
-
instructions: instrRaw,
|
|
500
|
-
trigger: typeof trigRaw === 'string' && trigRaw ? trigRaw : undefined,
|
|
501
|
-
changeSummary: typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined,
|
|
502
|
-
supersedesSkillId: id,
|
|
503
|
-
extraTags: extractPathTags(process.cwd()),
|
|
504
|
-
});
|
|
505
|
-
console.log(`Skill #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
506
|
-
if (created.memoryId)
|
|
507
|
-
console.log(` memory: ${created.memoryId}`);
|
|
508
|
-
}
|
|
509
|
-
catch (e) {
|
|
510
|
-
printError(e.message);
|
|
511
|
-
process.exit(1);
|
|
512
|
-
}
|
|
513
|
-
return;
|
|
440
|
+
console.log(md);
|
|
441
|
+
}
|
|
442
|
+
function skillGet(hippoRoot, tenantId, args) {
|
|
443
|
+
const idRaw = args[1];
|
|
444
|
+
if (!idRaw) {
|
|
445
|
+
printError('Usage: hippo skill get <id>');
|
|
446
|
+
process.exit(1);
|
|
514
447
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
448
|
+
const id = parsePositiveSkillId(idRaw);
|
|
449
|
+
const s = skillsModule.loadSkillById(hippoRoot, tenantId, id);
|
|
450
|
+
if (!s) {
|
|
451
|
+
printError(`Skill ${id} not found.`);
|
|
452
|
+
process.exit(1);
|
|
453
|
+
}
|
|
454
|
+
console.log(`Skill #${s.id}`);
|
|
455
|
+
console.log(` name: ${s.skillName}`);
|
|
456
|
+
console.log(` status: ${s.status}`);
|
|
457
|
+
console.log(` version: ${s.version}`);
|
|
458
|
+
if (s.trigger)
|
|
459
|
+
console.log(` when: ${s.trigger}`);
|
|
460
|
+
console.log(` instructions: ${s.instructions}`);
|
|
461
|
+
if (s.changeSummary)
|
|
462
|
+
console.log(` change_summary: ${s.changeSummary}`);
|
|
463
|
+
if (s.supersededBy !== null)
|
|
464
|
+
console.log(` superseded_by: #${s.supersededBy}`);
|
|
465
|
+
if (s.supersededAt)
|
|
466
|
+
console.log(` superseded_at: ${s.supersededAt}`);
|
|
467
|
+
if (s.closedAt)
|
|
468
|
+
console.log(` closed_at: ${s.closedAt}`);
|
|
469
|
+
if (s.memoryId)
|
|
470
|
+
console.log(` memory: ${s.memoryId}`);
|
|
471
|
+
console.log(` created: ${s.createdAt}`);
|
|
472
|
+
}
|
|
473
|
+
function skillSupersede(hippoRoot, tenantId, args, flags) {
|
|
474
|
+
const idRaw = args[1];
|
|
475
|
+
if (!idRaw) {
|
|
476
|
+
printError('Usage: hippo skill supersede <id> --instructions "<text>" [--trigger "<when>"] [--change "<summary>"]');
|
|
477
|
+
process.exit(1);
|
|
478
|
+
}
|
|
479
|
+
const id = parsePositiveSkillId(idRaw);
|
|
480
|
+
const instrRaw = flags['instructions'];
|
|
481
|
+
if (typeof instrRaw !== 'string' || !instrRaw.trim()) {
|
|
482
|
+
printError('hippo skill supersede requires --instructions "<text>" for the new version.');
|
|
483
|
+
process.exit(1);
|
|
525
484
|
}
|
|
485
|
+
const existing = skillsModule.loadSkillById(hippoRoot, tenantId, id);
|
|
486
|
+
if (!existing) {
|
|
487
|
+
printError(`Skill ${id} not found.`);
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
const trigRaw = flags['trigger'];
|
|
491
|
+
const changeRaw = flags['change'];
|
|
492
|
+
try {
|
|
493
|
+
const created = skillsModule.saveSkill(hippoRoot, tenantId, {
|
|
494
|
+
skillName: existing.skillName,
|
|
495
|
+
instructions: instrRaw,
|
|
496
|
+
trigger: typeof trigRaw === 'string' && trigRaw ? trigRaw : undefined,
|
|
497
|
+
changeSummary: typeof changeRaw === 'string' && changeRaw ? changeRaw : undefined,
|
|
498
|
+
supersedesSkillId: id,
|
|
499
|
+
extraTags: extractPathTags(process.cwd()),
|
|
500
|
+
});
|
|
501
|
+
console.log(`Skill #${created.id} recorded (v${created.version}), superseding #${id}.`);
|
|
502
|
+
if (created.memoryId)
|
|
503
|
+
console.log(` memory: ${created.memoryId}`);
|
|
504
|
+
}
|
|
505
|
+
catch (e) {
|
|
506
|
+
printError(e.message);
|
|
507
|
+
process.exit(1);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function skillClose(hippoRoot, tenantId, args) {
|
|
511
|
+
const idRaw = args[1];
|
|
512
|
+
if (!idRaw) {
|
|
513
|
+
printError('Usage: hippo skill close <id>');
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
const id = parsePositiveSkillId(idRaw);
|
|
517
|
+
const closed = skillsModule.closeSkill(hippoRoot, tenantId, id);
|
|
518
|
+
console.log(`Skill #${closed.id} closed.`);
|
|
519
|
+
}
|
|
520
|
+
export function cmdSkill(hippoRoot, args, flags) {
|
|
521
|
+
requireInit(hippoRoot);
|
|
522
|
+
const tenantId = resolveTenantId({});
|
|
523
|
+
const subcommand = args[0] ?? '';
|
|
524
|
+
if (subcommand === 'list')
|
|
525
|
+
return skillList(hippoRoot, tenantId, flags);
|
|
526
|
+
if (subcommand === 'export')
|
|
527
|
+
return skillExport(hippoRoot, tenantId);
|
|
528
|
+
if (subcommand === 'get')
|
|
529
|
+
return skillGet(hippoRoot, tenantId, args);
|
|
530
|
+
if (subcommand === 'supersede')
|
|
531
|
+
return skillSupersede(hippoRoot, tenantId, args, flags);
|
|
532
|
+
if (subcommand === 'close')
|
|
533
|
+
return skillClose(hippoRoot, tenantId, args);
|
|
534
|
+
skillCreate(hippoRoot, tenantId, args, flags);
|
|
535
|
+
}
|
|
536
|
+
function skillCreate(hippoRoot, tenantId, args, flags) {
|
|
537
|
+
const subcommand = args[0] ?? '';
|
|
526
538
|
// Default subcommand: new (create). Accept both `skill new "<name>"` and the
|
|
527
539
|
// bare `skill "<name>"` form: for the `new` keyword the name is args[1].
|
|
528
540
|
const skillName = subcommand === 'new' ? (args[1] ?? '') : subcommand;
|