rhachet 1.18.0 → 1.19.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.
Files changed (55) hide show
  1. package/dist/_topublish/rhachet-brain-openai/src/repls/genBrainRepl.js +3 -1
  2. package/dist/_topublish/rhachet-brain-openai/src/repls/genBrainRepl.js.map +1 -1
  3. package/dist/contract/cli/invoke.js +14 -2
  4. package/dist/contract/cli/invoke.js.map +1 -1
  5. package/dist/contract/cli/invokeAct.d.ts +14 -0
  6. package/dist/contract/cli/invokeAct.js +92 -0
  7. package/dist/contract/cli/invokeAct.js.map +1 -0
  8. package/dist/contract/cli/invokeAsk.d.ts +4 -1
  9. package/dist/contract/cli/invokeAsk.js +84 -21
  10. package/dist/contract/cli/invokeAsk.js.map +1 -1
  11. package/dist/contract/cli/invokeRun.d.ts +6 -2
  12. package/dist/contract/cli/invokeRun.js +111 -18
  13. package/dist/contract/cli/invokeRun.js.map +1 -1
  14. package/dist/contract/sdk.d.ts +1 -0
  15. package/dist/contract/sdk.js +3 -1
  16. package/dist/contract/sdk.js.map +1 -1
  17. package/dist/domain.objects/Actor.d.ts +94 -0
  18. package/dist/domain.objects/Actor.js +18 -0
  19. package/dist/domain.objects/Actor.js.map +1 -0
  20. package/dist/domain.objects/ActorRoleSkill.d.ts +41 -0
  21. package/dist/domain.objects/ActorRoleSkill.js +8 -0
  22. package/dist/domain.objects/ActorRoleSkill.js.map +1 -0
  23. package/dist/domain.objects/InvokeHooks.d.ts +38 -1
  24. package/dist/domain.objects/Role.d.ts +43 -2
  25. package/dist/domain.objects/Role.js +9 -0
  26. package/dist/domain.objects/Role.js.map +1 -1
  27. package/dist/domain.objects/index.d.ts +2 -0
  28. package/dist/domain.objects/index.js +2 -0
  29. package/dist/domain.objects/index.js.map +1 -1
  30. package/dist/domain.operations/actor/actorAct.d.ts +15 -0
  31. package/dist/domain.operations/actor/actorAct.js +30 -0
  32. package/dist/domain.operations/actor/actorAct.js.map +1 -0
  33. package/dist/domain.operations/actor/actorAsk.d.ts +15 -0
  34. package/dist/domain.operations/actor/actorAsk.js +32 -0
  35. package/dist/domain.operations/actor/actorAsk.js.map +1 -0
  36. package/dist/domain.operations/actor/actorRun.d.ts +11 -0
  37. package/dist/domain.operations/actor/actorRun.js +25 -0
  38. package/dist/domain.operations/actor/actorRun.js.map +1 -0
  39. package/dist/domain.operations/actor/findActorBrainInAllowlist.d.ts +16 -0
  40. package/dist/domain.operations/actor/findActorBrainInAllowlist.js +33 -0
  41. package/dist/domain.operations/actor/findActorBrainInAllowlist.js.map +1 -0
  42. package/dist/domain.operations/actor/findActorRoleSkillBySlug.d.ts +13 -0
  43. package/dist/domain.operations/actor/findActorRoleSkillBySlug.js +68 -0
  44. package/dist/domain.operations/actor/findActorRoleSkillBySlug.js.map +1 -0
  45. package/dist/domain.operations/actor/genActor.d.ts +18 -0
  46. package/dist/domain.operations/actor/genActor.js +98 -0
  47. package/dist/domain.operations/actor/genActor.js.map +1 -0
  48. package/dist/domain.operations/invoke/executeSkill.d.ts +3 -1
  49. package/dist/domain.operations/invoke/executeSkill.js +16 -3
  50. package/dist/domain.operations/invoke/executeSkill.js.map +1 -1
  51. package/dist/domain.operations/invoke/getBrainReplsByOpts.d.ts +14 -0
  52. package/dist/domain.operations/invoke/getBrainReplsByOpts.js +43 -0
  53. package/dist/domain.operations/invoke/getBrainReplsByOpts.js.map +1 -0
  54. package/package.json +1 -1
  55. package/readme.md +180 -34
