@irisrun/bundle-coding 0.1.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.
@@ -0,0 +1,38 @@
1
+ import type { Bundle, Tactic } from "@irisrun/core";
2
+ /** The stable id pinned into `Lock.tactics.bundle` and journaled as the tacticId. */
3
+ export declare const BUNDLE_ID = "iris/coding";
4
+ export interface CodingBundleOptions {
5
+ /** Extra read-only tools to allow-list (merged with the coding defaults). */
6
+ readOnlyTools?: string[];
7
+ /** shouldCompact trailing-window size (passed to windowCompaction). */
8
+ keepLast?: number;
9
+ /** onToolError retry cap (passed to toolRepair). */
10
+ maxAttempts?: number;
11
+ invariants?: {
12
+ maxStepsPerTurn?: number;
13
+ maxToolCalls?: number;
14
+ };
15
+ }
16
+ /**
17
+ * The coding-specialized gateAction tactic: read-only / codebase-search tools are
18
+ * a safe ALLOW; every other tool — writes (`write_file`), shell (`run_shell`),
19
+ * and anything unknown/irreversible — is gated to "ask" (HITL). A host-side
20
+ * factory function (not a bare object), matching core's convention.
21
+ */
22
+ export declare function codingGate(readOnlyTools?: string[]): Tactic<"gateAction">;
23
+ /**
24
+ * The coding bundle's decideNext: it DELEGATES verbatim to the proven ReAct
25
+ * tool-loop (continue while the model still requests tools, finish when it stops) —
26
+ * which is the CORRECT policy for a coding tool-loop agent, so there is nothing to
27
+ * "tune" today. The coding-specific behavior lives in `codingGate` (the
28
+ * read-only-allow / write-gate split). This is kept as a DISTINCT factory only so a
29
+ * future coding heuristic (e.g. a max-edit budget) can layer in here without
30
+ * touching core or the bundle's call sites — it is a pass-through for now.
31
+ */
32
+ export declare function codingDecideNext(): Tactic<"decideNext">;
33
+ /**
34
+ * Assemble the coding bundle: the SAME structure as core's `defaultBundle`, with
35
+ * the coding-specialized gate + decideNext and the reused window-compaction /
36
+ * tool-repair tactics, returning `{ tacticPerformer, invariants }`.
37
+ */
38
+ export declare function codingBundle(opts?: CodingBundleOptions): Bundle;
package/dist/coding.js ADDED
@@ -0,0 +1,101 @@
1
+ // @irisrun/bundle-coding — the first domain (coding) tactic bundle. HOST-SIDE: it
2
+ // composes coding-specialized tactics on the 5 harness seams from @irisrun/core's
3
+ // EXPORTED primitives ([[lrn-core-exports-functions-only]]), so @irisrun/core stays
4
+ // byte-untouched. The assembled `codingBundle()` returns the SAME shape as core's
5
+ // `defaultBundle()` — a pure `tacticPerformer` (a Performer answering a
6
+ // {seam, payload} request with {seam, tacticId:"iris/coding", choice}) plus the
7
+ // kernel invariant caps. The journaled {seam, tacticId, choice} outcome rides the
8
+ // `tactic` effect's result value exactly like the default bundle, so the ADR-0007
9
+ // quarantine (replay folds the journaled choice, never re-invokes a tactic)
10
+ // applies to this external bundle unchanged.
11
+ //
12
+ // Pure composition over core's surface — no host/Node imports (the @irisrun/core
13
+ // dependency is the ONLY dependency; this package is NOT a host/transport package).
14
+ import { composeAssemble, composeDecideNext, composeGate, reactAssembleContext, reactDecideNext, windowCompaction, toolRepair, defaultInvariants, } from "@irisrun/core";
15
+ /** The stable id pinned into `Lock.tactics.bundle` and journaled as the tacticId. */
16
+ export const BUNDLE_ID = "iris/coding";
17
+ // The read-only / reversible tools a coding agent may run without a gate. Writes
18
+ // and shell are NOT here — they default to "ask" (HITL approval), the secure
19
+ // gate-irreversible-by-default floor for a coding workflow.
20
+ const DEFAULT_READ_ONLY_TOOLS = ["read_file", "search", "list", "grep", "glob"];
21
+ /**
22
+ * The coding-specialized gateAction tactic: read-only / codebase-search tools are
23
+ * a safe ALLOW; every other tool — writes (`write_file`), shell (`run_shell`),
24
+ * and anything unknown/irreversible — is gated to "ask" (HITL). A host-side
25
+ * factory function (not a bare object), matching core's convention.
26
+ */
27
+ export function codingGate(readOnlyTools = []) {
28
+ const safe = new Set([...DEFAULT_READ_ONLY_TOOLS, ...readOnlyTools]);
29
+ return {
30
+ id: "iris/coding-gate",
31
+ seam: "gateAction",
32
+ decide: ({ call }) => (safe.has(call.name) ? "allow" : "ask"),
33
+ };
34
+ }
35
+ /**
36
+ * The coding bundle's decideNext: it DELEGATES verbatim to the proven ReAct
37
+ * tool-loop (continue while the model still requests tools, finish when it stops) —
38
+ * which is the CORRECT policy for a coding tool-loop agent, so there is nothing to
39
+ * "tune" today. The coding-specific behavior lives in `codingGate` (the
40
+ * read-only-allow / write-gate split). This is kept as a DISTINCT factory only so a
41
+ * future coding heuristic (e.g. a max-edit budget) can layer in here without
42
+ * touching core or the bundle's call sites — it is a pass-through for now.
43
+ */
44
+ export function codingDecideNext() {
45
+ const react = reactDecideNext();
46
+ return {
47
+ id: "iris/coding-decide",
48
+ seam: "decideNext",
49
+ decide: ({ state }) => react.decide({ state }),
50
+ };
51
+ }
52
+ /**
53
+ * Assemble the coding bundle: the SAME structure as core's `defaultBundle`, with
54
+ * the coding-specialized gate + decideNext and the reused window-compaction /
55
+ * tool-repair tactics, returning `{ tacticPerformer, invariants }`.
56
+ */
57
+ export function codingBundle(opts = {}) {
58
+ const assembleChain = [reactAssembleContext()];
59
+ const decideChain = [codingDecideNext()];
60
+ const gateChain = [codingGate(opts.readOnlyTools)];
61
+ const compact = windowCompaction(opts.keepLast);
62
+ const repair = toolRepair(opts.maxAttempts);
63
+ const tacticPerformer = async (request) => {
64
+ const req = request;
65
+ const seam = req.seam ?? "";
66
+ const payload = req.payload ?? null;
67
+ let choice;
68
+ switch (seam) {
69
+ case "assembleContext": {
70
+ const pl = payload;
71
+ choice = composeAssemble(assembleChain, pl.state, pl.ctx);
72
+ break;
73
+ }
74
+ case "shouldCompact": {
75
+ const pl = payload;
76
+ choice = compact.decide(pl);
77
+ break;
78
+ }
79
+ case "gateAction": {
80
+ const pl = payload;
81
+ choice = composeGate(gateChain, pl.call);
82
+ break;
83
+ }
84
+ case "onToolError": {
85
+ const pl = payload;
86
+ choice = repair.decide(pl);
87
+ break;
88
+ }
89
+ case "decideNext": {
90
+ const pl = payload;
91
+ choice = composeDecideNext(decideChain, pl.state);
92
+ break;
93
+ }
94
+ default:
95
+ return { ok: false, error: { message: `codingBundle: unknown seam '${seam}'` } };
96
+ }
97
+ return { ok: true, value: { seam, tacticId: BUNDLE_ID, choice } };
98
+ };
99
+ const invariants = defaultInvariants(opts.invariants);
100
+ return { tacticPerformer, invariants };
101
+ }
@@ -0,0 +1,3 @@
1
+ export declare const PACKAGE = "@irisrun/bundle-coding";
2
+ export { codingBundle, codingGate, codingDecideNext, BUNDLE_ID, } from "./coding.js";
3
+ export type { CodingBundleOptions } from "./coding.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // @irisrun/bundle-coding — public surface (host-side; composes from @irisrun/core's
2
+ // exported tactic primitives only — @irisrun/core is the ONLY dependency, and this
3
+ // is NOT a host/transport package).
4
+ export const PACKAGE = "@irisrun/bundle-coding";
5
+ export { codingBundle, codingGate, codingDecideNext, BUNDLE_ID, } from "./coding.js";
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@irisrun/bundle-coding",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Iris first domain tactic bundle — coding-specialized seam tactics (read-only tools allow / writes+shell gated to ask, a tool-loop decideNext, window-compaction + tool-repair) composed HOST-SIDE from @irisrun/core's exported primitives. Produces the defaultBundle shape {tacticPerformer, invariants}; journaled {seam, tacticId, choice} outcomes inherit the ADR-0007 replay quarantine. @irisrun/core dependency only; core stays byte-untouched.",
6
+ "exports": {
7
+ ".": {
8
+ "iris-src": "./src/index.ts",
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@irisrun/core": "^0.1.0"
15
+ },
16
+ "license": "MIT",
17
+ "engines": {
18
+ "node": ">=24"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/xoai/iris.git",
26
+ "directory": "packages/bundle-coding"
27
+ },
28
+ "homepage": "https://github.com/xoai/iris#readme",
29
+ "files": [
30
+ "dist"
31
+ ]
32
+ }