@vincemakes/kiso-task-ext 0.1.45

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kiso contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # kiso-task-ext
2
+
3
+ The kiso official task extension: long-horizon working memory (`task_set`),
4
+ the kernel untouched. Stateless — the list's memory is the session event
5
+ log, so it survives kill -9 and compaction.
6
+
7
+ ## How it is loaded
8
+
9
+ Since 0.1.45 this extension ships **built-in** with the kiso CLI — a fresh
10
+ install starts with it registered (the startup banner lists it), with zero
11
+ disk setup. The same artifact can also be installed as a user-level
12
+ extension: copy `dist/kiso-task.mjs` into `~/.kiso/extensions/` — the
13
+ user-layer loader accepts exactly this shape.
14
+
15
+ ## Configuration
16
+
17
+ None. No persistent resources.
18
+
19
+ ## Versioning
20
+
21
+ The version counter is this package's own. It is pinned exactly by the kiso
22
+ CLI it ships with; an extension release reaches CLI users through the next
23
+ CLI release.
@@ -0,0 +1,130 @@
1
+ /**
2
+ * kiso (foundation) official task extension — ⑥: long-horizon working memory,
3
+ * kernel untouched.
4
+ *
5
+ * task_set is a WHOLE-TABLE REPLACE (the CC whole-table-replace shape): the model
6
+ * sends the complete current list on every update — one item marked
7
+ * active/done, the rest carried over verbatim. Idempotent: the same items
8
+ * in → the same echo out, byte for byte.
9
+ *
10
+ * The extension is STATELESS — the list's memory is the SESSION EVENT LOG.
11
+ * The result (the normalized echo) is a durable tool-result message: it
12
+ * survives kill -9 (a resume rebuilds the projection from the log) and
13
+ * /compact (the result is tagged do-not-compact, so the summary layer's
14
+ * boundary never covers its round — the contrast with Claude Code's
15
+ * runtime-state checklist, which dies with the process).
16
+ *
17
+ * The content contract (the CLI's checklist cell parses this EXACT shape
18
+ * — keep it stable):
19
+ * [task] 3 items — 1 pending, 1 active, 1 done
20
+ * [pending] write the plan
21
+ * [active] implement the feature
22
+ * [done] verify with tests
23
+ * The first line is a count summary; every item line is
24
+ * `[<status>] <text>`. Unknown lines never appear — the echo is the
25
+ * canonical form.
26
+ */
27
+
28
+ const MAX_ITEMS = 50;
29
+ const MAX_TEXT = 500;
30
+ const STATUSES = ["pending", "active", "done"];
31
+
32
+ /** Parse + validate ONE call. Pure: same input, same echo. */
33
+ export function parseTaskSet(input) {
34
+ const raw = (input ?? {}).items;
35
+ if (!Array.isArray(raw)) {
36
+ return { error: "task_set: 'items' must be an array of {text, status}" };
37
+ }
38
+ if (raw.length > MAX_ITEMS) {
39
+ return { error: `task_set: at most ${MAX_ITEMS} items (got ${raw.length})` };
40
+ }
41
+ const items = [];
42
+ for (let i = 0; i < raw.length; i += 1) {
43
+ const item = raw[i];
44
+ if (typeof item !== "object" || item === null) {
45
+ return { error: `task_set: item ${i} is not an object` };
46
+ }
47
+ const status = item.status;
48
+ if (!STATUSES.includes(status)) {
49
+ return { error: `task_set: item ${i} status must be one of ${STATUSES.join("/")} (got "${String(status)}")` };
50
+ }
51
+ const text = typeof item.text === "string" ? item.text.trim() : "";
52
+ if (text === "") {
53
+ return { error: `task_set: item ${i} text must be a non-empty string` };
54
+ }
55
+ if (text.length > MAX_TEXT) {
56
+ return { error: `task_set: item ${i} text exceeds ${MAX_TEXT} chars (got ${text.length})` };
57
+ }
58
+ items.push({ text, status });
59
+ }
60
+ // CC's discipline: at most ONE active item — a second active means the
61
+ // model did not mark the previous step done. Refused loudly, never
62
+ // silently normalized.
63
+ const active = items.filter((it) => it.status === "active");
64
+ if (active.length > 1) {
65
+ return { error: `task_set: at most one active item (${active.length} are active — mark the others done first)` };
66
+ }
67
+ return { items };
68
+ }
69
+
70
+ /** The normalized echo — the deterministic, parseable canonical form. */
71
+ export function taskEcho(items) {
72
+ const counts = { pending: 0, active: 0, done: 0 };
73
+ for (const it of items) counts[it.status] += 1;
74
+ const lines = [
75
+ `[task] ${items.length} item${items.length === 1 ? "" : "s"} — ${counts.pending} pending, ${counts.active} active, ${counts.done} done`,
76
+ ...items.map((it) => `[${it.status}] ${it.text}`),
77
+ ];
78
+ return lines.join("\n");
79
+ }
80
+
81
+ export default function createTaskExtension() {
82
+ return {
83
+ name: "task",
84
+ tools: [
85
+ {
86
+ name: "task_set",
87
+ description:
88
+ "set the work plan as a whole-table replace: pass the COMPLETE current list (each item {text, status}) — at most one active. The result echoes the normalized list; it survives /compact and kill -9 (durable working memory).",
89
+ parameters: {
90
+ type: "object",
91
+ properties: {
92
+ items: {
93
+ type: "array",
94
+ items: {
95
+ type: "object",
96
+ properties: {
97
+ text: { type: "string", minLength: 1, maxLength: MAX_TEXT },
98
+ status: { type: "string", enum: STATUSES },
99
+ },
100
+ required: ["text", "status"],
101
+ },
102
+ maxItems: MAX_ITEMS,
103
+ },
104
+ },
105
+ required: ["items"],
106
+ },
107
+ execute: async (input) => {
108
+ const parsed = parseTaskSet(input);
109
+ if (parsed.error !== undefined) {
110
+ return { content: parsed.error, isError: true, errorKind: "invalid_input" };
111
+ }
112
+ return { content: taskEcho(parsed.items), isError: false, tags: ["do-not-compact"] };
113
+ },
114
+ },
115
+ ],
116
+ // The plan guidance — restrained, no runtime checks (a verification
117
+ // step is a discipline, not a gate).
118
+ systemPrompt: {
119
+ append: [
120
+ "Work planning (task_set):",
121
+ "- For a task with 3+ steps, call task_set once up front with one item",
122
+ " per step, and make the LAST item a verification step.",
123
+ "- Mark an item active just before you start it — at most one active.",
124
+ "- Mark an item done the moment its step completes, then call",
125
+ " task_set again with the whole updated list.",
126
+ "- For a single small step, skip the list and do the work directly.",
127
+ ].join("\n"),
128
+ },
129
+ };
130
+ }
package/index.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The published type surface of @vincemakes/kiso-task-ext: the default
3
+ * export is the FACTORY (the same contract the user-layer disk loader
4
+ * accepts — a KisoExtension or a factory returning one). The type import
5
+ * from kiso-core is compile-time only — the shipped bundle is
6
+ * self-contained, zero runtime dependencies.
7
+ */
8
+ import type { KisoExtension } from "@vincemakes/kiso-core";
9
+
10
+ declare const createTaskExtension: () => KisoExtension | Promise<KisoExtension>;
11
+ export default createTaskExtension;
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@vincemakes/kiso-task-ext",
3
+ "version": "0.1.45",
4
+ "description": "kiso official task extension \u2014 long-horizon working memory (task_set), kernel untouched",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "./dist/kiso-task.mjs",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./dist/kiso-task.mjs"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "index.d.ts",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "node build.mjs",
22
+ "typecheck": "tsc -p tsconfig.json",
23
+ "test": "vitest run"
24
+ },
25
+ "devDependencies": {
26
+ "@vincemakes/kiso-core": "0.1.35",
27
+ "@types/node": "^26.1.2",
28
+ "typescript": "^5.7.2",
29
+ "vitest": "^3.0.0"
30
+ }
31
+ }