@@ -0,0 +1,18 @@
1
+ import { Actor } from '../../domain.objects/Actor';
2
+ import type { BrainRepl } from '../../domain.objects/BrainRepl';
3
+ import type { Role } from '../../domain.objects/Role';
4
+ /**
5
+ * .what = creates an actor from a role and brain allowlist
6
+ * .why = composes role (skills + briefs) with brains for type-safe invocation
7
+ *
8
+ * .note =
9
+ * - first brain in allowlist is the default
10
+ * - .act() uses default brain when none specified
11
+ * - .act() validates brain against allowlist when specified
12
+ * - .run() executes solid skills without brain
13
+ * - .ask() starts fluid conversation with default brain
14
+ */
15
+ export declare const genActor: <TRole extends Role<import("../../domain.objects/Role").RoleSkillRegistry, import("../../domain.objects/Role").RoleSkillRegistry>>(input: {
16
+ role: TRole;
17
+ brains: BrainRepl[];
18
+ }) => Actor<TRole>;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.genActor = void 0;
4
+ const helpful_errors_1 = require("helpful-errors");
5
+ const Actor_1 = require("../../domain.objects/Actor");
6
+ const actorAct_1 = require("./actorAct");
7
+ const actorAsk_1 = require("./actorAsk");
8
+ const actorRun_1 = require("./actorRun");
9
+ const findActorBrainInAllowlist_1 = require("./findActorBrainInAllowlist");
10
+ const findActorRoleSkillBySlug_1 = require("./findActorRoleSkillBySlug");
11
+ /**
12
+ * .what = creates an actor from a role and brain allowlist
13
+ * .why = composes role (skills + briefs) with brains for type-safe invocation
14
+ *
15
+ * .note =
16
+ * - first brain in allowlist is the default
17
+ * - .act() uses default brain when none specified
18
+ * - .act() validates brain against allowlist when specified
19
+ * - .run() executes solid skills without brain
20
+ * - .ask() starts fluid conversation with default brain
21
+ */
22
+ const genActor = (input) => {
23
+ // validate that at least one brain is provided
24
+ if (input.brains.length === 0)
25
+ throw new helpful_errors_1.BadRequestError('genActor requires at least one brain in allowlist', { roleSlug: input.role.slug });
26
+ // extract default brain (first in list)
27
+ const defaultBrain = input.brains[0];
28
+ // create bound .act() method with strong types
29
+ const act = async (actInput) => {
30
+ // resolve brain: use provided or default to first
31
+ const brainResolved = actInput.brain
32
+ ? (0, findActorBrainInAllowlist_1.findActorBrainInAllowlist)({
33
+ brain: actInput.brain,
34
+ allowlist: input.brains,
35
+ })
36
+ : defaultBrain;
37
+ // extract skill slug and args from skill object
38
+ const entries = Object.entries(actInput.skill);
39
+ if (entries.length !== 1)
40
+ throw new helpful_errors_1.BadRequestError('actor.act expects exactly one skill entry', {
41
+ entriesCount: entries.length,
42
+ });
43
+ const [skillSlug, skillArgs] = entries[0];
44
+ // resolve skill from role
45
+ const skillResolved = (0, findActorRoleSkillBySlug_1.findActorRoleSkillBySlug)({
46
+ slug: skillSlug,
47
+ role: input.role,
48
+ route: 'rigid',
49
+ });
50
+ // delegate to actorAct with pre-resolved skill
51
+ return (0, actorAct_1.actorAct)({
52
+ role: input.role,
53
+ brain: brainResolved,
54
+ skill: skillResolved,
55
+ args: skillArgs,
56
+ });
57
+ };
58
+ // create bound .run() method with strong types
59
+ const run = async (runInput) => {
60
+ // extract skill slug and args from skill object
61
+ const entries = Object.entries(runInput.skill);
62
+ if (entries.length !== 1)
63
+ throw new helpful_errors_1.BadRequestError('actor.run expects exactly one skill entry', {
64
+ entriesCount: entries.length,
65
+ });
66
+ const [skillSlug, skillArgs] = entries[0];
67
+ // resolve skill from role
68
+ const skillResolved = (0, findActorRoleSkillBySlug_1.findActorRoleSkillBySlug)({
69
+ slug: skillSlug,
70
+ role: input.role,
71
+ route: 'solid',
72
+ });
73
+ // delegate to actorRun with pre-resolved skill
74
+ return (0, actorRun_1.actorRun)({
75
+ skill: skillResolved,
76
+ args: skillArgs,
77
+ });
78
+ };
79
+ // create bound .ask() method
80
+ const ask = async (askInput) => {
81
+ // delegate to actorAsk with default brain
82
+ return (0, actorAsk_1.actorAsk)({
83
+ role: input.role,
84
+ brain: defaultBrain,
85
+ prompt: askInput.prompt,
86
+ });
87
+ };
88
+ // return actor with bound methods via Actor.typed() for strong type preservation
89
+ return Actor_1.Actor.typed({
90
+ role: input.role,
91
+ brains: input.brains,
92
+ act,
93
+ run,
94
+ ask,
95
+ });
96
+ };
97
+ exports.genActor = genActor;
98
+ //# sourceMappingURL=genActor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genActor.js","sourceRoot":"","sources":["../../../src/domain.operations/actor/genActor.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,10 @@ import type { RoleSkillExecutable } from '../../domain.objects/RoleSkillExecutab
2
2
  /**
3
3
  * .what = executes a skill script with passthrough args
4
4
  * .why = runs the discovered skill with full arg passthrough
5
+ *
6
+ * .note = captures stdout and parses JSON output when available
5
7
  */
