obsidian-lean-coder 0.4.1 → 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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,44 @@ 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.5.1] — 2026-10-14 — English skill docs, concise install instructions
8
+
9
+ All 5 bundled skills (`olc-log`, `olc-explore`, `olc-init`, `olc-memory`,
10
+ `olc-taste`) are now written in English; code identifiers, paths, and
11
+ examples are unchanged. The README's install section is now a 3-command
12
+ quick start right under the brief, instead of a long three-step walkthrough;
13
+ the previous detailed content (dev install path, plugin activation, API
14
+ caveats) is preserved under a new `## Reference` section.
15
+
16
+ - **Verification:** typecheck/build clean; full suite green (152 tests,
17
+ no test changes needed — docs-only); `npm pack --dry-run` file check.
18
+ - **Upgrade:** `npm install obsidian-lean-coder@0.5.1`. No vault or config
19
+ changes required.
20
+
21
+ ## [0.5.0] — 2026-10-14 — vault cross-linking for the second-brain graph
22
+
23
+ Vault documents were isolated islands: no `[[wikilinks]]` connected intent to
24
+ plan, checkpoints to history, or the daily log to the task it recorded. Since
25
+ the vault is meant as the project's second brain, every bundled template now
26
+ ships a `## Terkait` section with relative wikilinks to its natural
27
+ neighbours (intent ↔ plan ↔ history ↔ checkpoint; explore reports and taste
28
+ rules back to the project hub; daily logs to the hub and, per entry, to the
29
+ task it concerns). `index.md` and `current-state.md` link to each other.
30
+ `decision.md` takes a new `related` variable so its links reflect the actual
31
+ decision (callers must supply it). `session-summary.md` stays link-free by
32
+ design — it has no fixed vault location, so it is returned in chat, never
33
+ written to a file.
34
+
35
+ This only affects newly rendered documents; pre-existing vault files from
36
+ earlier versions are not backfilled.
37
+
38
+ - **Verification:** typecheck/build clean; full suite green (152 tests,
39
+ including a new end-to-end fixture that walks every markdown file in a
40
+ generated vault and resolves every `[[...]]` target on disk);
41
+ `npm pack --dry-run` file check.
42
+ - **Upgrade:** `npm install obsidian-lean-coder@0.5.0`, then re-run any task
43
+ that still needs its docs drafted — existing docs keep their old content.
44
+
7
45
  ## [0.4.1] — 2026-10-14 — verification tooling rule for minimal harnesses
8
46
 
9
47
  `agents/olc-build.md` gains a verification rule from a real field report: prefer
package/README.md CHANGED
@@ -1,119 +1,119 @@
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.4.1: verification tooling rule for minimal harnesses — see CHANGELOG).
3
+ OpenCode extension for project-scoped planning, memory, and safe Git checkpoints. On npm as `obsidian-lean-coder` (v0.5.1: English skill docs, concise install — see CHANGELOG).
4
4
 
5
- ## Three separate steps
6
-
7
- Do not confuse these. They are different operations with different commands:
8
-
9
- | # | Step | What it does | Command |
10
- |---|------|--------------|---------|
11
- | 1 | **Dev install** | Install npm deps to hack on OLC itself | `npm ci && npm run build` |
12
- | 2 | **Plugin activation** | Load OLC as an OpenCode plugin | `npm i obsidian-lean-coder` + `opencode.json` snippet below |
13
- | 3 | **Project init** | Register one app repo + vault with OLC (`initProject`, idempotent, create-only) | via the `olc-init` skill in OpenCode (the tested path) |
14
-
15
- ## 1. Dev install
16
-
17
- Requirements: Node >= 18.18, npm, git.
18
-
19
- ```sh
20
- git clone <this-repo> olc && cd olc
21
- npm ci
22
- npm run build # tsc -p tsconfig.json → dist/
23
- npm test # tsc -p tsconfig.tests.json && node --test "dist-tests/tests/**/*.test.js"
24
- npm run typecheck
25
- ```
26
-
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
-
29
- > Published on npm as `obsidian-lean-coder` (MIT). Republishing needs a separate explicit approval — never publish by accident.
30
-
31
- ## 2. Plugin activation
5
+ ## Install
32
6
 
33
7
  ```sh
34
8
  npm install obsidian-lean-coder
35
9
  ```
36
10
 
37
- Then list it in your project's `opencode.json` (npm loaders resolve the package root `dist/index.js`, which since v0.1.1 carries the plugin default export alongside `OLC_VERSION`):
11
+ Add it to your project's `opencode.json`:
38
12
 
39
13
  ```json
40
- {
41
- "plugins": ["obsidian-lean-coder"]
42
- }
14
+ { "plugins": ["obsidian-lean-coder"] }
43
15
  ```
44
16
 
45
- Verify it loads (from the consuming project directory; the model call itself will fail without account funds, but plugin loading happens first):
17
+ Copy the agents/skills into `.opencode/` (idempotent — safe to re-run after upgrading):
46
18
 
