@rolexjs/core 0.7.0 → 0.9.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.
package/dist/index.d.ts CHANGED
@@ -26,7 +26,7 @@ interface Scenario extends Scenario$1 {
26
26
  * A Gherkin Feature enriched with RDD semantics.
27
27
  */
28
28
  interface Feature extends Feature$1 {
29
- readonly type: "persona" | "knowledge" | "experience" | "voice" | "goal" | "plan" | "task";
29
+ readonly type: "persona" | "knowledge" | "experience" | "voice" | "goal" | "plan" | "task" | "duty";
30
30
  readonly scenarios: Scenario[];
31
31
  }
32
32
 
@@ -107,6 +107,21 @@ interface Task extends Feature {
107
107
  readonly type: "task";
108
108
  }
109
109
 
110
+ /**
111
+ * Duty — Responsibilities defined by a Position.
112
+ *
113
+ * A Duty IS-A Feature with type='duty'.
114
+ * Expressed as *.duty.feature files within a position directory.
115
+ * Injected into role identity when the role is on_duty.
116
+ */
117
+
118
+ /**
119
+ * A duty (responsibility) assigned through a position.
120
+ */
121
+ interface Duty extends Feature {
122
+ readonly type: "duty";
123
+ }
124
+
110
125
  /**
111
126
  * Skill — Execution capability for a task.
112
127
  *
@@ -123,57 +138,131 @@ interface Skill {
123
138
  readonly reference: string;
124
139
  }
125
140
 
141
+ /**
142
+ * states.ts — Role and Position state definitions.
143
+ *
144
+ * Role: free → member → on_duty
145
+ * Position: vacant → filled
146
+ */
147
+ type RoleState = "free" | "member" | "on_duty";
148
+ type PositionState = "vacant" | "filled";
149
+ /**
150
+ * Derive a role's state from assignment data.
151
+ */
152
+ declare function getRoleState(assignment: {
153
+ org: string;
154
+ position?: string;
155
+ } | null): RoleState;
156
+ /**
157
+ * Derive a position's state from assignment data.
158
+ */
159
+ declare function getPositionState(assignedRole: string | null): PositionState;
160
+
126
161
  /**
127
162
  * Platform — The abstraction layer for role storage.
128
163
  *
129
- * Defines how roles are loaded and persisted.
164
+ * Defines how roles, organizations, and positions are stored and managed.
130
165
  * LocalPlatform uses the filesystem (.rolex/ directories).
131
166
  * Future platforms could use databases, cloud storage, etc.
132
167
  *
133
- * All methods are stateless — role name is passed per call.
168
+ * Three-entity architecture:
169
+ * Role = WHO (identity, goals)
170
+ * Organization = WHERE (structure, nesting)
171
+ * Position = WHAT (duties, boundaries)
172
+ *
173
+ * All methods are stateless — entity names are passed per call.
134
174
  */
135
175
 
136
176
  /**
137
- * Role entry in the organization.
177
+ * Assignment tracks which org/position a role is assigned to.
138
178
  */
139
- interface RoleEntry {
179
+ interface Assignment {
180
+ readonly org: string;
181
+ readonly position?: string;
182
+ }
183
+ /**
184
+ * OrganizationConfig — stored config for an organization.
185
+ */
186
+ interface OrganizationConfig {
187
+ readonly parent?: string;
188
+ readonly positions: string[];
189
+ }
190
+ /**
191
+ * RolexConfig — The single source of truth for society state.
192
+ *
193
+ * Always exists. Defined in core, persisted by Platform.
194
+ */
195
+ interface RolexConfig {
196
+ roles: string[];
197
+ organizations: Record<string, OrganizationConfig>;
198
+ assignments: Record<string, Assignment>;
199
+ }
200
+ /**
201
+ * Organization info (runtime view).
202
+ */
203
+ interface OrganizationInfo {
140
204
  readonly name: string;
141
- readonly team: string;
205
+ readonly parent?: string;
206
+ readonly positions: string[];
207
+ readonly members: string[];
142
208
  }
143
209
  /**
144
- * Organization structure.
210
+ * Position info (runtime view).
145
211
  */
146
- interface Organization {
212
+ interface PositionInfo {
147
213
  readonly name: string;
148
- readonly roles: RoleEntry[];
214
+ readonly org: string;
215
+ readonly state: PositionState;
216
+ readonly assignedRole: string | null;
217
+ readonly duties: Duty[];
149
218
  }
150
219
  /**
151
- * Society directory all known roles and organizations.
220
+ * Role directory entry with state information.
221
+ */
222
+ interface RoleEntry {
223
+ readonly name: string;
224
+ readonly state: RoleState;
225
+ readonly org?: string;
226
+ readonly position?: string;
227
+ }
228
+ /**
229
+ * Society directory — all known roles, organizations, and positions.
152
230
  */
153
231
  interface Directory {
154
232
  readonly roles: readonly RoleEntry[];
155
- readonly organizations: readonly {
156
- readonly name: string;
157
- }[];
233
+ readonly organizations: readonly OrganizationInfo[];
158
234
  }
159
235
  /**
160
- * Platform interface — abstracts role storage and retrieval.
161
- * All methods are stateless — role name identifies the target role.
236
+ * Platform interface — abstracts entity storage and retrieval.
162
237
  */
163
238
  interface Platform {
164
- /** Found an organization */
165
- found(name: string): void;
166
- /** Get the organization structure (teams + roles) */
167
- organization(): Organization;
168
- /** List all born roles in society (regardless of organization membership) */
239
+ /** List all born roles in society */
169
240
  allBornRoles(): string[];
170
241
  /** Create a new role with its persona */
171
242
  born(name: string, source: string): Feature;
172
- /** Hire a role into the organization establish CAS link */
173
- hire(name: string): void;
174
- /** Fire a role from the organization remove CAS link */
175
- fire(name: string): void;
176
- /** Load all identity features for a role */
243
+ /** Found an organization, optionally with a parent org and description */
244
+ found(name: string, source?: string, parent?: string): void;
245
+ /** Get organization info by name */
246
+ getOrganization(name: string): OrganizationInfo | null;
247
+ /** List all organizations */
248
+ allOrganizations(): OrganizationInfo[];
249
+ /** Hire a role into an organization */
250
+ hire(roleId: string, orgName: string): void;
251
+ /** Fire a role from an organization (auto-dismisses if on_duty) */
252
+ fire(roleId: string, orgName: string): void;
253
+ /** Establish a position within an organization */
254
+ establish(positionName: string, source: string, orgName: string): void;
255
+ /** Appoint a role to a position */
256
+ appoint(roleId: string, positionName: string, orgName: string): void;
257
+ /** Dismiss a role from their position (back to member) */
258
+ dismiss(roleId: string): void;
259
+ /** Get duties for a position */
260
+ positionDuties(positionName: string, orgName: string): Duty[];
261
+ /** Get a role's current assignment */
262
+ getAssignment(roleId: string): Assignment | null;
263
+ /** Get position info */
264
+ getPosition(positionName: string, orgName: string): PositionInfo | null;
265
+ /** Load all identity features for a role (includes duties if on_duty) */
177
266
  identity(roleId: string): Feature[];
178
267
  /** Add a growth dimension to a role's identity */
179
268
  growup(roleId: string, type: "knowledge" | "experience" | "voice", name: string, source: string): Feature;
@@ -204,4 +293,55 @@ interface Platform {
204
293
  reflect(roleId: string, experienceNames: string[], knowledgeName: string, knowledgeSource: string): Feature;
205
294
  }
206
295
 
207
- export type { Directory, Feature, Goal, Identity, Organization, Plan, Platform, Role, RoleEntry, Scenario, Skill, Task };
296
+ /**
297
+ * transitions.ts — State machine definitions and transition logic.
298
+ *
299
+ * Role transitions:
300
+ * free --(hire)--> member --(appoint)--> on_duty
301
+ * on_duty --(dismiss)--> member --(fire)--> free
302
+ * on_duty --(fire)--> free (auto-dismiss)
303
+ *
304
+ * Position transitions:
305
+ * vacant --(appoint)--> filled --(dismiss)--> vacant
306
+ */
307
+
308
+ interface Transition<S extends string> {
309
+ readonly from: S;
310
+ readonly to: S;
311
+ readonly action: string;
312
+ }
313
+ declare const ROLE_MACHINE: Transition<RoleState>[];
314
+ declare const POSITION_MACHINE: Transition<PositionState>[];
315
+ /**
316
+ * Find a transition by current state and action.
317
+ */
318
+ declare function findTransition<S extends string>(machine: Transition<S>[], from: S, action: string): Transition<S> | null;
319
+ /**
320
+ * Check if a transition is valid.
321
+ */
322
+ declare function canTransition<S extends string>(machine: Transition<S>[], from: S, action: string): boolean;
323
+ /**
324
+ * Execute a transition — returns new state or throws.
325
+ */
326
+ declare function transition<S extends string>(machine: Transition<S>[], from: S, action: string): S;
327
+
328
+ /**
329
+ * relations.ts — One-to-one relationship constraints.
330
+ *
331
+ * - A role can belong to at most one organization
332
+ * - A role can hold at most one position
333
+ * - A position can be held by at most one role
334
+ */
335
+ interface OneToOneConstraint {
336
+ readonly entity: string;
337
+ readonly relation: string;
338
+ readonly description: string;
339
+ }
340
+ declare const RELATIONS: OneToOneConstraint[];
341
+ /**
342
+ * Validate that a one-to-one assignment does not conflict.
343
+ * Throws if the entity is already assigned.
344
+ */
345
+ declare function validateOneToOne(entityName: string, currentValue: string | null, newValue: string, constraintDesc: string): void;
346
+
347
+ export { type Assignment, type Directory, type Duty, type Feature, type Goal, type Identity, type OneToOneConstraint, type OrganizationConfig, type OrganizationInfo, POSITION_MACHINE, type Plan, type Platform, type PositionInfo, type PositionState, RELATIONS, ROLE_MACHINE, type Role, type RoleEntry, type RoleState, type RolexConfig, type Scenario, type Skill, type Task, type Transition, canTransition, findTransition, getPositionState, getRoleState, transition, validateOneToOne };
package/dist/index.js CHANGED
@@ -1 +1,67 @@
1
+ // src/model/states.ts
2
+ function getRoleState(assignment) {
3
+ if (!assignment) return "free";
4
+ if (assignment.position) return "on_duty";
5
+ return "member";
6
+ }
7
+ function getPositionState(assignedRole) {
8
+ return assignedRole ? "filled" : "vacant";
9
+ }
10
+
11
+ // src/model/transitions.ts
12
+ var ROLE_MACHINE = [
13
+ { from: "free", to: "member", action: "hire" },
14
+ { from: "member", to: "on_duty", action: "appoint" },
15
+ { from: "on_duty", to: "member", action: "dismiss" },
16
+ { from: "member", to: "free", action: "fire" },
17
+ { from: "on_duty", to: "free", action: "fire" }
18
+ ];
19
+ var POSITION_MACHINE = [
20
+ { from: "vacant", to: "filled", action: "appoint" },
21
+ { from: "filled", to: "vacant", action: "dismiss" }
22
+ ];
23
+ function findTransition(machine, from, action) {
24
+ return machine.find((t) => t.from === from && t.action === action) ?? null;
25
+ }
26
+ function canTransition(machine, from, action) {
27
+ return findTransition(machine, from, action) !== null;
28
+ }
29
+ function transition(machine, from, action) {
30
+ const t = findTransition(machine, from, action);
31
+ if (!t) {
32
+ throw new Error(`Invalid transition: cannot "${action}" from state "${from}"`);
33
+ }
34
+ return t.to;
35
+ }
36
+
37
+ // src/model/relations.ts
38
+ var RELATIONS = [
39
+ {
40
+ entity: "role",
41
+ relation: "organization",
42
+ description: "A role can belong to at most one organization"
43
+ },
44
+ { entity: "role", relation: "position", description: "A role can hold at most one position" },
45
+ {
46
+ entity: "position",
47
+ relation: "role",
48
+ description: "A position can be held by at most one role"
49
+ }
50
+ ];
51
+ function validateOneToOne(entityName, currentValue, newValue, constraintDesc) {
52
+ if (currentValue && currentValue !== newValue) {
53
+ throw new Error(`${constraintDesc}: "${entityName}" is already assigned to "${currentValue}"`);
54
+ }
55
+ }
56
+ export {
57
+ POSITION_MACHINE,
58
+ RELATIONS,
59
+ ROLE_MACHINE,
60
+ canTransition,
61
+ findTransition,
62
+ getPositionState,
63
+ getRoleState,
64
+ transition,
65
+ validateOneToOne
66
+ };
1
67
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/model/states.ts","../src/model/transitions.ts","../src/model/relations.ts"],"sourcesContent":["/**\n * states.ts — Role and Position state definitions.\n *\n * Role: free → member → on_duty\n * Position: vacant → filled\n */\n\nexport type RoleState = \"free\" | \"member\" | \"on_duty\";\nexport type PositionState = \"vacant\" | \"filled\";\n\n/**\n * Derive a role's state from assignment data.\n */\nexport function getRoleState(assignment: { org: string; position?: string } | null): RoleState {\n if (!assignment) return \"free\";\n if (assignment.position) return \"on_duty\";\n return \"member\";\n}\n\n/**\n * Derive a position's state from assignment data.\n */\nexport function getPositionState(assignedRole: string | null): PositionState {\n return assignedRole ? \"filled\" : \"vacant\";\n}\n","/**\n * transitions.ts — State machine definitions and transition logic.\n *\n * Role transitions:\n * free --(hire)--> member --(appoint)--> on_duty\n * on_duty --(dismiss)--> member --(fire)--> free\n * on_duty --(fire)--> free (auto-dismiss)\n *\n * Position transitions:\n * vacant --(appoint)--> filled --(dismiss)--> vacant\n */\n\nimport type { RoleState, PositionState } from \"./states.js\";\n\nexport interface Transition<S extends string> {\n readonly from: S;\n readonly to: S;\n readonly action: string;\n}\n\nexport const ROLE_MACHINE: Transition<RoleState>[] = [\n { from: \"free\", to: \"member\", action: \"hire\" },\n { from: \"member\", to: \"on_duty\", action: \"appoint\" },\n { from: \"on_duty\", to: \"member\", action: \"dismiss\" },\n { from: \"member\", to: \"free\", action: \"fire\" },\n { from: \"on_duty\", to: \"free\", action: \"fire\" },\n];\n\nexport const POSITION_MACHINE: Transition<PositionState>[] = [\n { from: \"vacant\", to: \"filled\", action: \"appoint\" },\n { from: \"filled\", to: \"vacant\", action: \"dismiss\" },\n];\n\n/**\n * Find a transition by current state and action.\n */\nexport function findTransition<S extends string>(\n machine: Transition<S>[],\n from: S,\n action: string\n): Transition<S> | null {\n return machine.find((t) => t.from === from && t.action === action) ?? null;\n}\n\n/**\n * Check if a transition is valid.\n */\nexport function canTransition<S extends string>(\n machine: Transition<S>[],\n from: S,\n action: string\n): boolean {\n return findTransition(machine, from, action) !== null;\n}\n\n/**\n * Execute a transition — returns new state or throws.\n */\nexport function transition<S extends string>(machine: Transition<S>[], from: S, action: string): S {\n const t = findTransition(machine, from, action);\n if (!t) {\n throw new Error(`Invalid transition: cannot \"${action}\" from state \"${from}\"`);\n }\n return t.to;\n}\n","/**\n * relations.ts — One-to-one relationship constraints.\n *\n * - A role can belong to at most one organization\n * - A role can hold at most one position\n * - A position can be held by at most one role\n */\n\nexport interface OneToOneConstraint {\n readonly entity: string;\n readonly relation: string;\n readonly description: string;\n}\n\nexport const RELATIONS: OneToOneConstraint[] = [\n {\n entity: \"role\",\n relation: \"organization\",\n description: \"A role can belong to at most one organization\",\n },\n { entity: \"role\", relation: \"position\", description: \"A role can hold at most one position\" },\n {\n entity: \"position\",\n relation: \"role\",\n description: \"A position can be held by at most one role\",\n },\n];\n\n/**\n * Validate that a one-to-one assignment does not conflict.\n * Throws if the entity is already assigned.\n */\nexport function validateOneToOne(\n entityName: string,\n currentValue: string | null,\n newValue: string,\n constraintDesc: string\n): void {\n if (currentValue && currentValue !== newValue) {\n throw new Error(`${constraintDesc}: \"${entityName}\" is already assigned to \"${currentValue}\"`);\n }\n}\n"],"mappings":";AAaO,SAAS,aAAa,YAAkE;AAC7F,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,WAAW,SAAU,QAAO;AAChC,SAAO;AACT;AAKO,SAAS,iBAAiB,cAA4C;AAC3E,SAAO,eAAe,WAAW;AACnC;;;ACJO,IAAM,eAAwC;AAAA,EACnD,EAAE,MAAM,QAAQ,IAAI,UAAU,QAAQ,OAAO;AAAA,EAC7C,EAAE,MAAM,UAAU,IAAI,WAAW,QAAQ,UAAU;AAAA,EACnD,EAAE,MAAM,WAAW,IAAI,UAAU,QAAQ,UAAU;AAAA,EACnD,EAAE,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAAA,EAC7C,EAAE,MAAM,WAAW,IAAI,QAAQ,QAAQ,OAAO;AAChD;AAEO,IAAM,mBAAgD;AAAA,EAC3D,EAAE,MAAM,UAAU,IAAI,UAAU,QAAQ,UAAU;AAAA,EAClD,EAAE,MAAM,UAAU,IAAI,UAAU,QAAQ,UAAU;AACpD;AAKO,SAAS,eACd,SACA,MACA,QACsB;AACtB,SAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,WAAW,MAAM,KAAK;AACxE;AAKO,SAAS,cACd,SACA,MACA,QACS;AACT,SAAO,eAAe,SAAS,MAAM,MAAM,MAAM;AACnD;AAKO,SAAS,WAA6B,SAA0B,MAAS,QAAmB;AACjG,QAAM,IAAI,eAAe,SAAS,MAAM,MAAM;AAC9C,MAAI,CAAC,GAAG;AACN,UAAM,IAAI,MAAM,+BAA+B,MAAM,iBAAiB,IAAI,GAAG;AAAA,EAC/E;AACA,SAAO,EAAE;AACX;;;AClDO,IAAM,YAAkC;AAAA,EAC7C;AAAA,IACE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AAAA,EACA,EAAE,QAAQ,QAAQ,UAAU,YAAY,aAAa,uCAAuC;AAAA,EAC5F;AAAA,IACE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf;AACF;AAMO,SAAS,iBACd,YACA,cACA,UACA,gBACM;AACN,MAAI,gBAAgB,iBAAiB,UAAU;AAC7C,UAAM,IAAI,MAAM,GAAG,cAAc,MAAM,UAAU,6BAA6B,YAAY,GAAG;AAAA,EAC/F;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rolexjs/core",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "RoleX Core - AI Agent Role Management Framework",
5
5
  "keywords": [
6
6
  "rolex",