agent-recall-core 3.4.18 → 3.4.21
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 +404 -981
- package/dist/index.d.ts +45 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/dist/naming.d.ts +109 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +198 -0
- package/dist/naming.js.map +1 -0
- package/dist/palace/awareness.d.ts +6 -0
- package/dist/palace/awareness.d.ts.map +1 -1
- package/dist/palace/awareness.js +19 -0
- package/dist/palace/awareness.js.map +1 -1
- package/dist/palace/fsrs.d.ts +64 -0
- package/dist/palace/fsrs.d.ts.map +1 -0
- package/dist/palace/fsrs.js +86 -0
- package/dist/palace/fsrs.js.map +1 -0
- package/dist/palace/hopfield.d.ts +108 -0
- package/dist/palace/hopfield.d.ts.map +1 -0
- package/dist/palace/hopfield.js +237 -0
- package/dist/palace/hopfield.js.map +1 -0
- package/dist/palace/obsidian.d.ts.map +1 -1
- package/dist/palace/obsidian.js +25 -1
- package/dist/palace/obsidian.js.map +1 -1
- package/dist/palace/pipeline.d.ts +61 -0
- package/dist/palace/pipeline.d.ts.map +1 -0
- package/dist/palace/pipeline.js +289 -0
- package/dist/palace/pipeline.js.map +1 -0
- package/dist/palace/skills.d.ts +71 -0
- package/dist/palace/skills.d.ts.map +1 -0
- package/dist/palace/skills.js +225 -0
- package/dist/palace/skills.js.map +1 -0
- package/dist/storage/behavior-policies.d.ts +54 -0
- package/dist/storage/behavior-policies.d.ts.map +1 -0
- package/dist/storage/behavior-policies.js +98 -0
- package/dist/storage/behavior-policies.js.map +1 -0
- package/dist/storage/corrections.d.ts +54 -0
- package/dist/storage/corrections.d.ts.map +1 -1
- package/dist/storage/corrections.js +93 -4
- package/dist/storage/corrections.js.map +1 -1
- package/dist/storage/cwd-allowlist.d.ts +33 -0
- package/dist/storage/cwd-allowlist.d.ts.map +1 -0
- package/dist/storage/cwd-allowlist.js +106 -0
- package/dist/storage/cwd-allowlist.js.map +1 -0
- package/dist/storage/dream-health.d.ts +19 -0
- package/dist/storage/dream-health.d.ts.map +1 -0
- package/dist/storage/dream-health.js +79 -0
- package/dist/storage/dream-health.js.map +1 -0
- package/dist/storage/paths.d.ts +12 -0
- package/dist/storage/paths.d.ts.map +1 -1
- package/dist/storage/paths.js +37 -15
- package/dist/storage/paths.js.map +1 -1
- package/dist/storage/project.d.ts +6 -0
- package/dist/storage/project.d.ts.map +1 -1
- package/dist/storage/project.js +26 -1
- package/dist/storage/project.js.map +1 -1
- package/dist/storage/session.d.ts.map +1 -1
- package/dist/storage/session.js +16 -1
- package/dist/storage/session.js.map +1 -1
- package/dist/tools-logic/bootstrap.d.ts.map +1 -1
- package/dist/tools-logic/bootstrap.js +69 -6
- package/dist/tools-logic/bootstrap.js.map +1 -1
- package/dist/tools-logic/check-action.d.ts +55 -0
- package/dist/tools-logic/check-action.d.ts.map +1 -0
- package/dist/tools-logic/check-action.js +152 -0
- package/dist/tools-logic/check-action.js.map +1 -0
- package/dist/tools-logic/dashboard-export.d.ts +75 -0
- package/dist/tools-logic/dashboard-export.d.ts.map +1 -0
- package/dist/tools-logic/dashboard-export.js +271 -0
- package/dist/tools-logic/dashboard-export.js.map +1 -0
- package/dist/tools-logic/pipeline-close.d.ts +22 -0
- package/dist/tools-logic/pipeline-close.d.ts.map +1 -0
- package/dist/tools-logic/pipeline-close.js +66 -0
- package/dist/tools-logic/pipeline-close.js.map +1 -0
- package/dist/tools-logic/pipeline-current.d.ts +11 -0
- package/dist/tools-logic/pipeline-current.d.ts.map +1 -0
- package/dist/tools-logic/pipeline-current.js +8 -0
- package/dist/tools-logic/pipeline-current.js.map +1 -0
- package/dist/tools-logic/pipeline-list.d.ts +11 -0
- package/dist/tools-logic/pipeline-list.d.ts.map +1 -0
- package/dist/tools-logic/pipeline-list.js +8 -0
- package/dist/tools-logic/pipeline-list.js.map +1 -0
- package/dist/tools-logic/pipeline-open.d.ts +23 -0
- package/dist/tools-logic/pipeline-open.d.ts.map +1 -0
- package/dist/tools-logic/pipeline-open.js +109 -0
- package/dist/tools-logic/pipeline-open.js.map +1 -0
- package/dist/tools-logic/pipeline-show.d.ts +34 -0
- package/dist/tools-logic/pipeline-show.d.ts.map +1 -0
- package/dist/tools-logic/pipeline-show.js +134 -0
- package/dist/tools-logic/pipeline-show.js.map +1 -0
- package/dist/tools-logic/register-rule.d.ts +15 -0
- package/dist/tools-logic/register-rule.d.ts.map +1 -0
- package/dist/tools-logic/register-rule.js +13 -0
- package/dist/tools-logic/register-rule.js.map +1 -0
- package/dist/tools-logic/session-end-reflect.d.ts +57 -0
- package/dist/tools-logic/session-end-reflect.d.ts.map +1 -0
- package/dist/tools-logic/session-end-reflect.js +117 -0
- package/dist/tools-logic/session-end-reflect.js.map +1 -0
- package/dist/tools-logic/session-end.d.ts +29 -0
- package/dist/tools-logic/session-end.d.ts.map +1 -1
- package/dist/tools-logic/session-end.js +34 -0
- package/dist/tools-logic/session-end.js.map +1 -1
- package/dist/tools-logic/session-start-lite.d.ts +26 -0
- package/dist/tools-logic/session-start-lite.d.ts.map +1 -0
- package/dist/tools-logic/session-start-lite.js +46 -0
- package/dist/tools-logic/session-start-lite.js.map +1 -0
- package/dist/tools-logic/session-start.d.ts +26 -0
- package/dist/tools-logic/session-start.d.ts.map +1 -1
- package/dist/tools-logic/session-start.js +53 -7
- package/dist/tools-logic/session-start.js.map +1 -1
- package/dist/tools-logic/skill-list.d.ts +19 -0
- package/dist/tools-logic/skill-list.d.ts.map +1 -0
- package/dist/tools-logic/skill-list.js +20 -0
- package/dist/tools-logic/skill-list.js.map +1 -0
- package/dist/tools-logic/skill-recall.d.ts +26 -0
- package/dist/tools-logic/skill-recall.d.ts.map +1 -0
- package/dist/tools-logic/skill-recall.js +32 -0
- package/dist/tools-logic/skill-recall.js.map +1 -0
- package/dist/tools-logic/skill-write.d.ts +23 -0
- package/dist/tools-logic/skill-write.d.ts.map +1 -0
- package/dist/tools-logic/skill-write.js +46 -0
- package/dist/tools-logic/skill-write.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FSRS-lite — Free Spaced Repetition Scheduler, simplified for AgentRecall.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by SuperMemo / FSRS-6 (Anki ≥23.10). We don't run actual review
|
|
5
|
+
* sessions, so we track a 2-component model (Stability + Retrievability)
|
|
6
|
+
* instead of the full FSRS 3-component (S, D, R).
|
|
7
|
+
*
|
|
8
|
+
* Core idea:
|
|
9
|
+
* R = exp(-days_since_lastConfirmed / S)
|
|
10
|
+
* On confirmation / successful recall: S grows.
|
|
11
|
+
* On staleness (no confirm for long): R falls; eviction candidate.
|
|
12
|
+
*
|
|
13
|
+
* Used by:
|
|
14
|
+
* - insights (palace/awareness)
|
|
15
|
+
* - palace room facts
|
|
16
|
+
* - palace pipeline syntheses
|
|
17
|
+
*
|
|
18
|
+
* Decisions log:
|
|
19
|
+
* - We do NOT auto-delete. Retrievability < 0.3 is "archive candidate",
|
|
20
|
+
* surfaced in dashboard but never removed without explicit action.
|
|
21
|
+
* - Reinforcement happens on `recall` hit. Every retrieval bumps lastConfirmed
|
|
22
|
+
* and grows S. Same loop as biological reconsolidation but additive only.
|
|
23
|
+
*/
|
|
24
|
+
declare const DEFAULT_INITIAL_STABILITY = 7;
|
|
25
|
+
declare const ARCHIVE_THRESHOLD = 0.3;
|
|
26
|
+
declare const HOT_THRESHOLD = 0.85;
|
|
27
|
+
export interface FsrsState {
|
|
28
|
+
/** Stability — days. Higher = facts stays "remembered" longer between confirms. */
|
|
29
|
+
stability: number;
|
|
30
|
+
/** ISO timestamp of last successful confirmation/recall hit. */
|
|
31
|
+
last_confirmed: string;
|
|
32
|
+
/** Total confirmation count (monotonic). */
|
|
33
|
+
confirmations: number;
|
|
34
|
+
}
|
|
35
|
+
export interface FsrsScore {
|
|
36
|
+
/** Retrievability — probability the agent would find this useful today. 0..1. */
|
|
37
|
+
retrievability: number;
|
|
38
|
+
/** Stability (days). */
|
|
39
|
+
stability: number;
|
|
40
|
+
/** Days since lastConfirmed. */
|
|
41
|
+
age_days: number;
|
|
42
|
+
/** Health bucket. */
|
|
43
|
+
status: "hot" | "warm" | "cool" | "archive_candidate";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Initialize FSRS state for a new fact.
|
|
47
|
+
*/
|
|
48
|
+
export declare function initFsrs(now?: string): FsrsState;
|
|
49
|
+
/**
|
|
50
|
+
* Compute current retrievability + status from FSRS state.
|
|
51
|
+
*/
|
|
52
|
+
export declare function score(state: FsrsState, now?: string): FsrsScore;
|
|
53
|
+
/**
|
|
54
|
+
* Reinforce: a recall or confirmation bumps lastConfirmed and grows stability.
|
|
55
|
+
* Returns updated state. Pure — caller writes back to disk.
|
|
56
|
+
*/
|
|
57
|
+
export declare function reinforce(state: FsrsState, now?: string): FsrsState;
|
|
58
|
+
/**
|
|
59
|
+
* Penalize: explicit signal that this fact was wrong / unhelpful.
|
|
60
|
+
* Halves stability and keeps lastConfirmed (so age stays the same).
|
|
61
|
+
*/
|
|
62
|
+
export declare function penalize(state: FsrsState): FsrsState;
|
|
63
|
+
export { ARCHIVE_THRESHOLD, HOT_THRESHOLD, DEFAULT_INITIAL_STABILITY };
|
|
64
|
+
//# sourceMappingURL=fsrs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsrs.d.ts","sourceRoot":"","sources":["../../src/palace/fsrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,QAAA,MAAM,yBAAyB,IAAI,CAAC;AAEpC,QAAA,MAAM,iBAAiB,MAAM,CAAC;AAC9B,QAAA,MAAM,aAAa,OAAO,CAAC;AAG3B,MAAM,WAAW,SAAS;IACxB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAC;CACvD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,GAAE,MAAiC,GAAG,SAAS,CAM1E;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAE,MAAiC,GAAG,SAAS,CAYzF;AASD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAE,MAAiC,GAAG,SAAS,CAM7F;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAKpD;AAED,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FSRS-lite — Free Spaced Repetition Scheduler, simplified for AgentRecall.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by SuperMemo / FSRS-6 (Anki ≥23.10). We don't run actual review
|
|
5
|
+
* sessions, so we track a 2-component model (Stability + Retrievability)
|
|
6
|
+
* instead of the full FSRS 3-component (S, D, R).
|
|
7
|
+
*
|
|
8
|
+
* Core idea:
|
|
9
|
+
* R = exp(-days_since_lastConfirmed / S)
|
|
10
|
+
* On confirmation / successful recall: S grows.
|
|
11
|
+
* On staleness (no confirm for long): R falls; eviction candidate.
|
|
12
|
+
*
|
|
13
|
+
* Used by:
|
|
14
|
+
* - insights (palace/awareness)
|
|
15
|
+
* - palace room facts
|
|
16
|
+
* - palace pipeline syntheses
|
|
17
|
+
*
|
|
18
|
+
* Decisions log:
|
|
19
|
+
* - We do NOT auto-delete. Retrievability < 0.3 is "archive candidate",
|
|
20
|
+
* surfaced in dashboard but never removed without explicit action.
|
|
21
|
+
* - Reinforcement happens on `recall` hit. Every retrieval bumps lastConfirmed
|
|
22
|
+
* and grows S. Same loop as biological reconsolidation but additive only.
|
|
23
|
+
*/
|
|
24
|
+
const DEFAULT_INITIAL_STABILITY = 7; // days — new fact "feels fresh" for a week
|
|
25
|
+
const STABILITY_GROWTH = 0.3; // each confirmation grows S by 30%
|
|
26
|
+
const ARCHIVE_THRESHOLD = 0.3; // R below this → archive candidate
|
|
27
|
+
const HOT_THRESHOLD = 0.85; // R above this → strong fact
|
|
28
|
+
const MS_PER_DAY = 86_400_000;
|
|
29
|
+
/**
|
|
30
|
+
* Initialize FSRS state for a new fact.
|
|
31
|
+
*/
|
|
32
|
+
export function initFsrs(now = new Date().toISOString()) {
|
|
33
|
+
return {
|
|
34
|
+
stability: DEFAULT_INITIAL_STABILITY,
|
|
35
|
+
last_confirmed: now,
|
|
36
|
+
confirmations: 1,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute current retrievability + status from FSRS state.
|
|
41
|
+
*/
|
|
42
|
+
export function score(state, now = new Date().toISOString()) {
|
|
43
|
+
const last = new Date(state.last_confirmed).getTime();
|
|
44
|
+
const cur = new Date(now).getTime();
|
|
45
|
+
const ageMs = Math.max(0, cur - last);
|
|
46
|
+
const ageDays = ageMs / MS_PER_DAY;
|
|
47
|
+
const r = Math.exp(-ageDays / Math.max(0.001, state.stability));
|
|
48
|
+
return {
|
|
49
|
+
retrievability: Number(r.toFixed(4)),
|
|
50
|
+
stability: state.stability,
|
|
51
|
+
age_days: Number(ageDays.toFixed(2)),
|
|
52
|
+
status: bucket(r),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function bucket(r) {
|
|
56
|
+
if (r >= HOT_THRESHOLD)
|
|
57
|
+
return "hot";
|
|
58
|
+
if (r >= 0.6)
|
|
59
|
+
return "warm";
|
|
60
|
+
if (r >= ARCHIVE_THRESHOLD)
|
|
61
|
+
return "cool";
|
|
62
|
+
return "archive_candidate";
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Reinforce: a recall or confirmation bumps lastConfirmed and grows stability.
|
|
66
|
+
* Returns updated state. Pure — caller writes back to disk.
|
|
67
|
+
*/
|
|
68
|
+
export function reinforce(state, now = new Date().toISOString()) {
|
|
69
|
+
return {
|
|
70
|
+
stability: state.stability * (1 + STABILITY_GROWTH),
|
|
71
|
+
last_confirmed: now,
|
|
72
|
+
confirmations: state.confirmations + 1,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Penalize: explicit signal that this fact was wrong / unhelpful.
|
|
77
|
+
* Halves stability and keeps lastConfirmed (so age stays the same).
|
|
78
|
+
*/
|
|
79
|
+
export function penalize(state) {
|
|
80
|
+
return {
|
|
81
|
+
...state,
|
|
82
|
+
stability: Math.max(1, state.stability * 0.5),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export { ARCHIVE_THRESHOLD, HOT_THRESHOLD, DEFAULT_INITIAL_STABILITY };
|
|
86
|
+
//# sourceMappingURL=fsrs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsrs.js","sourceRoot":"","sources":["../../src/palace/fsrs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,yBAAyB,GAAG,CAAC,CAAC,CAAC,2CAA2C;AAChF,MAAM,gBAAgB,GAAG,GAAG,CAAC,CAAQ,mCAAmC;AACxE,MAAM,iBAAiB,GAAG,GAAG,CAAC,CAAO,mCAAmC;AACxE,MAAM,aAAa,GAAG,IAAI,CAAC,CAAU,6BAA6B;AAClE,MAAM,UAAU,GAAG,UAAU,CAAC;AAsB9B;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAC7D,OAAO;QACL,SAAS,EAAE,yBAAyB;QACpC,cAAc,EAAE,GAAG;QACnB,aAAa,EAAE,CAAC;KACjB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAgB,EAAE,MAAc,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAC5E,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAChE,OAAO;QACL,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,IAAI,CAAC,IAAI,aAAa;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,CAAC,IAAI,GAAG;QAAE,OAAO,MAAM,CAAC;IAC5B,IAAI,CAAC,IAAI,iBAAiB;QAAE,OAAO,MAAM,CAAC;IAC1C,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAgB,EAAE,MAAc,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAChF,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,gBAAgB,CAAC;QACnD,cAAc,EAAE,GAAG;QACnB,aAAa,EAAE,KAAK,CAAC,aAAa,GAAG,CAAC;KACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgB;IACvC,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modern Hopfield retrieval (Ramsauer et al. 2020 — "Hopfield Networks is All You Need").
|
|
3
|
+
*
|
|
4
|
+
* The math
|
|
5
|
+
* --------
|
|
6
|
+
* Given stored memory matrix X ∈ ℝ^{N × d} (N memories, d-dim embeddings)
|
|
7
|
+
* and query vector ξ ∈ ℝ^d
|
|
8
|
+
*
|
|
9
|
+
* ξ_new = X^⊤ · softmax( β · X · ξ )
|
|
10
|
+
*
|
|
11
|
+
* weights[i] = softmax(β · ⟨x_i, ξ⟩)[i]
|
|
12
|
+
* blended = Σ_i weights[i] · x_i
|
|
13
|
+
* energy = -1/β · log Σ_i exp(β · ⟨x_i, ξ⟩) + ½‖ξ‖²
|
|
14
|
+
*
|
|
15
|
+
* Why this beats cosine k-NN
|
|
16
|
+
* --------------------------
|
|
17
|
+
* 1. Storage capacity ~ exp(d/2) instead of 0.14·d (classical Hopfield).
|
|
18
|
+
* 2. Single-step convergence to the nearest pattern (no iterative search).
|
|
19
|
+
* 3. Temperature β tunes precision vs. associative blend:
|
|
20
|
+
* β → ∞ : retrieval ≈ argmax k-NN
|
|
21
|
+
* β → 0 : retrieval ≈ centroid of nearby memories
|
|
22
|
+
* 4. The `blended` vector is a free "expansion query" for a second
|
|
23
|
+
* retrieval pass (associative recall) — picks up wikilink-related
|
|
24
|
+
* memories that share semantic mass but lack lexical overlap.
|
|
25
|
+
*
|
|
26
|
+
* Use in AgentRecall
|
|
27
|
+
* ------------------
|
|
28
|
+
* This module is a *pure scoring primitive*. It does not do I/O. Callers
|
|
29
|
+
* pass in already-loaded embeddings (e.g. from local-vector-store or
|
|
30
|
+
* Supabase pgvector). Typical wiring:
|
|
31
|
+
*
|
|
32
|
+
* 1. recall() runs BM25 + vector RRF → returns candidate set of K items
|
|
33
|
+
* 2. Pull embeddings for those K items
|
|
34
|
+
* 3. hopfieldRecall({query, memoryMatrix}) → returns soft re-rank weights
|
|
35
|
+
* 4. Optionally pass `blended` back as a second-pass query for associative expansion
|
|
36
|
+
*
|
|
37
|
+
* Caveats
|
|
38
|
+
* -------
|
|
39
|
+
* - Patterns must be L2-normalized for the capacity claim to hold.
|
|
40
|
+
* - Near-duplicate memories (cos > 0.95) produce blurry centroids ("spurious
|
|
41
|
+
* attractors"). Pre-dedup or raise β to mitigate.
|
|
42
|
+
* - The `energy` value is comparable only within a fixed (N, β); don't
|
|
43
|
+
* compare across different memory sets.
|
|
44
|
+
*/
|
|
45
|
+
export interface HopfieldRecallInput {
|
|
46
|
+
/** Query vector — does not need to be normalized; we normalize internally. */
|
|
47
|
+
query: number[];
|
|
48
|
+
/** N stored memory vectors, each length d. Will be normalized internally. */
|
|
49
|
+
memoryMatrix: number[][];
|
|
50
|
+
/** Inverse temperature. Higher β = sharper retrieval. Default 8. */
|
|
51
|
+
beta?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Number of update steps. 1 is usually enough for well-separated patterns.
|
|
54
|
+
* Set 2-3 only when patterns are dense (cos < 0.7 between nearest neighbors).
|
|
55
|
+
*/
|
|
56
|
+
steps?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Optional human-readable IDs aligned with memoryMatrix rows. Returned
|
|
59
|
+
* with topIndices so callers don't have to re-map.
|
|
60
|
+
*/
|
|
61
|
+
ids?: string[];
|
|
62
|
+
}
|
|
63
|
+
export interface HopfieldRecallResult {
|
|
64
|
+
/** Softmax weights, length N, sums to 1. */
|
|
65
|
+
weights: number[];
|
|
66
|
+
/** Top indices by weight (descending). */
|
|
67
|
+
topIndices: number[];
|
|
68
|
+
/** Top ids (if provided in input), aligned with topIndices. */
|
|
69
|
+
topIds?: string[];
|
|
70
|
+
/** Weighted-sum vector — use as a synthetic expansion query. */
|
|
71
|
+
blended: number[];
|
|
72
|
+
/** Log-sum-exp energy. Lower = sharper match. */
|
|
73
|
+
energy: number;
|
|
74
|
+
/**
|
|
75
|
+
* Retrieval status:
|
|
76
|
+
* sharp — winner weight > 0.5
|
|
77
|
+
* blended — top-2 weights within 2x of each other
|
|
78
|
+
* spurious — entropy of weight distribution > log(N/2) (memory mass smeared)
|
|
79
|
+
*/
|
|
80
|
+
status: "sharp" | "blended" | "spurious";
|
|
81
|
+
/** Number of steps actually run. */
|
|
82
|
+
steps_taken: number;
|
|
83
|
+
}
|
|
84
|
+
export declare function hopfieldRecall(input: HopfieldRecallInput): HopfieldRecallResult;
|
|
85
|
+
/**
|
|
86
|
+
* Convenience: rerank an existing candidate list (e.g. from RRF) using
|
|
87
|
+
* Hopfield soft weights. Returns the input candidates in new order plus a
|
|
88
|
+
* `score` field per candidate.
|
|
89
|
+
*/
|
|
90
|
+
export interface RerankInput<T> {
|
|
91
|
+
query: number[];
|
|
92
|
+
candidates: Array<T & {
|
|
93
|
+
embedding: number[];
|
|
94
|
+
}>;
|
|
95
|
+
beta?: number;
|
|
96
|
+
steps?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface RerankItem<T> {
|
|
99
|
+
item: T;
|
|
100
|
+
score: number;
|
|
101
|
+
rank: number;
|
|
102
|
+
}
|
|
103
|
+
export declare function hopfieldRerank<T>(input: RerankInput<T>): {
|
|
104
|
+
items: Array<RerankItem<T>>;
|
|
105
|
+
status: HopfieldRecallResult["status"];
|
|
106
|
+
energy: number;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=hopfield.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hopfield.d.ts","sourceRoot":"","sources":["../../src/palace/hopfield.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,WAAW,mBAAmB;IAClC,8EAA8E;IAC9E,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC;IACzB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;IACzC,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;CACrB;AAgFD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAyF/E;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC,CAAC,GAAG;QAAE,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;IACxD,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB,CAwBA"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modern Hopfield retrieval (Ramsauer et al. 2020 — "Hopfield Networks is All You Need").
|
|
3
|
+
*
|
|
4
|
+
* The math
|
|
5
|
+
* --------
|
|
6
|
+
* Given stored memory matrix X ∈ ℝ^{N × d} (N memories, d-dim embeddings)
|
|
7
|
+
* and query vector ξ ∈ ℝ^d
|
|
8
|
+
*
|
|
9
|
+
* ξ_new = X^⊤ · softmax( β · X · ξ )
|
|
10
|
+
*
|
|
11
|
+
* weights[i] = softmax(β · ⟨x_i, ξ⟩)[i]
|
|
12
|
+
* blended = Σ_i weights[i] · x_i
|
|
13
|
+
* energy = -1/β · log Σ_i exp(β · ⟨x_i, ξ⟩) + ½‖ξ‖²
|
|
14
|
+
*
|
|
15
|
+
* Why this beats cosine k-NN
|
|
16
|
+
* --------------------------
|
|
17
|
+
* 1. Storage capacity ~ exp(d/2) instead of 0.14·d (classical Hopfield).
|
|
18
|
+
* 2. Single-step convergence to the nearest pattern (no iterative search).
|
|
19
|
+
* 3. Temperature β tunes precision vs. associative blend:
|
|
20
|
+
* β → ∞ : retrieval ≈ argmax k-NN
|
|
21
|
+
* β → 0 : retrieval ≈ centroid of nearby memories
|
|
22
|
+
* 4. The `blended` vector is a free "expansion query" for a second
|
|
23
|
+
* retrieval pass (associative recall) — picks up wikilink-related
|
|
24
|
+
* memories that share semantic mass but lack lexical overlap.
|
|
25
|
+
*
|
|
26
|
+
* Use in AgentRecall
|
|
27
|
+
* ------------------
|
|
28
|
+
* This module is a *pure scoring primitive*. It does not do I/O. Callers
|
|
29
|
+
* pass in already-loaded embeddings (e.g. from local-vector-store or
|
|
30
|
+
* Supabase pgvector). Typical wiring:
|
|
31
|
+
*
|
|
32
|
+
* 1. recall() runs BM25 + vector RRF → returns candidate set of K items
|
|
33
|
+
* 2. Pull embeddings for those K items
|
|
34
|
+
* 3. hopfieldRecall({query, memoryMatrix}) → returns soft re-rank weights
|
|
35
|
+
* 4. Optionally pass `blended` back as a second-pass query for associative expansion
|
|
36
|
+
*
|
|
37
|
+
* Caveats
|
|
38
|
+
* -------
|
|
39
|
+
* - Patterns must be L2-normalized for the capacity claim to hold.
|
|
40
|
+
* - Near-duplicate memories (cos > 0.95) produce blurry centroids ("spurious
|
|
41
|
+
* attractors"). Pre-dedup or raise β to mitigate.
|
|
42
|
+
* - The `energy` value is comparable only within a fixed (N, β); don't
|
|
43
|
+
* compare across different memory sets.
|
|
44
|
+
*/
|
|
45
|
+
const DEFAULT_BETA = 8.0;
|
|
46
|
+
const DEFAULT_STEPS = 1;
|
|
47
|
+
/**
|
|
48
|
+
* Validate that every value in a numeric vector is finite (no NaN, no ±Infinity).
|
|
49
|
+
* Throws with a precise message including the offending position. Cheap (single pass).
|
|
50
|
+
*/
|
|
51
|
+
function assertFiniteVector(v, label) {
|
|
52
|
+
for (let i = 0; i < v.length; i++) {
|
|
53
|
+
if (!Number.isFinite(v[i])) {
|
|
54
|
+
throw new Error(`hopfieldRecall: ${label}[${i}] is not finite (got ${v[i]})`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function dot(a, b) {
|
|
59
|
+
// Hard-fail on dim mismatch — silent truncation produced plausible-looking
|
|
60
|
+
// but wrong rankings when callers accidentally mixed embedding-model versions.
|
|
61
|
+
if (a.length !== b.length) {
|
|
62
|
+
throw new Error(`hopfieldRecall: dimension mismatch (${a.length} vs ${b.length})`);
|
|
63
|
+
}
|
|
64
|
+
let s = 0;
|
|
65
|
+
for (let i = 0; i < a.length; i++)
|
|
66
|
+
s += a[i] * b[i];
|
|
67
|
+
return s;
|
|
68
|
+
}
|
|
69
|
+
function norm(v) {
|
|
70
|
+
let s = 0;
|
|
71
|
+
for (let i = 0; i < v.length; i++)
|
|
72
|
+
s += v[i] * v[i];
|
|
73
|
+
return Math.sqrt(s);
|
|
74
|
+
}
|
|
75
|
+
function l2normalize(v) {
|
|
76
|
+
const n = norm(v);
|
|
77
|
+
if (n === 0)
|
|
78
|
+
return v.slice();
|
|
79
|
+
const out = new Array(v.length);
|
|
80
|
+
for (let i = 0; i < v.length; i++)
|
|
81
|
+
out[i] = v[i] / n;
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Numerically-stable softmax + log-sum-exp.
|
|
86
|
+
* Returns {weights, logSumExp} so callers can recover energy without recomputing.
|
|
87
|
+
*/
|
|
88
|
+
function softmaxStable(scores) {
|
|
89
|
+
if (scores.length === 0)
|
|
90
|
+
return { weights: [], logSumExp: -Infinity };
|
|
91
|
+
let maxScore = -Infinity;
|
|
92
|
+
for (const s of scores)
|
|
93
|
+
if (s > maxScore)
|
|
94
|
+
maxScore = s;
|
|
95
|
+
const expScores = scores.map((s) => Math.exp(s - maxScore));
|
|
96
|
+
let sum = 0;
|
|
97
|
+
for (const e of expScores)
|
|
98
|
+
sum += e;
|
|
99
|
+
const weights = expScores.map((e) => e / sum);
|
|
100
|
+
const logSumExp = maxScore + Math.log(sum);
|
|
101
|
+
return { weights, logSumExp };
|
|
102
|
+
}
|
|
103
|
+
function entropy(weights) {
|
|
104
|
+
let h = 0;
|
|
105
|
+
for (const w of weights) {
|
|
106
|
+
if (w > 0)
|
|
107
|
+
h -= w * Math.log(w);
|
|
108
|
+
}
|
|
109
|
+
return h;
|
|
110
|
+
}
|
|
111
|
+
function classifyStatus(weights) {
|
|
112
|
+
if (weights.length === 0)
|
|
113
|
+
return "spurious";
|
|
114
|
+
// Defensive: any non-finite weight = garbage retrieval, mark spurious.
|
|
115
|
+
for (const w of weights) {
|
|
116
|
+
if (!Number.isFinite(w))
|
|
117
|
+
return "spurious";
|
|
118
|
+
}
|
|
119
|
+
const sorted = [...weights].sort((a, b) => b - a);
|
|
120
|
+
if (sorted[0] > 0.5)
|
|
121
|
+
return "sharp";
|
|
122
|
+
const h = entropy(weights);
|
|
123
|
+
const hThreshold = Math.log(Math.max(2, weights.length / 2));
|
|
124
|
+
if (h > hThreshold)
|
|
125
|
+
return "spurious";
|
|
126
|
+
return "blended";
|
|
127
|
+
}
|
|
128
|
+
export function hopfieldRecall(input) {
|
|
129
|
+
const beta = input.beta ?? DEFAULT_BETA;
|
|
130
|
+
// Input validation — fail loud rather than silently corrupting downstream consumers.
|
|
131
|
+
if (!Number.isFinite(beta) || beta <= 0) {
|
|
132
|
+
throw new Error(`hopfieldRecall: beta must be a finite positive number (got ${beta})`);
|
|
133
|
+
}
|
|
134
|
+
if (input.query.length === 0) {
|
|
135
|
+
throw new Error("hopfieldRecall: query vector cannot be empty");
|
|
136
|
+
}
|
|
137
|
+
assertFiniteVector(input.query, "query");
|
|
138
|
+
const steps = Math.max(1, input.steps ?? DEFAULT_STEPS);
|
|
139
|
+
const N = input.memoryMatrix.length;
|
|
140
|
+
if (N === 0) {
|
|
141
|
+
return {
|
|
142
|
+
weights: [],
|
|
143
|
+
topIndices: [],
|
|
144
|
+
topIds: input.ids ? [] : undefined,
|
|
145
|
+
blended: input.query.slice(),
|
|
146
|
+
energy: 0,
|
|
147
|
+
status: "spurious",
|
|
148
|
+
steps_taken: 0,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// ids length must match memory matrix length when provided
|
|
152
|
+
if (input.ids && input.ids.length !== N) {
|
|
153
|
+
throw new Error(`hopfieldRecall: ids.length (${input.ids.length}) must equal memoryMatrix.length (${N})`);
|
|
154
|
+
}
|
|
155
|
+
const d = input.query.length;
|
|
156
|
+
// Validate every memory vector before normalizing
|
|
157
|
+
for (let i = 0; i < N; i++) {
|
|
158
|
+
const row = input.memoryMatrix[i];
|
|
159
|
+
if (row.length !== d) {
|
|
160
|
+
throw new Error(`hopfieldRecall: memoryMatrix[${i}].length (${row.length}) must equal query.length (${d})`);
|
|
161
|
+
}
|
|
162
|
+
assertFiniteVector(row, `memoryMatrix[${i}]`);
|
|
163
|
+
}
|
|
164
|
+
// Normalize once — capacity & convergence assume unit vectors.
|
|
165
|
+
const X = input.memoryMatrix.map((v) => l2normalize(v));
|
|
166
|
+
let xi = l2normalize(input.query);
|
|
167
|
+
let weights = new Array(N).fill(0);
|
|
168
|
+
let logSumExp = 0;
|
|
169
|
+
let stepsRun = 0;
|
|
170
|
+
for (let step = 0; step < steps; step++) {
|
|
171
|
+
// Scores = β · X · ξ
|
|
172
|
+
const scores = new Array(N);
|
|
173
|
+
for (let i = 0; i < N; i++)
|
|
174
|
+
scores[i] = beta * dot(X[i], xi);
|
|
175
|
+
const sm = softmaxStable(scores);
|
|
176
|
+
weights = sm.weights;
|
|
177
|
+
logSumExp = sm.logSumExp;
|
|
178
|
+
stepsRun++;
|
|
179
|
+
// Blended = Σ w_i · x_i
|
|
180
|
+
const blended = new Array(d).fill(0);
|
|
181
|
+
for (let i = 0; i < N; i++) {
|
|
182
|
+
const w = weights[i];
|
|
183
|
+
const xi_i = X[i];
|
|
184
|
+
for (let j = 0; j < d; j++)
|
|
185
|
+
blended[j] += w * xi_i[j];
|
|
186
|
+
}
|
|
187
|
+
xi = l2normalize(blended);
|
|
188
|
+
}
|
|
189
|
+
// Final blended (pre-normalized) for caller to use as expansion query
|
|
190
|
+
const blendedRaw = new Array(d).fill(0);
|
|
191
|
+
for (let i = 0; i < N; i++) {
|
|
192
|
+
const w = weights[i];
|
|
193
|
+
const xi_i = X[i];
|
|
194
|
+
for (let j = 0; j < d; j++)
|
|
195
|
+
blendedRaw[j] += w * xi_i[j];
|
|
196
|
+
}
|
|
197
|
+
// Energy = -1/β · log Σ exp(β · ⟨x_i, ξ⟩) + ½‖ξ‖²
|
|
198
|
+
// (ξ is the final iterate; ‖ξ‖² ≈ 1 since we re-normalize each step)
|
|
199
|
+
const energy = -logSumExp / beta + 0.5 * dot(xi, xi);
|
|
200
|
+
// Rank indices by weight desc
|
|
201
|
+
const order = Array.from({ length: N }, (_, i) => i).sort((a, b) => weights[b] - weights[a]);
|
|
202
|
+
return {
|
|
203
|
+
weights,
|
|
204
|
+
topIndices: order,
|
|
205
|
+
topIds: input.ids ? order.map((i) => input.ids[i]) : undefined,
|
|
206
|
+
blended: blendedRaw,
|
|
207
|
+
energy,
|
|
208
|
+
status: classifyStatus(weights),
|
|
209
|
+
steps_taken: stepsRun,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
export function hopfieldRerank(input) {
|
|
213
|
+
// Validate every candidate has a usable embedding before delegating.
|
|
214
|
+
for (let i = 0; i < input.candidates.length; i++) {
|
|
215
|
+
const cand = input.candidates[i];
|
|
216
|
+
if (!cand || !Array.isArray(cand.embedding)) {
|
|
217
|
+
throw new Error(`hopfieldRerank: candidates[${i}].embedding must be a number[]`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const matrix = input.candidates.map((c) => c.embedding);
|
|
221
|
+
const result = hopfieldRecall({
|
|
222
|
+
query: input.query,
|
|
223
|
+
memoryMatrix: matrix,
|
|
224
|
+
beta: input.beta,
|
|
225
|
+
steps: input.steps,
|
|
226
|
+
});
|
|
227
|
+
const items = result.topIndices.map((origIdx, newRank) => {
|
|
228
|
+
const { embedding: _omit, ...rest } = input.candidates[origIdx];
|
|
229
|
+
return {
|
|
230
|
+
item: rest,
|
|
231
|
+
score: result.weights[origIdx],
|
|
232
|
+
rank: newRank,
|
|
233
|
+
};
|
|
234
|
+
});
|
|
235
|
+
return { items, status: result.status, energy: result.energy };
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=hopfield.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hopfield.js","sourceRoot":"","sources":["../../src/palace/hopfield.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AA2CH,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB;;;GAGG;AACH,SAAS,kBAAkB,CAAC,CAAW,EAAE,KAAa;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,CAAW,EAAE,CAAW;IACnC,2EAA2E;IAC3E,+EAA+E;IAC/E,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,IAAI,CAAC,CAAW;IACvB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,WAAW,CAAC,CAAW;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAgB;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC;IACtE,IAAI,QAAQ,GAAG,CAAC,QAAQ,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,IAAI,CAAC,GAAG,QAAQ;YAAE,QAAQ,GAAG,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC5D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,GAAG,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,OAAO,CAAC,OAAiB;IAChC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC;YAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,cAAc,CAAC,OAAiB;IACvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC5C,uEAAuE;IACvE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,UAAU,CAAC;IAC7C,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG;QAAE,OAAO,OAAO,CAAC;IACpC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,GAAG,UAAU;QAAE,OAAO,UAAU,CAAC;IACtC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC;IACxC,qFAAqF;IACrF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,8DAA8D,IAAI,GAAG,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;YAClC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE;YAC5B,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,UAAU;YAClB,WAAW,EAAE,CAAC;SACf,CAAC;IACJ,CAAC;IACD,2DAA2D;IAC3D,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,CAAC,GAAG,CAAC,MAAM,qCAAqC,CAAC,GAAG,CAAC,CAAC;IAC5G,CAAC;IACD,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IAC7B,kDAAkD;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,aAAa,GAAG,CAAC,MAAM,8BAA8B,CAAC,GAAG,CAAC,CAAC;QAC9G,CAAC;QACD,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,+DAA+D;IAC/D,MAAM,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAElC,IAAI,OAAO,GAAa,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QACxC,qBAAqB;QACrB,MAAM,MAAM,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAE7D,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;QACrB,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,QAAQ,EAAE,CAAC;QAEX,wBAAwB;QACxB,MAAM,OAAO,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,sEAAsE;IACtE,MAAM,UAAU,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,kDAAkD;IAClD,qEAAqE;IACrE,MAAM,MAAM,GAAG,CAAC,SAAS,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAErD,8BAA8B;IAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7F,OAAO;QACL,OAAO;QACP,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAC/D,OAAO,EAAE,UAAU;QACnB,MAAM;QACN,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC;QAC/B,WAAW,EAAE,QAAQ;KACtB,CAAC;AACJ,CAAC;AAoBD,MAAM,UAAU,cAAc,CAAI,KAAqB;IAKrD,qEAAqE;IACrE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,gCAAgC,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,cAAc,CAAC;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY,EAAE,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC;IACH,MAAM,KAAK,GAAyB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;QAC7E,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAsD,CAAC;QACrH,OAAO;YACL,IAAI,EAAE,IAAoB;YAC1B,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,OAAO;SACd,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian.d.ts","sourceRoot":"","sources":["../../src/palace/obsidian.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"obsidian.d.ts","sourceRoot":"","sources":["../../src/palace/obsidian.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0B5C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAczE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CA0BxD;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1D;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,CAmBR"}
|
package/dist/palace/obsidian.js
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
* Obsidian-compatible markdown formatting.
|
|
3
3
|
* Generates YAML frontmatter and [[wikilinks]] for every palace file.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Quote a scalar value safely for YAML.
|
|
7
|
+
* Always JSON-stringifies strings that contain newline, colon, dash, hash, or
|
|
8
|
+
* other YAML-significant characters, preventing injection where an attacker
|
|
9
|
+
* (or prompt-injected LLM) could close the frontmatter or forge keys.
|
|
10
|
+
*/
|
|
11
|
+
function quoteScalar(value) {
|
|
12
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
13
|
+
return String(value);
|
|
14
|
+
}
|
|
15
|
+
if (typeof value !== "string") {
|
|
16
|
+
return JSON.stringify(value);
|
|
17
|
+
}
|
|
18
|
+
// Quote if the string contains anything that could be YAML-significant,
|
|
19
|
+
// including leading/trailing whitespace, or starts with a special marker.
|
|
20
|
+
// JSON.stringify gives us valid double-quoted YAML for free (newline → \n etc).
|
|
21
|
+
if (/[\n\r\t"'#:&*!|>%@`{}\[\]?,]|^\s|\s$|^-|^---|^\.\.\./.test(value)) {
|
|
22
|
+
return JSON.stringify(value);
|
|
23
|
+
}
|
|
24
|
+
// Empty string must be quoted
|
|
25
|
+
if (value === "")
|
|
26
|
+
return '""';
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
5
29
|
export function generateFrontmatter(meta) {
|
|
6
30
|
const lines = ["---"];
|
|
7
31
|
for (const [key, value] of Object.entries(meta)) {
|
|
@@ -14,7 +38,7 @@ export function generateFrontmatter(meta) {
|
|
|
14
38
|
lines.push(`${key}: ${JSON.stringify(value)}`);
|
|
15
39
|
}
|
|
16
40
|
else {
|
|
17
|
-
lines.push(`${key}: ${value}`);
|
|
41
|
+
lines.push(`${key}: ${quoteScalar(value)}`);
|
|
18
42
|
}
|
|
19
43
|
}
|
|
20
44
|
lines.push("---", "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/palace/obsidian.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAC/D,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;IACtB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/palace/obsidian.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline layer — project milestone narrative spine.
|
|
3
|
+
* Stored under palace/pipeline/NNNN-phase-slug.md, one file per phase.
|
|
4
|
+
* Distinct from journal (chronology), palace/rooms (facts), awareness (cross-project).
|
|
5
|
+
*
|
|
6
|
+
* Hardening notes:
|
|
7
|
+
* - Order numbers sorted numerically (lex sort breaks at 10).
|
|
8
|
+
* - Atomic writes via tmp+rename (writeFileSync is not crash-safe).
|
|
9
|
+
* - Section parser only ends at the four KNOWN headings, so user-supplied
|
|
10
|
+
* "## Anything" inside a section body cannot break it.
|
|
11
|
+
* - Frontmatter parser accepts both quoted (JSON-encoded) and bare scalars.
|
|
12
|
+
*/
|
|
13
|
+
export type PhaseStatus = "active" | "closed" | "abandoned";
|
|
14
|
+
export interface MilestoneMeta {
|
|
15
|
+
phase: string;
|
|
16
|
+
order: number;
|
|
17
|
+
status: PhaseStatus;
|
|
18
|
+
opened: string;
|
|
19
|
+
closed?: string | null;
|
|
20
|
+
related_journal?: string[];
|
|
21
|
+
related_insights?: string[];
|
|
22
|
+
/** True if this phase was drafted automatically (v1.5+); false/absent = manual. */
|
|
23
|
+
auto?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface MilestoneSections {
|
|
26
|
+
goal: string;
|
|
27
|
+
what_was_hard: string;
|
|
28
|
+
how_solved: string;
|
|
29
|
+
synthesis: string;
|
|
30
|
+
}
|
|
31
|
+
export interface Milestone {
|
|
32
|
+
meta: MilestoneMeta;
|
|
33
|
+
sections: MilestoneSections;
|
|
34
|
+
file_path: string;
|
|
35
|
+
}
|
|
36
|
+
export interface MilestoneSummary {
|
|
37
|
+
order: number;
|
|
38
|
+
phase: string;
|
|
39
|
+
status: PhaseStatus;
|
|
40
|
+
opened: string;
|
|
41
|
+
closed: string | null;
|
|
42
|
+
synthesis: string | null;
|
|
43
|
+
file_path: string;
|
|
44
|
+
}
|
|
45
|
+
declare const PLACEHOLDER = "(in progress)";
|
|
46
|
+
export declare function pipelineDir(project: string): string;
|
|
47
|
+
export declare function zeroPad(n: number, width?: number): string;
|
|
48
|
+
export declare function milestoneFileName(order: number, phase: string): string;
|
|
49
|
+
export declare function parseMilestoneFile(filePath: string): Milestone;
|
|
50
|
+
export declare function listMilestones(project: string): Milestone[];
|
|
51
|
+
export declare function findActiveMilestone(project: string): Milestone | null;
|
|
52
|
+
export declare function nextOrder(project: string): number;
|
|
53
|
+
export declare function renderMilestone(meta: MilestoneMeta, sections: MilestoneSections): string;
|
|
54
|
+
/**
|
|
55
|
+
* Write a milestone file atomically via tmp + rename.
|
|
56
|
+
* Refuses to follow symlinks at the target path.
|
|
57
|
+
*/
|
|
58
|
+
export declare function writeMilestone(project: string, meta: MilestoneMeta, sections: MilestoneSections, existingFilePath?: string): string;
|
|
59
|
+
export declare function summarize(m: Milestone): MilestoneSummary;
|
|
60
|
+
export { PLACEHOLDER };
|
|
61
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/palace/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,QAAA,MAAM,WAAW,kBAAkB,CAAC;AAKpC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,MAAM,CAE5D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtE;AA2GD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAe9D;AAYD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAgB3D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGrE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIjD;AAsBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,iBAAiB,GAAG,MAAM,CAwBxF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,CA4BR;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,gBAAgB,CAUxD;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|