47
19
  ```sh
48
- OPENCODE_LOG_LEVEL=DEBUG opencode run --standalone "hi" --print-logs 2>&1 | grep -E "loading plugin.*obsidian-lean-coder|failed to load plugin"
20
+ npx obsidian-lean-coder setup
49
21
  ```
50
22
 
51
- Expected: a `loading plugin ... obsidian-lean-coder` line and **zero** `failed to load plugin` lines. (Verified 2026-10-13 via the equivalent local-file shape against the real loader; npm-registry install itself verified in OLC-071.)
23
+ Then open OpenCode in the project and run the **olc-init** skill to register the repo with a vault — that's it. Everything below is reference detail (requirements, what each step actually does, uninstall, troubleshooting).
52
24
 
53
- > `npm install` alone shows nothing in OpenCode — that is normal. The package must be listed under `plugins`, and agents/skills never auto-appear: they are project-local files you copy yourself (next step). No restart or rebuild needed after editing `opencode.json`.
25
+ Requirements: OpenCode 2.x (V2 plugin API), Node >= 18.18.
54
26
 
55
- ### Local dev path (this checkout, no npm)
27
+ ## Reference
56
28
 
57
- An `index.js` under `.opencode/plugins/<name>/` auto-loads with no install step (proven in OLC-011, re-verified in OLC-071). The plugin entrypoint is `dist/plugin.js` (`src/plugin.ts` → `Plugin.define({ id: "olc" })`, one read-only `olc_status` tool, zero writes on load).
29
+ ### What `npx obsidian-lean-coder setup` does
58
30
 
59
- In your consuming project (replace `/home/you/olc` with your OLC checkout):
31
+ Installs `agents/olc-plan.md`, `agents/olc-build.md`, and the five skills
32
+ (`olc-init`, `olc-explore`, `olc-memory`, `olc-log`, `olc-taste`) under
33
+ `.opencode/` (project scope by default). `--global` installs under
34
+ `~/.config/opencode` instead; `--dry-run` previews with no writes. Missing
35
+ directories are created; existing OLC agent/skill files are overwritten with
36
+ the package versions (a deliberate exception to the create-only rule, scoped
37
+ to these files only — your own vault notes are never touched by this).
60
38
 
61
- ```sh
62
- PKG=/home/you/olc # your OLC checkout — build it first (step 1)
63
- mkdir -p .opencode/plugins/olc
64
- printf '%s\n' 'export { default } from "file://'"$PKG"'/dist/plugin.js";' > .opencode/plugins/olc/index.js
65
- printf '%s\n' '{ "type": "module", "dependencies": { "@opencode/plugin": "2.0.27" } }' > .opencode/plugins/olc/package.json
66
- ```
39
+ Both agents behave exactly like OpenCode's default Plan/Build agents first,
40
+ then add OLC rules: each session they read the project root `AGENTS.md` (if
41
+ present) and `.olc/AGENTS.md` (if present). If the two disagree, the OpenCode
42
+ default wins — the agent shows the conflict, suggests a fix, and stops for
43
+ your choice.
67
44
 
68
- Verify with the same `grep` as above, expecting `.opencode/plugins/olc/index.js` in the loading line.
45
+ ### What `olc-init` does
69
46
 
70
- Then install the agent/skill resources — recommended via the setup helper:
47
+ `initProject` (`src/init/index.ts`) registers one app repo + vault. It is
48
+ idempotent and **create-only**: existing files are reported `preserved`,
49
+ never overwritten. Anything needing a human choice comes back as
50
+ `status: "needs-decision"` — no prompting inside the module. During init you
51
+ are asked whether the project has extra rules beyond the main agents file;
52
+ confirmed additions go under "Additional project rules" in `.olc/AGENTS.md`.
71
53
 
72
- ```sh
73
- npx obsidian-lean-coder setup # project scope: ./.opencode
74
- npx obsidian-lean-coder setup --global # global scope: ~/.config/opencode
75
- npx obsidian-lean-coder setup --dry-run # preview, writes nothing
76
- ```
54
+ What it creates (only when missing):
77
55
 