6
8
  export declare const executeSkill: (input: {
7
9
  skill: RoleSkillExecutable;
8
10
  args: string[];
9
- }) => void;
11
+ }) => unknown;
@@ -5,6 +5,8 @@ const node_child_process_1 = require("node:child_process");
5
5
  /**
6
6
  * .what = executes a skill script with passthrough args
7
7
  * .why = runs the discovered skill with full arg passthrough
8
+ *
9
+ * .note = captures stdout and parses JSON output when available
8
10
  */
9
11
  const executeSkill = (input) => {
10
12
  // build command with args
@@ -16,12 +18,23 @@ const executeSkill = (input) => {
16
18
  return arg;
17
19
  })
18
20
  .join(' ');
19
- // execute with inherited stdio
20
- (0, node_child_process_1.execSync)(command, {
21
+ // execute and capture stdout
22
+ const stdout = (0, node_child_process_1.execSync)(command, {
21
23
  cwd: process.cwd(),
22
- stdio: 'inherit',
23
24
  shell: '/bin/bash',
25
+ encoding: 'utf-8',
24
26
  });
27
+ // parse JSON output if present
28
+ const trimmed = stdout.trim();
29
+ if (!trimmed)
30
+ return undefined;
31
+ try {
32
+ return JSON.parse(trimmed);
33
+ }
34
+ catch {
35
+ // return raw string if not valid JSON
36
+ return trimmed;
37
+ }
25
38
  };
26
39
  exports.executeSkill = executeSkill;
27
40
  //# sourceMappingURL=executeSkill.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"executeSkill.js","sourceRoot":"","sources":["../../../src/domain.operations/invoke/executeSkill.ts"],"names":[],"mappings":";;;AAEA,2DAA8C;AAE9C;;;GAGG;AACI,MAAM,YAAY,GAAG,CAAC,KAG5B,EAAQ,EAAE;IACT,0BAA0B;IAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC;SAC9C,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,yBAAyB;QACzB,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,GAAG,GAAG,CAAC;QACzC,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,+BAA+B;IAC/B,IAAA,6BAAQ,EAAC,OAAO,EAAE;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAnBW,QAAA,YAAY,gBAmBvB"}
1
+ {"version":3,"file":"executeSkill.js","sourceRoot":"","sources":["../../../src/domain.operations/invoke/executeSkill.ts"],"names":[],"mappings":";;;AAEA,2DAA8C;AAE9C;;;;;GAKG;AACI,MAAM,YAAY,GAAG,CAAC,KAG5B,EAAW,EAAE;IACZ,0BAA0B;IAC1B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC;SAC9C,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,yBAAyB;QACzB,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,GAAG,GAAG,CAAC;QACzC,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,6BAA6B;IAC7B,MAAM,MAAM,GAAG,IAAA,6BAAQ,EAAC,OAAO,EAAE;QAC/B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;QACtC,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AA9BW,QAAA,YAAY,gBA8BvB"}
@@ -0,0 +1,14 @@
1
+ import type { BrainRepl } from '../../domain.objects';
2
+ import type { InvokeOpts } from '../../domain.objects/InvokeOpts';
3
+ /**
4
+ * .what = get brain repls from the invocation options declared
5
+ * .why = enables CLI commands to resolve brains from config
6
+ * .how =
7
+ * - lookup the config based on the options
8
+ * - grab the brain repls from the config
9
+ */
10
+ export declare const getBrainReplsByOpts: (input: {
11
+ opts: InvokeOpts<{
12
+ config: string;
13
+ }>;
14
+ }) => Promise<BrainRepl[]>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.getBrainReplsByOpts = void 0;
27
+ /**
28
+ * .what = get brain repls from the invocation options declared
29
+ * .why = enables CLI commands to resolve brains from config
30
+ * .how =
31
+ * - lookup the config based on the options
32
+ * - grab the brain repls from the config
33
+ */
34
+ const getBrainReplsByOpts = async (input) => {
35
+ // import the config
36
+ const config = await Promise.resolve(`${input.opts.config}`).then(s => __importStar(require(s)));
37
+ // grab the brain repls if available
38
+ if (!config.getBrainRepls)
39
+ return [];
40
+ return await config.getBrainRepls();
41
+ };
42
+ exports.getBrainReplsByOpts = getBrainReplsByOpts;
43
+ //# sourceMappingURL=getBrainReplsByOpts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getBrainReplsByOpts.js","sourceRoot":"","sources":["../../../src/domain.operations/invoke/getBrainReplsByOpts.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;;GAMG;AACI,MAAM,mBAAmB,GAAG,KAAK,EAAE,KAEzC,EAAwB,EAAE;IACzB,oBAAoB;IACpB,MAAM,MAAM,GAAmD,yBAC7D,KAAK,CAAC,IAAI,CAAC,MAAM,uCAClB,CAAC;IAEF,oCAAoC;IACpC,IAAI,CAAC,MAAM,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAErC,OAAO,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;AACtC,CAAC,CAAC;AAZW,QAAA,mBAAmB,uBAY9B"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "rhachet",
3
3
  "author": "ehmpathy",
4
4
  "description": "A framework for reliable, thorough thought. Weave threads of thought via stitches.",
5
- "version": "1.18.0",
5
+ "version": "1.19.1",
6
6
  "repository": "ehmpathy/rhachet",
7
7
  "homepage": "https://github.com/ehmpathy/rhachet",
8
8
  "keywords": [
package/readme.md CHANGED
@@ -3,31 +3,78 @@
3
3
  ![test](https://github.com/ehmpathy/rhachet/workflows/test/badge.svg)
4
4
  ![publish](https://github.com/ehmpathy/rhachet/workflows/publish/badge.svg)
5
5
 
6
- Build reusable roles with rhachet: a framework for reliable, composable, and iteratively improvable thought.
6
+ a framework for reliable, composable, and iteratively improvable thought.
7
7
 
8
- > Weave threads 🧵 of thought, stitched 🪡 with a rhachet ⚙️
8
+ > weave threads 🧵 of thought, stitched 🪡 with a rhachet ⚙️
9
9
 
10
- # vision
10
+ # purpose
11
11
 
12
- Build or use digital actors, who work even from your laptop, and work for anyone you choose.
12
+ rhachet makes it simple to leverage thought routes - safely, easily, and effectively.
13
13
 
14
- Distill your skills and roles iteratively, with rhachet. Use them, compose them, share them, open source them. The choice is yours.
14
+ - 🪨 **solid** routes for deterministic operations
15
+ - 🔩 **rigid** routes for augmented orchestration
16
+ - 💧 **fluid** routes for probabalistic exploration
15
17
 
16
- - With open source top to bottom, we can raise the floor and prosper collectively.
17
- - With observable routes of thought, we can not only debug, but align.
18
- - With composable thought routes, we can build incremental complexity and automate test coverage just like any code.
18
+ with rhachet, you can:
19
+ - declare thought routes, reusably and maintainably
20
+ - apply thought routes, observably and reliably
21
+ - compose and accumulate reusable thought skill
22
+ - assure slipless progress towards goals, like a ratchet (🎼 click, click, click)
23
+ - enable iterative improvement of skills, like a ratchet (🎼 click, click, click)
19
24
 
20
- Here's to a solarpunk future of abundance 🌞🌴
25
+ # concepts
21
26
 
22
- # purpose
27
+ ## thought routes
28
+
29
+ thought routes describe the determinism profile of an execution path.
30
+
31
+ | route | what | when to use |
32
+ | ----------- | ------------------------------------------------ | ------------------------------------------------ |
33
+ | 🪨 **solid** | deterministic throughout | whenever you can; faster, cheaper, more reliable |
34
+ | 🔩 **rigid** | deterministic harness + probabilistic operations | when you can control the flow, brain fills gaps |
35
+ | 💧 **fluid** | probabilistic throughout | when brain must decide the flow |
36
+
37
+ the key distinction:
38
+ - 🔩 **rigid**: you know when thought is needed, harness controls
39
+ - 💧 **fluid**: you don't know when or what thought is needed, brain decides
40
+
41
+ ## brains
42
+
43
+ brains are probabilistic imagination mechanisms that provide creative thought capabilities:
44
+
45
+ | type | what | characteristics |
46
+ | -------------- | -------------------- | ------------------------------ |
47
+ | **brain.atom** | single inference | stateless, one-shot |
48
+ | **brain.repl** | read-eval-print-loop | stateful, multi-turn, tool use |
49
+
50
+ brain.atom is for single-turn operations. brain.repl is for multi-turn operations.
51
+
52
+ ## actors, roles, skills, briefs
53
+
54
+ rhachet organizes thought operators into a composable hierarchy
55
+
56
+ ```
57
+ actor
58
+ ├── brain
59
+ └── role
60
+ ├── briefs
61
+ └── skills
62
+ ```
23
63
 
24
- 1. declare thought routes, reusably and maintainably
25
- 2. apply thought routes, observably and reliably
26
- 3. compose and accumulate reusable thought skill
27
- 4. assure slipless progress towards goals, like a ratchet (🎼 click, click, click)
28
- 5. enable iterative improvement of skills, like a ratchet (🎼 click, click, click)
29
- 6. assure guarded budgets of money and time, with route plans, expense approvals, and circuit breakers
30
- 7. observe thought routes and weaves intuitively
64
+ | concept | what | example |
65
+ | ----------- | ---------------------------------- | -------------------------------------------- |
66
+ | 🎭 **actor** | a brain in a role | mechanic actor (brain:codex + role:mechanic) |
67
+ | 🧢 **role** | a bundle of skills + briefs | mechanic, reviewer, architect |
68
+ | 📚 **brief** | curated knowledge for the role | code standards, domain patterns |
69
+ | 💪 **skill** | executable capability for the role | review, deliver, decompose |
70
+
71
+ actors cause action - yet are not agents until delegated to.
72
+
73
+ roles are portable - the same role can be assumed by different brains.
74
+
75
+ briefs are cumulative - they encode institutional knowledge that improves over time.
76
+
77
+ skills are composable - they can invoke other skills, nest thought routes, and build complexity incrementally.
31
78
 
32
79
  # install
33
80
 
@@ -37,43 +84,142 @@ npm install rhachet
37
84
 
38
85
  # use
39
86
 
87
+ ## cli
40
88
 
41
- ## use a prebuilt roles registry
89
+ rhachet provides cli commands for each thought route:
42
90
 
43
- ### setup your config file
91
+ | command | route | what it does |
92
+ | ----------------- | ------- | ------------------------------------------ |
93
+ | `npx rhachet run` | 🪨 solid | execute a shell skill, no brain |
94
+ | `npx rhachet act` | 🔩 rigid | execute a skill with deterministic harness |
95
+ | `npx rhachet ask` | 💧 fluid | converse with an actor, brain decides path |
44
96
 
45
- looks for `@gitroot/rhachet.use.ts` by default
97
+ ### setup
98
+
99
+ rhachet looks for `@gitroot/rhachet.use.ts`:
46
100
 
47
101
  ```ts
48
- // @/rhachet.use.ts
102
+ // rhachet.use.ts
49
103
  import { getRoleRegistry as getBhrainRegistry } from 'rhachet-roles-bhrain';
50
104
  import { getRoleRegistry as getEhmpathyRegistry } from 'rhachet-roles-ehmpathy';
51
105
 
52
106
  export const getRoleRegistries = () => [
53
107
  getBhrainRegistry(),
54
108
  getEhmpathyRegistry(),
55
- // whichever other registries you'd like
56
- ]
109
+ ];
57
110
  ```
58
111
 
59
- ### perform a skill
112
+ ### 🪨 solid: run
60
113
 
61
114
  ```sh
62
- npx rhachet act \
63
- --repo bhrain --role skeptic --skill review \
64
- --ask "are birds real? or are they just government drones 🤔"
115
+ npx rhachet run --skill gh.workflow.logs --workflow test
65
116
  ```
66
117
 
118
+ deterministic operations, no brain.
119
+
120
+ ### 🔩 rigid: act
121
+
67
122
  ```sh
68
123
  npx rhachet act \
69
- --repo ehmpathy --role mechanic --skill review \
70
- --input "https://github.com/ehmpathy/simple-in-memory-cache/pull/9" \
71
- --ask "review this pr"
124
+ --role mechanic --skill review \
125
+ --input "https://github.com/org/repo/pull/9"
126
+
127
+ npx rhachet act \
128
+ --role mechanic --skill review \
129
+ --input "https://github.com/org/repo/pull/9" \
130
+ --brain openai/codex
72
131
  ```
73
132
 
133
+ augmented orchestration, harness controls flow, brain augments.
134
+
135
+ ### 💧 fluid: ask
136
+
74
137
  ```sh
75
- npx rhachet act \
76
- --repo ehmpathy --role mechanic --skill deliver \
77
- --input "https://github.com/ehmpathy/domain-objects/issues/7" \
78
- --ask "push a pr to solve the issue"
138
+ npx rhachet ask \
139
+ --role skeptic \
140
+ --ask "are birds real?"
79
141
  ```
142
+
143
+ probabilistic exploration, brain decides the path.
144
+
145
+ ## sdk
146
+
147
+ rhachet provides a type-safe sdk for programmatic actor usage.
148
+
149
+ | method | route | what it does |
150
+ | ------------- | ------- | ------------------------------------------ |
151
+ | `actor.run()` | 🪨 solid | execute a shell skill, no brain |
152
+ | `actor.act()` | 🔩 rigid | execute a skill with deterministic harness |
153
+ | `actor.ask()` | 💧 fluid | converse with an actor, brain decides path |
154
+
155
+ ### setup
156
+
157
+ generate an actor from a role with an allowlist of brains:
158
+
159
+ ```ts
160
+ import { genActor } from 'rhachet';
161
+ import { genBrainRepl } from 'rhachet-brains-openai';
162
+ import { mechanicRole } from './roles/mechanic';
163
+
164
+ export const mechanic = genActor({
165
+ role: mechanicRole,
166
+ brains: [
167
+ genBrainRepl({ slug: 'openai/codex' }), // default (first in list)
168
+ genBrainRepl({ slug: 'openai/codex/mini' }), // fast + cheap alternative
169
+ ],
170
+ });
171
+ ```
172
+
173
+ the `brains` allowlist:
174
+ - defines which brains this actor supports
175
+ - first brain is the default (used when no explicit brain is provided)
176
+ - ensures only allowlisted brains can be used
177
+
178
+ ### 🪨 solid: run
179
+
180
+ ```ts
181
+ await mechanic.run({
182
+ skill: { 'gh.workflow.logs': { workflow: 'test' } },
183
+ });
184
+ ```
185
+
186
+ deterministic operations, no brain.
187
+
188
+ ### 🔩 rigid: act
189
+
190
+ ```ts
191
+ // uses default brain (first in allowlist)
192
+ await mechanic.act({
193
+ skill: { review: { input: 'https://github.com/org/repo/pull/9' } },
194
+ });
195
+
196
+ // uses explicit brain (must be in allowlist)
197
+ await mechanic.act({
198
+ brain: { repo: 'openai', slug: 'codex/mini' },
199
+ skill: { review: { input: 'https://github.com/org/repo/pull/9' } },
200
+ });
201
+ ```
202
+
203
+ augmented orchestration, harness controls flow, brain augments.
204
+
205
+ ### 💧 fluid: ask
206
+
207
+ ```ts
208
+ await skeptic.ask({
209
+ prompt: 'are birds real?',
210
+ });
211
+ ```
212
+
213
+ probabilistic exploration, brain decides the path.
214
+
215
+ # vision
216
+
217
+ build or use digital actors, who work even from your laptop, and work for anyone you choose.
218
+
219
+ distill your skills and roles iteratively, with rhachet. use them, compose them, share them, open source them. the choice is yours.
220
+
221
+ - with open source top to bottom, we can raise the floor and prosper collectively.
222
+ - with observable routes of thought, we can not only debug, but align.
223
+ - with composable thought routes, we can build incremental complexity and automate test coverage just like any code.
224
+
225
+ here's to a solarpunk future of abundance 🌞🌴