obsidian-lean-coder 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to OLC (Obsidian Lean Coder) are recorded here.
4
4
  OLC is pre-release: versions are `0.x` until a controlled-testing release says otherwise.
5
5
  `package.json` shipped `"private": true` through 0.1.0; the flag was removed at publish time with explicit user approval, and 0.1.0 is live as [`obsidian-lean-coder`](https://www.npmjs.com/package/obsidian-lean-coder). Publishing a new version is still a separate explicitly approved action, never automatic.
6
6
 
7
+ ## [0.3.0] — 2026-10-13 — primary agents + all PRD skills
8
+
9
+ Agents `olc-plan`/`olc-build` move from `mode: subagent` (@-only invocation) to `mode: primary`,
10
+ so they appear in the OpenCode agent switcher (user decision).
11
+ Ships the four missing PRD §7.3 skill wrappers — `olc-init`, `olc-memory`, `olc-log`, `olc-taste` —
12
+ alongside the existing `olc-explore`; `olc-setup` installs all 7 owned files (2 agents + 5 skills).
13
+ Each SKILL.md documents its module's real contract (init create-only flow, progressive recall,
14
+ secret-scrubbed append-only log + session summary, pending→active taste lifecycle).
15
+
16
+ - **Verification:** `tests/setup.test.ts` counts updated (7 created/skipped); full suite green;
17
+ typecheck/build clean.
18
+ - **Upgrade:** `npm install obsidian-lean-coder@0.3.0`, then
19
+ `npx obsidian-lean-coder setup` (existing files are overwritten with package versions).
20
+
7
21
  ## [0.2.0] — 2026-10-13 — `olc-setup` resource installer
8
22
 
