akm-opencode 0.9.20202609302253 → 0.9.20202610010009

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 CHANGED
@@ -45,7 +45,7 @@ The plugin subscribes to OpenCode lifecycle events. Hook failures are logged thr
45
45
  | --- | --- |
46
46
  | `session.created` | Warms local data in the background, and prepares hints, an active-workflow summary, and curated context for the session. |
47
47
  | `session.updated` | Backfills hints and the workflow summary for a session the plugin has not prepared yet. It does not re-run session-created work. |
48
- | `chat.message` | Records feedback/memory intent, captures corrections, guardrails, preferences, explicit memories, and positive feedback, and can schedule non-blocking curation. High-confidence durable signals submit asynchronous AKM proposals; recurring task intent across distinct sessions can submit a skill proposal. |
48
+ | `chat.message` | Records feedback/memory intent, captures corrections, guardrails, preferences, explicit memories, and positive feedback, and can schedule non-blocking curation. High-confidence durable signals submit asynchronous AKM proposals; recurring task intent across distinct sessions can submit a skill proposal. Only the text you typed counts; the synthetic parts OpenCode adds (an attached file's contents, the Read call that fetched it) are ignored. |
49
49
  | `experimental.chat.system.transform` | Injects the AKM guidance and cached curated context into the system prompt. The host rebuilds the system prompt on every request, so these blocks are re-injected each turn — including after a compaction — rather than once per session. |
50
50
  | `tool.execute.before` | The format-declaration write gate (`AKM_WRITE_GATE`, `observe` by default). Blocks the first `edit`/`write` to an existing file that declares a format your bundle documents and hands the model the ref to read. Once per file per session, released unconditionally on the retry. |
51
51
  | `tool.execute.after` | Tracks concepts used by AKM tools and checkpoints session observations. It also records what a file the session `read` declares about its own format, which is what the write gate above keys on. `write` is deliberately not a source: a file the session created is not one it needs the bundle to explain. The create itself is recorded on the write's `tool.execute.before` pass, so a later read-back of that file cannot re-arm the gate. |
package/dist/index.js CHANGED
@@ -1009,6 +1009,7 @@ function isFile(file) {
1009
1009
  }
1010
1010
  }
1011
1011
  function conceptExistsInAnyBundle(conceptId, bundleRoots) {
1012
+ const type = conceptId.split("/", 1)[0];
1012
1013
  for (const root of bundleRoots) {
1013
1014
  if (!root)
1014
1015
  continue;
@@ -1016,12 +1017,18 @@ function conceptExistsInAnyBundle(conceptId, bundleRoots) {
1016
1017
  const directPath = path3.resolve(resolvedRoot, conceptId);
1017
1018
  if (directPath !== resolvedRoot && !directPath.startsWith(`${resolvedRoot}${path3.sep}`))
1018
1019
  continue;
1019
- if (isFile(directPath) || isFile(`${directPath}.md`))
1020
- return true;
1021
- if (isFile(path3.join(directPath, "SKILL.md")))
1022
- return true;
1023
- if (conceptId.startsWith("memories/") && isFile(`${directPath}.derived.md`))
1024
- return true;
1020
+ if (type === "skills") {
1021
+ if (isFile(path3.join(directPath, "SKILL.md")))
1022
+ return true;
1023
+ } else if (type === "scripts" || type === "secrets") {
1024
+ if (isFile(directPath))
1025
+ return true;
1026
+ } else {
1027
+ if (isFile(`${directPath}.md`) || directPath.endsWith(".md") && isFile(directPath))
1028
+ return true;
1029
+ if (type === "memories" && isFile(`${directPath}.derived.md`))
1030
+ return true;
1031
+ }
1025
1032
  }
1026
1033
  return false;
1027
1034
  }
@@ -1042,9 +1049,10 @@ function validateRefCandidates(candidates, bundleRoots) {
1042
1049
 
1043
1050
  // ../claude/shared/recall-policy.ts
1044
1051
  var STASH_BOILERPLATE = "This is an **AKM stash** \u2014 a structured knowledge repository that stores reusable";
1052
+ var COMPACTION_CONTINUATION = "This session is being continued from a previous conversation";
1045
1053
  function isNonTaskPrompt(text) {
1046
1054
  const stripped = text.trimStart();
1047
- if (stripped === STASH_BOILERPLATE)
1055
+ if (stripped === STASH_BOILERPLATE || stripped.startsWith(COMPACTION_CONTINUATION))
1048
1056
  return true;
1049
1057
  return stripped.startsWith("<") && stripped.includes("</");
1050
1058
  }
@@ -2927,7 +2935,7 @@ function extractText(parts) {
2927
2935
  return "";
2928
2936
  const segments = [];
2929
2937
  for (const part of parts) {
2930
- if (part?.type === "text" && typeof part.text === "string") {
2938
+ if (part?.type === "text" && !part.synthetic && typeof part.text === "string") {
2931
2939
  const raw = part.text.trim();
2932
2940
  let text = raw;
2933
2941
  if (raw.startsWith('"') && raw.endsWith('"')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-opencode",
3
- "version": "0.9.20202609302253",
3
+ "version": "0.9.20202610010009",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for AKM with discovery tools, feedback, memory, and automatic learning proposals from corrections and recurring workflows.",
6
6
  "keywords": [