78
- Missing directories are created; existing OLC agent/skill files are overwritten with the package
79
- versions (a deliberate exception to the create-only rule, scoped to these files only).
80
- Manual equivalent (DECISIONS.md #2 — programmatic registration was rejected for MVP):
56
+ - `<repo>/.olc/config.json` — `{ schemaVersion, projectId, vaultPath }`. No secrets (keys matching `secret|token|password|api-key` are rejected).
57
+ - `<repo>/.olc/AGENTS.md` — stub instructions for agents. Review and customize.
58
+ - `<vault>/OLC/Projects/<project_id>/{index.md, current-state.md, decisions/, tasks/, logs/, memory/, taste/}`
59
+ - `<vault>/OLC/registry.json` — `{ projects: { "<id>": { repoRoot } } }` entry for this repo.
81
60
 
82
- ```sh
83
- PKG=/home/you/olc # your OLC checkout
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
- cp "$PKG"/agents/olc-plan.md "$PKG"/agents/olc-build.md .opencode/agents/
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
- ```
61
+ Vault path precedence: explicit `vaultPath` > `OLC_VAULT_PATH` env > existing
62
+ config. OLC never invents a vault location — missing path returns
63
+ `needs-decision`, never a silent default. Re-running init is always safe:
64
+ `created` becomes `preserved`.
88
65
 
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:
66
+ ### Contributing to OLC itself
90
67
 
91
68
  ```sh
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
69
+ git clone <this-repo> olc && cd olc
70
+ npm ci
71
+ npm run build # tsc -p tsconfig.json → dist/
72
+ npm test # tsc -p tsconfig.tests.json && node --test "dist-tests/tests/**/*.test.js"
73
+ npm run typecheck
93
74
  ```
94
75
 
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
-
97
- Both agents behave exactly like OpenCode's default Plan/Build agents first, then add OLC rules: each session they read the project root `AGENTS.md` (if present) and `.olc/AGENTS.md` (if present). If the two disagree, the OpenCode default wins — the agent shows the conflict, suggests a fix, and stops for your choice. During `olc-init` you are asked whether the project has extra rules beyond the main agents file; confirmed additions go under "Aturan tambahan proyek" in `.olc/AGENTS.md`.
76
+ Expected: build clean, typecheck clean, full suite green (currently 152
77
+ tests). `npm pack --dry-run` shows what would ship (`dist/`, `agents/`,
78
+ `skills/`, `templates/`).
98
79
 
99
- 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).
80
+ A local checkout can be loaded without publishing: `.opencode/plugins/<name>/index.js`
81
+ re-exporting `file://<checkout>/dist/plugin.js` auto-loads with no install
82
+ step. See `docs/DECISIONS.md` and `docs/TASKS.md` for the full history if you
83
+ need it.
100
84
 
101
- ## 3. Project init
102
-
103
- `initProject` (`src/init/index.ts`) registers one app repo + vault. It is idempotent and **create-only**: existing files are reported `preserved`, never overwritten. Anything needing a human choice comes back as `status: "needs-decision"` — no prompting inside the module.
104
-
105
- Run it via the `olc-init` skill inside OpenCode (recommended — the only tested path for MVP). A programmatic import is not yet wired: the package entrypoint (`dist/index.js`) exports `OLC_VERSION` plus the plugin default, and `initProject` lives in `src/init/index.ts` for internal/agent use.
106
-
107
- What it creates (only when missing):
108
-
109
- - `<repo>/.olc/config.json` — `{ schemaVersion, projectId, vaultPath }`. No secrets (keys matching `secret|token|password|api-key` are rejected).
110
- - `<repo>/.olc/AGENTS.md` — stub instructions for agents. Review and customize.
111
- - `<vault>/OLC/Projects/<project_id>/{index.md, current-state.md, decisions/, tasks/, logs/, memory/, taste/}`
112
- - `<vault>/OLC/registry.json` — `{ projects: { "<id>": { repoRoot } } }` entry for this repo.
113
-
114
- Vault path precedence: explicit `vaultPath` > `OLC_VAULT_PATH` env > existing config. OLC never invents a vault location — missing path returns `needs-decision`, never a silent default.
85
+ > Published on npm as `obsidian-lean-coder` (MIT). Republishing needs a separate explicit approval — never publish by accident.
115
86
 