9
23
  New `olc-setup setup [--project|--global]` command (run manually via `npx obsidian-lean-coder setup`
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OLC — Obsidian Lean Coder
2
2
 
3
- OpenCode extension for project-scoped planning, memory, and safe Git checkpoints. On npm as `obsidian-lean-coder` (v0.1.1 fixes plugin activation — see CHANGELOG).
3
+ OpenCode extension for project-scoped planning, memory, and safe Git checkpoints. On npm as `obsidian-lean-coder` (v0.3.0: primary agents + all 5 skills — see CHANGELOG).
4
4
 
5
5
  ## Three separate steps
6
6
 
@@ -24,7 +24,7 @@ npm test # tsc -p tsconfig.tests.json && node --test "dist-tests/tests/*
24
24
  npm run typecheck
25
25
  ```
26
26
 
27
- Expected: build clean, typecheck clean. `npm test` runs the full suite (currently 140 tests). `npm pack --dry-run` shows what would ship (`dist/`, `agents/`, `skills/`, `templates/`).
27
+ Expected: build clean, typecheck clean. `npm test` runs the full suite (currently 146 tests). `npm pack --dry-run` shows what would ship (`dist/`, `agents/`, `skills/`, `templates/`).
28
28
 
29
29
  > Published on npm as `obsidian-lean-coder` (MIT). Republishing needs a separate explicit approval — never publish by accident.
30
30
 
@@ -81,18 +81,18 @@ Manual equivalent (DECISIONS.md #2 — programmatic registration was rejected fo
81
81
 
82
82
  ```sh
83
83
  PKG=/home/you/olc # your OLC checkout
84
- mkdir -p .opencode/agents .opencode/skills/olc-explore
84
+ mkdir -p .opencode/agents .opencode/skills/olc-init .opencode/skills/olc-explore .opencode/skills/olc-memory .opencode/skills/olc-log .opencode/skills/olc-taste
85
85
  cp "$PKG"/agents/olc-plan.md "$PKG"/agents/olc-build.md .opencode/agents/
86
- cp "$PKG"/skills/olc-explore/SKILL.md .opencode/skills/olc-explore/
86
+ for s in olc-init olc-explore olc-memory olc-log olc-taste; do cp "$PKG"/skills/$s/SKILL.md .opencode/skills/$s/; done
87
87
  ```
88
88
 
89
89
  Discovery note: `/api/agent` and `/api/skill` returned `[]` for project-local files in this build — even for a minimal probe agent — so API listing is not a valid verification (OLC-012 evidence did not reproduce; TUI-side discovery untested). Verify by file presence instead:
90
90
 
91
91
  ```sh
92
- ls .opencode/agents/olc-plan.md .opencode/agents/olc-build.md .opencode/skills/olc-explore/SKILL.md
92
+ ls .opencode/agents/olc-plan.md .opencode/agents/olc-build.md .opencode/skills/olc-init/SKILL.md .opencode/skills/olc-explore/SKILL.md .opencode/skills/olc-memory/SKILL.md .opencode/skills/olc-log/SKILL.md .opencode/skills/olc-taste/SKILL.md
93
93
  ```
94
94
 
95
- `olc-plan`/`olc-build` agents and the `olc-explore` skill are picked up by OpenCode from these paths. Re-running the `cp` commands is safe as long as you have not customized the destination files — `cp` overwrites; the no-clobber guarantee belongs to `olc-init`, which reports existing files as `preserved` instead of overwriting them.
95
+ `olc-plan`/`olc-build` agents and the five skills (`olc-init`, `olc-explore`, `olc-memory`, `olc-log`, `olc-taste`) are picked up by OpenCode from these paths. Re-running the `cp` commands is safe as long as you have not customized the destination files — `cp` overwrites; the no-clobber guarantee belongs to `olc-init`, which reports existing files as `preserved` instead of overwriting them.
96
96
 
97
97
  Supported versions: OpenCode 2.x with the V2 plugin API. OLC pins `@opencode/plugin` 2.0.27 to match the CLI it was smoke-tested against (see OLC-011). Other 2.x versions will likely work; 1.x will not. The exact minimum version is still open (DECISIONS.md #3).
98
98
 
@@ -128,7 +128,8 @@ Per consuming project:
128
128
  ```sh
129
129
  # 1. Remove OLC resources from the project
130
130
  rm -rf .opencode/agents/olc-plan.md .opencode/agents/olc-build.md \
131
- .opencode/skills/olc-explore .olc
131
+ .opencode/skills/olc-init .opencode/skills/olc-explore .opencode/skills/olc-memory \
132
+ .opencode/skills/olc-log .opencode/skills/olc-taste .olc
132
133
  # 2. Remove the plugin entry from opencode.json ("plugin": ["file:///..."])
133
134
  # 3. Optionally remove the vault scope (YOUR NOTES — back up first):
134
135
  # rm -rf "$VAULT/OLC/Projects/<project_id>"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: OLC build agent — implements one approved task step at a time with evidence-backed verification
3
- mode: subagent
3
+ mode: primary
4
4
  ---
5
5
 
6
6
  You are `olc-build`, the implementation agent of OLC (Obsidian Lean Coder).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: OLC planning agent — investigates a task and writes intent.md + plan.md without touching app source
3
- mode: subagent
3
+ mode: primary
4
4
  ---
5
5
 
6
6
  You are `olc-plan`, the planning agent of OLC (Obsidian Lean Coder).
package/bin/olc-setup.js CHANGED
@@ -32,7 +32,11 @@ import { fileURLToPath } from "node:url";
32
32
  const OWNED_FILES = [
33
33
  ["agents/olc-plan.md", ".opencode/agents/olc-plan.md"],
34
34
  ["agents/olc-build.md", ".opencode/agents/olc-build.md"],
35
+ ["skills/olc-init/SKILL.md", ".opencode/skills/olc-init/SKILL.md"],
35
36
  ["skills/olc-explore/SKILL.md", ".opencode/skills/olc-explore/SKILL.md"],
37
+ ["skills/olc-memory/SKILL.md", ".opencode/skills/olc-memory/SKILL.md"],
38
+ ["skills/olc-log/SKILL.md", ".opencode/skills/olc-log/SKILL.md"],
39
+ ["skills/olc-taste/SKILL.md", ".opencode/skills/olc-taste/SKILL.md"],
36
40
  ];
37
41
 
38
42
  function usage() {
package/dist/index.d.ts CHANGED
@@ -10,5 +10,5 @@
10
10
  * `plugin.ts` tool `execute` (deferred to call time), so this re-export
11
11
  * cycle is safe under ESM live bindings.
12
12
  */
13
- export declare const OLC_VERSION = "0.2.0";
13
+ export declare const OLC_VERSION = "0.3.0";
14
14
  export { default } from "./plugin.js";
package/dist/index.js CHANGED
@@ -10,5 +10,5 @@
10
10
  * `plugin.ts` tool `execute` (deferred to call time), so this re-export
11
11
  * cycle is safe under ESM live bindings.
12
12
  */
13
- export const OLC_VERSION = "0.2.0";
13
+ export const OLC_VERSION = "0.3.0";
14
14
  export { default } from "./plugin.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obsidian-lean-coder",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Obsidian Lean Coder — OpenCode extension for project-scoped planning, memory, and safe Git checkpoints.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: olc-init
3
+ description: Daftarkan satu repo app + vault ke OLC secara aman dan idempotent. Create-only — tidak pernah menimpa file yang sudah ada.
4
+ ---
5
+
6
+ # olc-init
7
+
8
+ Inisialisasi proyek OLC: mengusulkan `project_id`, mengonfirmasi vault path, menyiapkan `.olc/` dan struktur vault, lalu mendaftarkan pasangan repo↔vault di registry.
9
+
10
+ ## Aturan keras
11
+
12
+ 1. **Jelaskan dulu sebelum menulis.** Sebutkan file apa saja yang akan dibuat sebelum memanggil `initProject`.
13
+ 2. **Create-only.** File yang sudah ada dilaporkan `preserved` — tidak pernah ditimpa. Yang butuh keputusan manusia dikembalikan sebagai `status: "needs-decision"` dengan pesan yang bisa ditindaklanjuti.
14
+ 3. **Tidak ada tebakan vault.** Urutan: `vaultPath` eksplisit > env `OLC_VAULT_PATH` > config yang ada. Bila tidak ada, minta ke user — jangan membuat lokasi default diam-diam.
15
+ 4. **Tidak ada prompting di dalam modul.** Kumpulkan jawaban dulu, lalu panggil ulang dengan parameter lengkap.
16
+
17
+ ## Alur
18
+
19
+ 1. Panggil `initProject({ projectRoot })` — dapatkan usulan `project_id` (turunan nama repo yang disanitasi).
20
+ 2. Bila `status: "needs-decision"`, tanyakan ke user: konfirmasi `projectId`, isi `vaultPath`, atau selesaikan duplikat id sesuai pesan.
21
+ 3. Panggil ulang dengan `{ projectRoot, projectId, vaultPath }` hingga `status: "ready"`.
22
+ 4. Laporkan ringkasan `created` / `preserved` / `attention` ke user dalam bahasa sederhana.
23
+ 5. Untuk pratinjau tanpa menulis: `initProject({ ..., dryRun: true })` — `created` berarti "akan dibuat".
24
+
25
+ ## Yang dibuat (hanya bila belum ada)
26
+
27
+ - `<repo>/.olc/config.json` — `{ schemaVersion, projectId, vaultPath }`. Kunci berbau kredensial (`secret|token|password|api-key`) ditolak.
28
+ - `<repo>/.olc/AGENTS.md` — stub instruksi, minta user meninjau dan menyesuaikan.
29
+ - `<vault>/OLC/Projects/<project_id>/{index.md, current-state.md, decisions/, tasks/, logs/, memory/, taste/}`
30
+ - Entri `{ projects: { "<id>": { repoRoot } } }` di `<vault>/OLC/registry.json`.
31
+
32
+ ## Verifikasi skill ini
33
+
34
+ - Jalankan init dua kali di fixture repo/vault sementara: larian kedua semua `preserved`, tidak ada byte berubah.
35
+ - Init dengan config + instruksi kustom yang sudah ada: file kustom tetap identik.
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: olc-log
3
+ description: Catat event penting, checkpoint, dan ringkasan sesi ke log aktivitas harian yang tahan lama. Terverifikasi anti rusak dan anti bocor rahasia.
4
+ ---
5
+
6
+ # olc-log
7
+
8
+ Log aktivitas abadi per proyek di `<vault>/OLC/Projects/<project_id>/logs/YYYY-MM-DD.md` (satu file per hari — itulah rotasinya, tanpa rotasi ukuran untuk MVP).
9
+
10
+ ## Aturan keras
11
+
12
+ 1. **Hanya event eksplisit.** Modul tidak hook ke tool call — tidak ada noise per-tool-call secara konstruksi. Catat hanya milestone, checkpoint, verifikasi, dan ringkasan sesi.
13
+ 2. **Rahasia disensor, tidak disimpan.** Pola kredensial yang dikenal di summary/details diganti `[redacted]` dan entri ditandai.
14
+ 3. **Append aman.** Satu write `O_APPEND` per entri; interupsi tidak pernah merusak entri sebelumnya. File tanpa newline akhir (sisa crash) dinormalisasi sebelum append berikutnya.
15
+ 4. **Identitas dulu.** Vault salah → throw dengan nol file dibuat.
16
+
17
+ ## Alur
18
+
19
+ 1. Tulis: `logEvent({ projectRoot, config, event: { kind, summary, taskId?, details?, gitSha?, date? } })` — `kind` mis. `milestone|checkpoint|verify|session`; `summary` non-kosong wajib.
20
+ 2. Baca: `readLogDay(vaultRoot, projectId, day)` atau `readLastEvents(vaultRoot, projectId, limit)` (urutan terbaru dulu — verifikasi terakhir terlihat di sana).
21
+ 3. Akhir sesi normal: panggil `buildSessionSummary` (modul `session`) — teks Indonesia via template `session-summary` + footer jujur hard-kill, klaim faktual hanya dari `VerifyOutcome`/SHA/checkpoint nyata — lalu tampilkan ke user. Sesi yang mati mendadak tidak menghasilkan ringkasan; event log terakhir adalah titik pemulihan (lihat resume).
22
+
23
+ ## Verifikasi skill ini
24
+
25
+ - Rahasia pola `sk-...`, `ghp_...`, `AKIA...` di summary tidak pernah sampai ke vault (jadi `[redacted]`).
26
+ - Interupsi di tengah append tidak merusak entri sebelumnya.
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: olc-memory
3
+ description: Cari dan perbarui catatan memori proyek secara progresif — baca yang kecil dulu, hanya yang relevan dengan query. Tidak pernah memindai seluruh vault.
4
+ ---
5
+
6
+ # olc-memory
7
+
8
+ Ingatan berlingkup proyek: baca `index.md` + `current-state.md` dulu, lalu hanya dokumen `memory/` + `decisions/`, doc task, dan event log yang relevan dengan query. Tulis balik hanya di scope proyek yang tervalidasi.
9
+
10
+ ## Aturan keras
11
+
12
+ 1. **Identitas dulu.** `validateIdentity` harus lolos sebelum baca/tulis apa pun. Proyek salah atau vault tak tersedia → gagal dengan nol file tersentuh.
13
+ 2. **Tidak memindai folder proyek lain.** Semua path di-resolve di dalam `<vault>/OLC/Projects/<id>/`; folder lain tidak tersentuh secara konstruksi.
14
+ 3. **Tulis terkontrol.** `recordMemory` butuh nama polos (huruf/angka/dash/underscore, tanpa path/ekstensi) + konten non-kosong; file yang sudah ada tidak ditimpa diam-diam (`overwrite` eksplisit).
15
+
16
+ ## Alur
17
+
18
+ 1. Panggil `recallMemory({ projectRoot, config, query?, taskId?, includeLogs?, logLimit?, limit? })` — tanpa query = konteks dasar (index + state + log terbaru, tanpa filter).
19
+ 2. Dengan query: token query difilter stopwords, skor per dokumen `memory/` + `decisions/` (bobot nama file), kutipan dibatasi 1200 karakter dengan flag truncasi, urutan skor terbaik dulu.
20
+ 3. Dengan `taskId`: sertakan status doc intent/plan task itu (hilang → null, bukan error).
21
+ 4. Untuk menyimpan: `recordMemory({ projectRoot, config, name, content, overwrite? })` → `memory/<name>.md` atomik.
22
+
23
+ ## Verifikasi skill ini
24
+
25
+ - Ingatan proyek A tidak pernah muncul saat recall di proyek B (isolasi multi-proyek).
26
+ - Setiap klaim relevansi bisa ditelusur ke dokumen + barisnya, bukan karangan.
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: olc-taste
3
+ description: Pelajari preferensi khas proyek tanpa mengubah perilaku diam-diam. Sinyal berulang jadi usulan pending; hanya persetujuan user yang mengaktifkan.
4
+ ---
5
+
6
+ # olc-taste
7
+
8
+ Selera proyek dipelajari tanpa silent behavior change: sinyal berulang dicatat sebagai proposal `pending` lengkap dengan contoh/bukti, dan hanya keputusan user eksplisit yang mengubahnya jadi `active`. Penolakan memarkirnya sebagai `rejected` (riwayat, tidak pernah dipakai). Rule `pending` tidak pernah diperlakukan sebagai aktif oleh konsumen mana pun.
9
+
10
+ ## Aturan keras
11
+
12
+ 1. **Hanya user yang mengaktifkan.** Tidak ada jalur otomatis pending→active. Review terminal: `active`/`rejected` tidak bisa di-review ulang (`BAD_TRANSITION`).
13
+ 2. **Scope satu proyek.** Semua path di dalam `taste/` proyek tervalidasi; proyek lain tidak tersentuh. Modul ini tidak pernah menyentuh `tasks/` — intent/plan yang disetujui tidak bisa tertimpa dari sini.
14
+ 3. **Usulan butuh bukti.** Tanpa ≥1 contoh/sinyal berulang, usulan ditolak langsung (`INVALID_INPUT`). Duplikat tidak digabung diam-diam (`ALREADY_EXISTS`).
15
+
16
+ ## Alur
17
+
18
+ 1. Usulkan: `proposeTasteRule({ projectRoot, config, name, rule, examples[] })` → `taste/<name>.md` status `pending` via template `taste-rule`, write atomik create-only.
19
+ 2. Baca: `getTasteRule(...)` / `listTasteRules({ status? })` — hanya di scope tervalidasi, urut nama.
20
+ 3. Review eksplisit bersama user: `reviewTasteRule({ projectRoot, config, name, approve })` — `true` = pending→active, `false` = pending→rejected. Nama tak dikenal → `UNKNOWN_RULE`.
21
+
22
+ ## Verifikasi skill ini
23
+
24
+ - Rule `pending` tidak muncul di daftar `active`.
25
+ - `approve` mengaktifkan, `reject` memarkir; review ulang status terminal gagal.
26
+ - Intent/plan task byte-identik sebelum dan sesudah siklus propose→review.