@fingerskier/augment 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +494 -450
  3. package/dist/cli.js +5 -4
  4. package/dist/cli.js.map +1 -1
  5. package/dist/daemon/client.d.ts +6 -0
  6. package/dist/daemon/client.js +19 -0
  7. package/dist/daemon/client.js.map +1 -1
  8. package/dist/daemon/http.js +79 -9
  9. package/dist/daemon/http.js.map +1 -1
  10. package/dist/daemon/lifetime-lock.js +12 -12
  11. package/dist/db.js +107 -107
  12. package/dist/decoction.d.ts +51 -0
  13. package/dist/decoction.js +184 -0
  14. package/dist/decoction.js.map +1 -0
  15. package/dist/hooks.d.ts +8 -5
  16. package/dist/hooks.js +49 -20
  17. package/dist/hooks.js.map +1 -1
  18. package/dist/install.d.ts +14 -2
  19. package/dist/install.js +189 -1
  20. package/dist/install.js.map +1 -1
  21. package/dist/mcp/apps.js +480 -480
  22. package/dist/mcp/server.js +83 -0
  23. package/dist/mcp/server.js.map +1 -1
  24. package/dist/memory/files.js +21 -2
  25. package/dist/memory/files.js.map +1 -1
  26. package/dist/memory/project.d.ts +3 -0
  27. package/dist/memory/project.js +20 -0
  28. package/dist/memory/project.js.map +1 -1
  29. package/dist/pi/extension.d.ts +6 -0
  30. package/dist/pi/extension.js +74 -20
  31. package/dist/pi/extension.js.map +1 -1
  32. package/dist/proposals.js +16 -15
  33. package/dist/proposals.js.map +1 -1
  34. package/dist/service.d.ts +134 -2
  35. package/dist/service.js +578 -51
  36. package/dist/service.js.map +1 -1
  37. package/docs/FEATURES.md +771 -615
  38. package/docs/verify-memory-flow.md +4 -3
  39. package/integrations/claude/skills/augment-context/SKILL.md +74 -74
  40. package/integrations/claude/skills/augment-decoction/SKILL.md +36 -0
  41. package/integrations/claude/skills/augment-dream/SKILL.md +34 -0
  42. package/integrations/claude/skills/augment-dream/agents/openai.yaml +4 -0
  43. package/integrations/claude/skills/augment-sleep/SKILL.md +26 -26
  44. package/integrations/codex/SKILL.md +107 -74
  45. package/integrations/examples/claude-mcp-config.json +17 -17
  46. package/integrations/examples/codex-mcp-config.json +17 -17
  47. package/integrations/examples/grok-mcp-config.toml +18 -0
  48. package/integrations/grok/AGENTS.md +61 -0
  49. package/integrations/pi/skills/augment-decoction/SKILL.md +37 -0
  50. package/integrations/pi/skills/augment-dream/SKILL.md +36 -0
  51. package/package.json +85 -84
  52. package/dist/tally.d.ts +0 -46
  53. package/dist/tally.js +0 -94
  54. package/dist/tally.js.map +0 -1
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: augment-decoction
3
+ description: Distill recurring cross-project Augment memory into generic SPEC/ARCH records and optionally remove fully subsumed originals from Pi. Use when the user asks to "decoct", "glean", generalize, or clean up repeated memories across projects.
4
+ ---
5
+
6
+ # Augment Decoction for Pi
7
+
8
+ Decoction extracts durable, project-independent knowledge from recurring
9
+ memories. It is separate from sleep: sleep consolidates settled work within one
10
+ project, while decoction finds patterns across projects and writes them under
11
+ `.generic/`.
12
+
13
+ 1. Call `augment_decoction_glean` with `action: "discover"`. If no cluster
14
+ spans at least four distinct projects, report that and stop.
15
+ 2. Pick a cluster and call `augment_read_memory` for every source. Synthesize
16
+ one generic record:
17
+ - use SPEC for a reusable contract or rule;
18
+ - use ARCH for a reusable decision or tradeoff;
19
+ - retain only claims supported across the projects;
20
+ - put every source used in `derived_from`.
21
+ 3. Suggest source removal only when the generic preserves the original's entire
22
+ durable content. Do not suggest a source that also contains project-specific
23
+ facts, history, caveats, or unresolved work.
24
+ 4. Call `augment_decoction_glean` with `action: "write"`, the complete draft,
25
+ and the reasoned `suggested_removals`. For an existing generic, read it fresh
26
+ and pass both of its expected hashes.
27
+ 5. Report the generic path and any warnings. Warnings are advisory and do not
28
+ block the write.
29
+ 6. Show each suggested cleanup path and reason verbatim. Ask for explicit user
30
+ approval of the exact paths; never infer approval from approval of the
31
+ generic itself.
32
+ 7. Only after approval, call `augment_decoction_cleanup` with the generic path
33
+ and the approved source paths. Report every deletion and any failure.
34
+
35
+ Cleanup hard-deletes the selected originals after retargeting inbound links to
36
+ the generic. It has no journal or rollback. The user may approve a subset or
37
+ decline cleanup entirely.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: augment-dream
3
+ description: Explore globally recalled Augment memories and propose speculative memories or links for explicit user approval. Use when the user asks to "dream" over memory, imagine hypotheses, or surface hidden connections across the current, generic, or foreign projects.
4
+ ---
5
+
6
+ # Augment Dream
7
+
8
+ Dreams are hypotheses, not established facts. Discover and draft freely, but
9
+ never mutate the corpus before the user explicitly approves a named proposal.
10
+ Use a real project as the active project; `.generic` is inspiration or a link
11
+ target only.
12
+
13
+ 1. Call `augment_search` separately for each exploratory query, always passing
14
+ the active `project_name` and singular `query` argument. Use normal global
15
+ results as ranked: the current project receives its normal priority, while
16
+ generic and foreign memories remain eligible. Do not reserve a generic
17
+ quota or add a generic fallback.
18
+ 2. Call `augment_read_memory` with each useful result's numeric memory id, and
19
+ retain its returned relative path for provenance. Imagine 1-5 coherent
20
+ candidates:
21
+ - dream memory: a new record in the active project, with `derived_from`
22
+ equal to the exact inspiration paths;
23
+ - dream link: a link from an active-project memory to any current, generic,
24
+ or foreign memory.
25
+ Generic-only and foreign-only inspiration are valid.
26
+ 3. Call `augment_dream_propose` for each worthwhile candidate. State the
27
+ speculation plainly in the content and rationale; do not present it as
28
+ settled truth.
29
+ 4. Show each proposal to the user. Only after explicit approval call
30
+ `augment_dream_apply` with its filename. Call `augment_dream_reject` when
31
+ the user rejects it. If approval is unclear, leave the proposal pending.
32
+ 5. Report the applied speculative memory or link and its `dream:` commit.
33
+
34
+ Keep evidence and conjecture distinguishable. Do not invent supporting source
35
+ paths, and do not rewrite a foreign memory: foreign projects are inspiration
36
+ and link targets only.
package/package.json CHANGED
@@ -1,84 +1,85 @@
1
- {
2
- "name": "@fingerskier/augment",
3
- "version": "0.4.0",
4
- "description": "Local RAG memory system for coding agents",
5
- "keywords": [
6
- "pi-package",
7
- "pi",
8
- "opencode",
9
- "memory",
10
- "rag",
11
- "mcp",
12
- "coding-agent"
13
- ],
14
- "type": "module",
15
- "main": "./dist/opencode/plugin.js",
16
- "types": "./dist/opencode/plugin.d.ts",
17
- "publishConfig": {
18
- "access": "public"
19
- },
20
- "bin": {
21
- "augment": "./dist/bin/augment.js",
22
- "augment-daemon": "./dist/bin/augment-daemon.js",
23
- "augment-mcp": "./dist/bin/augment-mcp.js"
24
- },
25
- "pi": {
26
- "extensions": [
27
- "./dist/pi/extension.js"
28
- ],
29
- "skills": [
30
- "./integrations/pi/skills"
31
- ]
32
- },
33
- "files": [
34
- "dist",
35
- "docs",
36
- "integrations",
37
- "README.md",
38
- "LICENSE"
39
- ],
40
- "scripts": {
41
- "build": "tsc -p tsconfig.json",
42
- "test": "node --import tsx --test \"test/**/*.test.ts\"",
43
- "test:model": "node --import tsx --import ./test/setup-real-model.mjs --test \"test/**/*.model.ts\"",
44
- "check": "npm run build && npm test",
45
- "prepack": "npm run check",
46
- "prepublishOnly": "npm run check"
47
- },
48
- "peerDependencies": {
49
- "@earendil-works/pi-ai": "*",
50
- "@earendil-works/pi-coding-agent": "*",
51
- "typebox": "*"
52
- },
53
- "peerDependenciesMeta": {
54
- "@earendil-works/pi-ai": {
55
- "optional": true
56
- },
57
- "@earendil-works/pi-coding-agent": {
58
- "optional": true
59
- },
60
- "typebox": {
61
- "optional": true
62
- }
63
- },
64
- "dependencies": {
65
- "@huggingface/transformers": "^3.8.0",
66
- "@libsql/client": "^0.15.15",
67
- "@modelcontextprotocol/sdk": "^1.29.0",
68
- "chokidar": "^4.0.3",
69
- "cytoscape": "^3.34.0",
70
- "gray-matter": "^4.0.3",
71
- "zod": "^3.25.76"
72
- },
73
- "devDependencies": {
74
- "@opencode-ai/plugin": "^1.17.15",
75
- "@types/node": "^24.3.0",
76
- "tsx": "^4.20.5",
77
- "typebox": "^1.1.38",
78
- "typescript": "^5.9.2"
79
- },
80
- "engines": {
81
- "node": ">=20"
82
- },
83
- "license": "Apache-2.0"
84
- }
1
+ {
2
+ "name": "@fingerskier/augment",
3
+ "version": "0.5.1",
4
+ "description": "Local RAG memory system for coding agents",
5
+ "keywords": [
6
+ "pi-package",
7
+ "pi",
8
+ "opencode",
9
+ "memory",
10
+ "rag",
11
+ "mcp",
12
+ "coding-agent"
13
+ ],
14
+ "type": "module",
15
+ "main": "./dist/opencode/plugin.js",
16
+ "types": "./dist/opencode/plugin.d.ts",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "bin": {
21
+ "augment": "./dist/bin/augment.js",
22
+ "augment-daemon": "./dist/bin/augment-daemon.js",
23
+ "augment-mcp": "./dist/bin/augment-mcp.js"
24
+ },
25
+ "pi": {
26
+ "extensions": [
27
+ "./dist/pi/extension.js"
28
+ ],
29
+ "skills": [
30
+ "./integrations/pi/skills"
31
+ ]
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "docs",
36
+ "integrations",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "scripts": {
41
+ "clean": "node --eval \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
42
+ "build": "npm run clean && tsc -p tsconfig.json",
43
+ "test": "node --import tsx --test \"test/**/*.test.ts\"",
44
+ "test:model": "node --import tsx --import ./test/setup-real-model.mjs --test \"test/**/*.model.ts\"",
45
+ "check": "npm run build && npm test",
46
+ "prepack": "npm run check",
47
+ "prepublishOnly": "npm run check"
48
+ },
49
+ "peerDependencies": {
50
+ "@earendil-works/pi-ai": "*",
51
+ "@earendil-works/pi-coding-agent": "*",
52
+ "typebox": "*"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "@earendil-works/pi-ai": {
56
+ "optional": true
57
+ },
58
+ "@earendil-works/pi-coding-agent": {
59
+ "optional": true
60
+ },
61
+ "typebox": {
62
+ "optional": true
63
+ }
64
+ },
65
+ "dependencies": {
66
+ "@huggingface/transformers": "^3.8.0",
67
+ "@libsql/client": "^0.15.15",
68
+ "@modelcontextprotocol/sdk": "^1.29.0",
69
+ "chokidar": "^4.0.3",
70
+ "cytoscape": "^3.34.0",
71
+ "gray-matter": "^4.0.3",
72
+ "zod": "^3.25.76"
73
+ },
74
+ "devDependencies": {
75
+ "@opencode-ai/plugin": "^1.17.15",
76
+ "@types/node": "^24.3.0",
77
+ "tsx": "^4.20.5",
78
+ "typebox": "^1.1.38",
79
+ "typescript": "^5.9.2"
80
+ },
81
+ "engines": {
82
+ "node": ">=20"
83
+ },
84
+ "license": "Apache-2.0"
85
+ }
package/dist/tally.d.ts DELETED
@@ -1,46 +0,0 @@
1
- /**
2
- * Phase-2 dogfood tally (council 2026-06-30): ~30 human-scored datapoints over
3
- * ~2 weeks of real use, per injection surface, never a CI gate. Data lives as
4
- * JSONL under `<stateDir>/tally/` — deliberately OUTSIDE the memory corpus so
5
- * the corpus Phase 2 measures stays clean.
6
- */
7
- export declare const TALLY_TARGET = 30;
8
- export declare const TALLY_VERDICTS: readonly ["helpful", "harmless", "harmful", "correct-abstention"];
9
- export type TallyVerdict = (typeof TALLY_VERDICTS)[number];
10
- /** One human rating of a recall outcome. */
11
- export interface TallyRating {
12
- ts: string;
13
- verdict: TallyVerdict;
14
- /** Injection surface being rated: user-prompt-submit | pre-tool-use | mcp-search | cli-recall | unknown. */
15
- surface: string;
16
- note?: string;
17
- }
18
- /** One automatically-logged injection event (what search actually returned). */
19
- export interface TallyEvent {
20
- ts: string;
21
- surface: string;
22
- project?: string;
23
- /** Query text, truncated by the writer — context for later audit, not for ranking. */
24
- query: string;
25
- abstained: boolean;
26
- result_count: number;
27
- top_score?: number;
28
- /** Durable relative paths of the memories injected. */
29
- paths: string[];
30
- }
31
- export interface TallySummary {
32
- total: number;
33
- target: number;
34
- by_verdict: Record<TallyVerdict, number>;
35
- by_surface: Record<string, number>;
36
- first_at?: string;
37
- last_at?: string;
38
- }
39
- export declare function isTallyVerdict(value: unknown): value is TallyVerdict;
40
- export declare function ratingsPath(stateDir: string): string;
41
- export declare function eventsPath(stateDir: string): string;
42
- export declare function appendTallyRating(stateDir: string, rating: TallyRating): Promise<void>;
43
- export declare function appendTallyEvent(stateDir: string, event: TallyEvent): Promise<void>;
44
- export declare function readTallyRatings(stateDir: string): Promise<TallyRating[]>;
45
- export declare function summarizeTally(ratings: TallyRating[]): TallySummary;
46
- export declare function renderTallySummary(summary: TallySummary): string;
package/dist/tally.js DELETED
@@ -1,94 +0,0 @@
1
- import { appendFile, mkdir, readFile } from "node:fs/promises";
2
- import path from "node:path";
3
- /**
4
- * Phase-2 dogfood tally (council 2026-06-30): ~30 human-scored datapoints over
5
- * ~2 weeks of real use, per injection surface, never a CI gate. Data lives as
6
- * JSONL under `<stateDir>/tally/` — deliberately OUTSIDE the memory corpus so
7
- * the corpus Phase 2 measures stays clean.
8
- */
9
- export const TALLY_TARGET = 30;
10
- export const TALLY_VERDICTS = ["helpful", "harmless", "harmful", "correct-abstention"];
11
- export function isTallyVerdict(value) {
12
- return typeof value === "string" && TALLY_VERDICTS.includes(value);
13
- }
14
- export function ratingsPath(stateDir) {
15
- return path.join(stateDir, "tally", "ratings.jsonl");
16
- }
17
- export function eventsPath(stateDir) {
18
- return path.join(stateDir, "tally", "events.jsonl");
19
- }
20
- async function appendLine(file, record) {
21
- await mkdir(path.dirname(file), { recursive: true });
22
- await appendFile(file, `${JSON.stringify(record)}\n`, "utf8");
23
- }
24
- export async function appendTallyRating(stateDir, rating) {
25
- await appendLine(ratingsPath(stateDir), rating);
26
- }
27
- export async function appendTallyEvent(stateDir, event) {
28
- await appendLine(eventsPath(stateDir), event);
29
- }
30
- export async function readTallyRatings(stateDir) {
31
- let raw;
32
- try {
33
- raw = await readFile(ratingsPath(stateDir), "utf8");
34
- }
35
- catch {
36
- return [];
37
- }
38
- const ratings = [];
39
- for (const line of raw.split("\n")) {
40
- if (!line.trim()) {
41
- continue;
42
- }
43
- try {
44
- const parsed = JSON.parse(line);
45
- if (isTallyVerdict(parsed.verdict)) {
46
- ratings.push(parsed);
47
- }
48
- }
49
- catch {
50
- // A corrupt line loses one datapoint, never the tally.
51
- }
52
- }
53
- return ratings;
54
- }
55
- export function summarizeTally(ratings) {
56
- const by_verdict = {
57
- helpful: 0,
58
- harmless: 0,
59
- harmful: 0,
60
- "correct-abstention": 0,
61
- };
62
- const by_surface = {};
63
- for (const rating of ratings) {
64
- by_verdict[rating.verdict] += 1;
65
- by_surface[rating.surface || "unknown"] = (by_surface[rating.surface || "unknown"] ?? 0) + 1;
66
- }
67
- return {
68
- total: ratings.length,
69
- target: TALLY_TARGET,
70
- by_verdict,
71
- by_surface,
72
- ...(ratings.length > 0
73
- ? { first_at: ratings[0].ts, last_at: ratings[ratings.length - 1].ts }
74
- : {}),
75
- };
76
- }
77
- export function renderTallySummary(summary) {
78
- const lines = [
79
- `Dogfood tally: ${summary.total}/${summary.target} datapoints`,
80
- ` helpful: ${summary.by_verdict.helpful} harmless: ${summary.by_verdict.harmless} ` +
81
- `harmful: ${summary.by_verdict.harmful} correct-abstention: ${summary.by_verdict["correct-abstention"]}`,
82
- ];
83
- const surfaces = Object.entries(summary.by_surface)
84
- .map(([surface, count]) => `${surface}:${count}`)
85
- .join(" ");
86
- if (surfaces) {
87
- lines.push(` by surface: ${surfaces}`);
88
- }
89
- if (summary.first_at && summary.last_at) {
90
- lines.push(` window: ${summary.first_at} .. ${summary.last_at}`);
91
- }
92
- return lines.join("\n");
93
- }
94
- //# sourceMappingURL=tally.js.map
package/dist/tally.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"tally.js","sourceRoot":"","sources":["../src/tally.ts"],"names":[],"mappings":"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"}