116
- Re-running init is always safe: run it again after pulling updates; `created` becomes `preserved`. To preview without writing: `initProject({ ..., dryRun: true })`.
87
+ ### Vault linking rules (second brain)
88
+
89
+ The vault is meant as the project's long-term memory, so every document a
90
+ template produces must be a node in Obsidian's link graph, not an isolated
91
+ file. Rules:
92
+
93
+ - Every bundled template carries a `## Terkait` section with **relative**
94
+ `[[wikilinks]]` to its natural neighbours — e.g. `intent.md` ↔ `plan.md` ↔
95
+ `history.md` ↔ `checkpoint.md`; `explore-report.md` and `taste-rule.md`
96
+ back to the project hub (`index.md`, `current-state.md`); each daily log
97
+ file links to the hub, and each logged event with a `taskId` links to that
98
+ task's `intent.md`/`plan.md`.
99
+ - `index.md` and `current-state.md` link to each other — they are the hub a
100
+ reader lands on first.
101
+ - Links are relative path-form (`[[../T-1/plan]]`, not a bare `[[plan]]`),
102
+ so they resolve correctly whether Obsidian's vault root is `<vault>` or
103
+ `<vault>/OLC/Projects/<id>`, and stay correct across multiple projects
104
+ sharing one vault (a bare `[[plan]]` would be ambiguous between projects).
105
+ - `decision.md` takes a `related` template variable — the caller supplies
106
+ the links relevant to that specific decision; there is no fixed set.
107
+ - `session-summary.md` is the one exception: it has no fixed vault location
108
+ (it's returned in chat for the user to read, never written to a file), so
109
+ it carries no links by design.
110
+ - **Limitation:** linking only applies to newly rendered documents. Older
111
+ vault files written by a previous OLC version are not backfilled with
112
+ links (see D-005 in `docs/TASKS.md`).
113
+ - Writing to `memory/<name>.md` via the `olc-memory` skill is free-form
114
+ (no template), but should still include a `## Terkait` section linking
115
+ back to `[[../index]]`/`[[../current-state]]` and any related task or
116
+ decision, to keep the memory graph connected.
117
117
 
118
118
  ## Updating
119
119
 
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.4.1";
13
+ export declare const OLC_VERSION = "0.5.1";
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.4.1";
13
+ export const OLC_VERSION = "0.5.1";
14
14
  export { default } from "./plugin.js";
@@ -26,8 +26,10 @@ const AGENTS_STUB = (projectId) => `# OLC project instructions — ${projectId}\
26
26
  "Bila bertentangan dengan perilaku default OpenCode, default yang menang — agen akan\n" +
27
27
  "menunjukkan konfliknya dan meminta keputusan Anda sebelum lanjut.\n\n" +
28
28
  "- (belum ada — tambahkan sesuai kebutuhan proyek)\n";
29
- const VAULT_INDEX = (projectId) => `# ${projectId}\n\nOLC project memory root. See current-state.md for the latest status.\n`;
30
- const VAULT_STATE = (projectId) => `# Current state — ${projectId}\n\nInitialized. No activity recorded yet.\n`;
29
+ const VAULT_INDEX = (projectId) => `# ${projectId}\n\nOLC project memory root. See current-state.md for the latest status.\n` +
30
+ `\n## Terkait\n\n- [[current-state]] — status terbaru proyek\n`;
31
+ const VAULT_STATE = (projectId) => `# Current state — ${projectId}\n\nInitialized. No activity recorded yet.\n` +
32
+ `\n## Terkait\n\n- [[index]] — hub memori proyek\n`;
31
33
  /** Derive a safe project_id proposal from the repository directory name. */
32
34
  export function proposeProjectId(repoRoot) {
33
35
  const cleaned = basename(resolve(repoRoot))
package/dist/log/index.js CHANGED
@@ -70,7 +70,8 @@ function ensureDayFile(path, projectId, day) {
70
70
  // "wx" fails when another process won the race — that is fine, the file
71
71
  // (with an identical header) already exists and we just append below.
72
72
  try {
73
- const header = withFrontmatter({ project: projectId, type: "activity-log", date: day }, "");
73
+ const header = withFrontmatter({ project: projectId, type: "activity-log", date: day }, "") +
74
+ "## Terkait\n\n- [[../index]] — hub memori proyek\n- [[../current-state]] — status terbaru proyek\n\n";
74
75
  appendFileSync(path, header.endsWith("\n") ? header : header + "\n", { flag: "wx" });
75
76
  }
76
77
  catch (error) {
@@ -91,6 +92,12 @@ function formatEntry(event, iso) {
91
92
  lines.push(`- sha: ${event.gitSha}`);
92
93
  if (redacted)
93
94
  lines.push(`- redacted: true`);
95
+ // Obsidian graph links toward the task docs. parseEntries does not know the
96
+ // `terkait` key and safely ignores it; it exists purely so every log entry
97
+ // is a clickable node in the vault graph (second-brain navigation).
98
+ if (event.taskId) {
99
+ lines.push(`- terkait: [[../tasks/${event.taskId}/intent]], [[../tasks/${event.taskId}/plan]]`);
100
+ }
94
101
  return lines.join("\n") + "\n";
95
102
  }
96
103
  /**
@@ -112,7 +112,10 @@ function appendHistory(vaultRoot, projectId, taskId, kind, reason, date) {
112
112
  existing = "";
113
113
  }
114
114
  const entry = `## ${date} — ${kind}\n\n${reason}\n`;
115
- writeVaultDoc(history, existing === "" ? `# History — ${taskId}\n\n${entry}` : `${existing}\n${entry}`, {
115
+ const header = `# History — ${taskId}\n\n## Terkait\n\n` +
116
+ `- [[../${taskId}/intent]] — maksud kerja\n` +
117
+ `- [[../${taskId}/plan]] — rencana kerja\n\n`;
118
+ writeVaultDoc(history, existing === "" ? `${header}${entry}` : `${existing}\n${entry}`, {
116
119
  overwrite: true,
117
120
  });
118
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obsidian-lean-coder",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
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",
@@ -1,35 +1,35 @@
1
1
  ---
2
2
  name: olc-explore
3
- description: Selidiki request yang kompleks/tidak pasti sebelum planning. Read-only terhadap app code; menghasilkan satu laporan eksplorasi di vault.
3
+ description: Investigate a complex/uncertain request before planning. Read-only against app code; produces a single exploration report in the vault.
4
4
  ---
5
5
 
6
6
  # olc-explore
7
7
 
8
- Klarifikasi request yang kompleks atau tidak pasti **sebelum** `intent.md`/`plan.md` dibuat.
9
- Untuk task sederhana yang sudah jelas, lewati skill ini dan langsung ke Plan (direct Plan).
8
+ Clarify a complex or uncertain request **before** `intent.md`/`plan.md` are created.
9
+ For simple, already-clear tasks, skip this skill and go straight to Plan (direct Plan).
10
10
 
11
- ## Kapan dipakai vs direct Plan
11
+ ## When to use vs direct Plan
12
12
 
13
- - Pakai Explore bila: request ambigu, menyentuh area yang belum dikenal, ada beberapa pendekatan dengan tradeoff nyata, atau risiko salah paham tinggi.
14
- - Direct Plan bila: perubahan kecil dan terlokalisasi, pendekatan sudah jelas, tidak ada pertanyaan material yang terbuka.
15
- - Pilihan user yang menang: kalau user minta direct Plan, jangan memaksa Explore, dan sebaliknya.
13
+ - Use Explore when: the request is ambiguous, touches unfamiliar territory, has multiple approaches with real tradeoffs, or carries a high risk of misunderstanding.
14
+ - Use direct Plan when: the change is small and localized, the approach is already clear, there are no material open questions.
15
+ - The user's choice wins: if the user asks for direct Plan, don't force Explore, and vice versa.
16
16
 
17
- ## Aturan keras
17
+ ## Hard rules
18
18
 
19
- 1. **Read-only terhadap app source.** Boleh membaca file, menjalankan perintah baca (status, log, test baca), menelusuri kode. DILARANG mengubah, menambah, atau menghapus file app dalam bentuk apa pun — tidak ada fix "sekalian", tidak ada refactor kecil.
20
- 2. Satu laporan aktif per task: `tasks/<task-id>/explore/report.md` di vault proyek yang sudah tervalidasi (OLC-021). Jangan membuat file laporan tandingan.
21
- 3. Setiap klaim temuan harus punya bukti: path file + baris, output perintah, atau kutipan config. Tanpa bukti = pertanyaan terbuka, bukan temuan.
22
- 4. Revisi tidak menghapus penalaran penting: revisi ditambahkan sebagai bagian baru bertanggal di laporan yang sama; alasan perubahan pendekatan harus tercatat.
19
+ 1. **Read-only against app source.** Allowed: reading files, running read-only commands (status, log, read-only tests), tracing code. FORBIDDEN: changing, adding, or removing app files in any way — no "while I'm at it" fixes, no small refactors.
20
+ 2. One active report per task: `tasks/<task-id>/explore/report.md` in the already-validated project vault (OLC-021). Do not create a competing report file.
21
+ 3. Every finding claim needs evidence: a file path + line, command output, or a config quote. No evidence = open question, not a finding.
22
+ 4. Revisions never erase important reasoning: a revision is added as a new dated section in the same report; the reason for the approach change must be recorded.
23
23
 
24
- ## Alur
24
+ ## Flow
25
25
 
26
- 1. Validasi identitas proyek dan baca `project_id` dari `.olc/config.json` (jangan operasi vault sebelum ini lolos).
27
- 2. Baca request user + konteks relevan secukupnya (index/current-state vault bila ada, file app terkait). Jangan membaca seluruh vault.
28
- 3. Tulis laporan via template `explore-report` (var: `task_id`, `project_id`, `date`, `request`, `findings`, `options`, `recommendation`). Buat direktori `explore/` bila belum ada; jangan menimpa laporan yang sudah dikustom tanpa persetujuan (ikuti aturan create-only OLC-023).
29
- 4. Bila request berubah atau temuan baru muncul: tambah bagian revisi bertanggal di laporan yang sama, catat alasan di `history.md` task.
30
- 5. Serahkan ke Plan: laporan explore adalah input `draftTaskDocs`, bukan pengganti `intent.md`/`plan.md`. Tanpa kedua dokumen itu disetujui, tidak ada coding (OLC-032).
26
+ 1. Validate project identity and read `project_id` from `.olc/config.json` (no vault operation passes before this).
27
+ 2. Read the user's request plus just enough relevant context (vault index/current-state if present, related app files). Do not read the entire vault.
28
+ 3. Write the report via the `explore-report` template (vars: `task_id`, `project_id`, `date`, `request`, `findings`, `options`, `recommendation`). Create the `explore/` directory if missing; never overwrite an already-customized report without approval (follow OLC-023's create-only rule).
29
+ 4. If the request changes or new findings appear: add a new dated revision section to the same report, record the reason in the task's `history.md`.
30
+ 5. Hand off to Plan: the explore report is input to `draftTaskDocs`, not a replacement for `intent.md`/`plan.md`. No coding happens until both documents are approved (OLC-032).
31
31
 
32
- ## Verifikasi skill ini
32
+ ## Verifying this skill
33
33
 
34
- - Setelah Explore: `git status --short` di repo app harus bersih (tidak ada perubahan app).
35
- - Laporan ada di path yang benar dan semua var template terisi (tidak ada `{{...}}` tersisa).
34
+ - After Explore: `git status --short` in the app repo must be clean (no app changes).
35
+ - The report exists at the correct path and every template var is filled (no leftover `{{...}}`).
@@ -1,39 +1,40 @@
1
1
  ---
2
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.
3
+ description: Safely and idempotently register one app repo + vault with OLC. Create-only — never overwrites existing files.
4
4
  ---
5
5
 
6
6
  # olc-init
7
7
 
8
- Inisialisasi proyek OLC: mengusulkan `project_id`, mengonfirmasi vault path, menyiapkan `.olc/` dan struktur vault, lalu mendaftarkan pasangan repo↔vault di registry.
8
+ Initialize an OLC project: propose a `project_id`, confirm the vault path, set up `.olc/` and the vault structure, then register the repo↔vault pair in the registry.
9
9
 
10
- ## Aturan keras
10
+ ## Hard rules
11
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.
12
+ 1. **Explain before writing.** State which files will be created before calling `initProject`.
13
+ 2. **Create-only.** Existing files are reported as `preserved` — never overwritten. Anything needing a human decision comes back as `status: "needs-decision"` with an actionable message.
14
+ 3. **No guessing the vault.** Precedence: explicit `vaultPath` > env `OLC_VAULT_PATH` > existing config. If none exist, ask the user — never silently create a default location.
15
+ 4. **No prompting inside the module.** Gather answers first, then call again with the full parameters.
16
16
 
17
- ## Alur
17
+ ## Flow
18
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. Tanyakan ke user: "Apakah ada aturan tambahan proyek selain yang ada di
23
- AGENTS.md utama?" Bila ada, tulis ke bagian "Aturan tambahan proyek" di
24
- `<repo>/.olc/AGENTS.md` (file itu create-only — bila sudah ada dan sudah
25
- berisi aturan, jangan ditimpa; gabungkan hanya bila user meminta).
26
- 5. Laporkan ringkasan `created` / `preserved` / `attention` ke user dalam bahasa sederhana.
27
- 5. Untuk pratinjau tanpa menulis: `initProject({ ..., dryRun: true })` — `created` berarti "akan dibuat".
19
+ 1. Call `initProject({ projectRoot })` — get a proposed `project_id` (sanitized derivative of the repo name).
20
+ 2. If `status: "needs-decision"`, ask the user: confirm `projectId`, fill in `vaultPath`, or resolve a duplicate id per the message.
21
+ 3. Call again with `{ projectRoot, projectId, vaultPath }` until `status: "ready"`.
22
+ 4. Ask the user: "Are there any additional project rules beyond what's in the
23
+ main AGENTS.md?" If yes, write them to the "Additional project rules"
24
+ section of `<repo>/.olc/AGENTS.md` (that file is create-only — if it
25
+ already exists and already has rules, don't overwrite; merge only if the
26
+ user asks).
27
+ 5. Report a `created` / `preserved` / `attention` summary to the user in plain language.
28
+ 5. To preview without writing: `initProject({ ..., dryRun: true })` — `created` means "would be created".
28
29
 
29
- ## Yang dibuat (hanya bila belum ada)
30
+ ## What gets created (only if missing)
30
31
 
31
- - `<repo>/.olc/config.json` — `{ schemaVersion, projectId, vaultPath }`. Kunci berbau kredensial (`secret|token|password|api-key`) ditolak.
32
- - `<repo>/.olc/AGENTS.md` — stub instruksi, minta user meninjau dan menyesuaikan.
32
+ - `<repo>/.olc/config.json` — `{ schemaVersion, projectId, vaultPath }`. Keys that look like credentials (`secret|token|password|api-key`) are rejected.
33
+ - `<repo>/.olc/AGENTS.md` — instruction stub, asks the user to review and adjust.
33
34
  - `<vault>/OLC/Projects/<project_id>/{index.md, current-state.md, decisions/, tasks/, logs/, memory/, taste/}`
34
- - Entri `{ projects: { "<id>": { repoRoot } } }` di `<vault>/OLC/registry.json`.
35
+ - An entry `{ projects: { "<id>": { repoRoot } } }` in `<vault>/OLC/registry.json`.
35
36
 
36
- ## Verifikasi skill ini
37
+ ## Verifying this skill
37
38
 
38
- - Jalankan init dua kali di fixture repo/vault sementara: larian kedua semua `preserved`, tidak ada byte berubah.
39
- - Init dengan config + instruksi kustom yang sudah ada: file kustom tetap identik.
39
+ - Run init twice against a temporary fixture repo/vault: the second run is all `preserved`, no byte changes.
40
+ - Init with existing config + custom instructions: the custom file stays byte-identical.
@@ -1,26 +1,26 @@
1
1
  ---
2
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.
3
+ description: Record important events, checkpoints, and session summaries into a durable daily activity log. Verified crash-safe and secret-leak-safe.
4
4
  ---
5
5
 
6
6
  # olc-log
7
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).
8
+ Durable per-project activity log at `<vault>/OLC/Projects/<project_id>/logs/YYYY-MM-DD.md` (one file per day — that's its only rotation, no size-based rotation for MVP).
9
9
 
10
- ## Aturan keras
10
+ ## Hard rules
11
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.
12
+ 1. **Explicit events only.** The module never hooks tool calls — no per-tool-call noise by construction. Log only milestones, checkpoints, verifications, and session summaries.
13
+ 2. **Secrets are redacted, never stored.** Known credential patterns in summary/details are replaced with `[redacted]` and the entry is flagged.
14
+ 3. **Safe appends.** One `O_APPEND` write per entry; an interruption never corrupts earlier entries. A file missing its trailing newline (crash remnant) is normalized before the next append.
15
+ 4. **Identity first.** Wrong vault → throw with zero files created.
16
16
 
17
- ## Alur
17
+ ## Flow
18
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).
19
+ 1. Write: `logEvent({ projectRoot, config, event: { kind, summary, taskId?, details?, gitSha?, date? } })` — `kind` e.g. `milestone|checkpoint|verify|session`; non-empty `summary` is required.
20
+ 2. Read: `readLogDay(vaultRoot, projectId, day)` or `readLastEvents(vaultRoot, projectId, limit)` (newest first — the last verification shows up there).
21
+ 3. Normal session end: call `buildSessionSummary` (module `session`) — rendered via the `session-summary` template with an honest hard-kill footer, factual claims sourced only from a real `VerifyOutcome`/SHA/checkpoint — then show it to the user. A session that dies abruptly produces no summary; the last log event is the recovery point (see resume).
22
22
 
23
- ## Verifikasi skill ini
23
+ ## Verifying this skill
24
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.
25
+ - Secret patterns like `sk-...`, `ghp_...`, `AKIA...` in a summary never reach the vault (they become `[redacted]`).
26
+ - An interruption mid-append never corrupts earlier entries.
@@ -1,26 +1,26 @@
1
1
  ---
2
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.
3
+ description: Search and update project memory notes progressively — read small first, only what's relevant to the query. Never scans the whole vault.
4
4
  ---
5
5
 
6
6
  # olc-memory
7
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.
8
+ Project-scoped memory: read `index.md` + `current-state.md` first, then only the `memory/` + `decisions/` documents, task docs, and log events relevant to the query. Write back only within the validated project scope.
9
9
 
10
- ## Aturan keras
10
+ ## Hard rules
11
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).
12
+ 1. **Identity first.** `validateIdentity` must pass before any read/write. Wrong project or unavailable vault → fail with zero files touched.
13
+ 2. **Never scans other projects' folders.** Every path resolves inside `<vault>/OLC/Projects/<id>/`; other folders are untouched by construction.
14
+ 3. **Controlled writes.** `recordMemory` requires a plain name (letters/digits/dash/underscore, no path/extension) plus non-empty content; existing files are never silently overwritten (`overwrite` must be explicit).
15
15
 
16
- ## Alur
16
+ ## Flow
17
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.
18
+ 1. Call `recallMemory({ projectRoot, config, query?, taskId?, includeLogs?, logLimit?, limit? })` — no query = base context (index + state + recent log, unfiltered).
19
+ 2. With a query: query tokens are filtered for stopwords, each `memory/` + `decisions/` document is scored (filename weighted), excerpts are capped at 1200 characters with a truncation flag, best score first.
20
+ 3. With `taskId`: include that task's intent/plan doc status (missing → null, not an error).
21
+ 4. To save: `recordMemory({ projectRoot, config, name, content, overwrite? })` → atomic write to `memory/<name>.md`. `content` must include a `## Terkait` section with relative wikilinks to `[[../index]]`, `[[../current-state]]`, and any related task/decision document — this keeps the memory note connected in the vault graph (second brain) instead of an isolated island.
22
22
 
23
- ## Verifikasi skill ini
23
+ ## Verifying this skill
24
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.
25
+ - Project A's memory never shows up on recall in project B (multi-project isolation).
26
+ - Every relevance claim is traceable to a document + line, not invented.
@@ -1,26 +1,26 @@
1
1
  ---
2
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.
3
+ description: Learn project-specific preferences without silently changing behavior. Repeated signals become pending proposals; only user approval activates them.
4
4
  ---
5
5
 
6
6
  # olc-taste
7
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.
8
+ Project taste is learned without silent behavior change: a repeated signal is recorded as a `pending` proposal complete with examples/evidence, and only an explicit user decision turns it `active`. Rejection parks it as `rejected` (kept as history, never used). A `pending` rule is never treated as active by any consumer.
9
9
 
10
- ## Aturan keras
10
+ ## Hard rules
11
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`).
12
+ 1. **Only the user activates.** There is no automatic pending→active path. Review is terminal: `active`/`rejected` cannot be re-reviewed (`BAD_TRANSITION`).
13
+ 2. **Single-project scope.** Every path lives inside the validated project's `taste/`; other projects are untouched. This module never touches `tasks/` — approved intent/plan can't be overwritten from here.
14
+ 3. **Proposals need evidence.** Without ≥1 example/repeated signal, a proposal is rejected outright (`INVALID_INPUT`). Duplicates are never silently merged (`ALREADY_EXISTS`).
15
15
 
16
- ## Alur
16
+ ## Flow
17
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`.
18
+ 1. Propose: `proposeTasteRule({ projectRoot, config, name, rule, examples[] })` → `taste/<name>.md` with status `pending`, via the `taste-rule` template, atomic create-only write.
19
+ 2. Read: `getTasteRule(...)` / `listTasteRules({ status? })` — only within the validated scope, name-sorted.
20
+ 3. Explicit review with the user: `reviewTasteRule({ projectRoot, config, name, approve })` — `true` = pending→active, `false` = pending→rejected. Unknown name → `UNKNOWN_RULE`.
21
21
 
22
- ## Verifikasi skill ini
22
+ ## Verifying this skill
23
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.
24
+ - A `pending` rule never appears in the `active` list.
25
+ - `approve` activates, `reject` parks; re-reviewing a terminal status fails.
26
+ - Task intent/plan stay byte-identical before and after a propose→review cycle.
@@ -5,6 +5,11 @@ date: {{date}}
5
5
 
6
6
  # Activity log — {{date}}
7
7
 
8
+ ## Terkait (dokumen terkait)
9
+
10
+ - [[../index]] — hub memori proyek
11
+ - [[../current-state]] — status terbaru proyek
12
+
8
13
  ## {{event}} ({{timestamp}})
9
14
 
10
15
  {{details}}
@@ -22,3 +22,9 @@ date: {{date}}
22
22
  ## Timestamp
23
23
 
24
24
  {{date}}
25
+
26
+ ## Terkait (dokumen terkait)
27
+
28
+ - [[../{{task_id}}/intent]] — maksud kerja
29
+ - [[../{{task_id}}/plan]] — rencana kerja
30
+ - [[../{{task_id}}/history]] — riwayat revisi keputusan
@@ -17,3 +17,7 @@ date: {{date}}
17
17
  ## Consequences (akibat / yang harus diikuti)
18
18
 
19
19
  {{consequences}}
20
+
21
+ ## Terkait (dokumen terkait)
22
+
23
+ {{related}}
@@ -21,3 +21,9 @@ date: {{date}}
21
21
  ## Recommendation (pilihan yang disarankan + alasan)
22
22
 
23
23
  {{recommendation}}
24
+
25
+ ## Terkait (dokumen terkait)
26
+
27
+ - [[../../{{task_id}}/intent]] — maksud kerja
28
+ - [[../../{{task_id}}/plan]] — rencana kerja
29
+ - [[../../index]] — hub memori proyek
@@ -21,3 +21,9 @@ project: {{project_id}}
21
21
  ## Open questions
22
22
 
23
23
  {{open_questions}}
24
+
25
+ ## Terkait (dokumen terkait)
26
+
27
+ - [[../{{task_id}}/plan]] — rencana kerja untuk intent ini
28
+ - [[../../index]] — hub memori proyek
29
+ - [[../../current-state]] — status terbaru proyek
package/templates/plan.md CHANGED
@@ -25,3 +25,10 @@ project: {{project_id}}
25
25
  ## Risks and open questions
26
26
 
27
27
  {{risks}}
28
+
29
+ ## Terkait (dokumen terkait)
30
+
31
+ - [[../{{task_id}}/intent]] — maksud dari rencana ini
32
+ - [[../{{task_id}}/history]] — riwayat revisi keputusan
33
+ - [[../../index]] — hub memori proyek
34
+ - [[../../current-state]] — status terbaru proyek
@@ -12,3 +12,8 @@ status: {{status}}
12
12
  ## Examples / evidence (contoh + bukti)
13
13
 
14
14
  {{examples}}
15
+
16
+ ## Terkait (dokumen terkait)
17
+
18
+ - [[../index]] — hub memori proyek
19
+ - [[../current-state]] — status terbaru proyek