@undefineds.co/models 0.2.26 → 0.2.28
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 +12 -0
- package/dist/approval.schema.js +2 -1
- package/dist/audit.schema.js +2 -1
- package/dist/bin/udfs.d.ts +2 -0
- package/dist/bin/udfs.js +430 -0
- package/dist/chat.repository.d.ts +8 -0
- package/dist/chat.schema.d.ts +10 -0
- package/dist/chat.schema.js +9 -2
- package/dist/chat.utils.js +24 -9
- package/dist/index.d.ts +7 -3
- package/dist/index.js +7 -3
- package/dist/message.repository.d.ts +29 -9
- package/dist/message.schema.d.ts +29 -6
- package/dist/message.schema.js +26 -10
- package/dist/namespaces.js +23 -0
- package/dist/pod-storage-descriptor.d.ts +189 -0
- package/dist/pod-storage-descriptor.js +283 -0
- package/dist/repository.d.ts +2 -0
- package/dist/repository.js +3 -0
- package/dist/resource-id-defaults.d.ts +18 -0
- package/dist/resource-id-defaults.js +84 -0
- package/dist/run.schema.d.ts +112 -0
- package/dist/run.schema.js +89 -0
- package/dist/schema.d.ts +132 -8
- package/dist/schema.js +8 -0
- package/dist/session/session.schema.js +2 -1
- package/dist/sidecar/sidecar-events.d.ts +36 -36
- package/dist/task.schema.d.ts +62 -0
- package/dist/task.schema.js +49 -0
- package/dist/thread.repository.d.ts +15 -3
- package/dist/thread.schema.d.ts +14 -2
- package/dist/thread.schema.js +13 -5
- package/package.json +25 -3
- package/skills/README.md +41 -0
- package/skills/solid-modeling/SKILL.md +185 -0
- package/skills/solid-modeling/agents/openai.yaml +6 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { id, integer, object, podTable, string, timestamp, uri } from '@undefineds.co/drizzle-solid';
|
|
2
|
+
import { DCTerms, UDFS } from './namespaces.js';
|
|
3
|
+
import { threadResource } from './thread.schema.js';
|
|
4
|
+
import { taskResourceId } from './resource-id-defaults.js';
|
|
5
|
+
export const TaskStatus = {
|
|
6
|
+
ACTIVE: 'active',
|
|
7
|
+
PAUSED: 'paused',
|
|
8
|
+
COMPLETED: 'completed',
|
|
9
|
+
FAILED: 'failed',
|
|
10
|
+
};
|
|
11
|
+
export const TaskTriggerKind = {
|
|
12
|
+
ONCE: 'once',
|
|
13
|
+
INTERVAL: 'interval',
|
|
14
|
+
CRON: 'cron',
|
|
15
|
+
EVENT: 'event',
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Task resource.
|
|
19
|
+
*
|
|
20
|
+
* Task is a durable task-style command, parallel to Chat as a command surface.
|
|
21
|
+
* It is intentionally generic: protocol-specific request, response, and event
|
|
22
|
+
* shapes stay in adapter code.
|
|
23
|
+
*/
|
|
24
|
+
export const taskResource = podTable('task', {
|
|
25
|
+
id: id('id').default(taskResourceId),
|
|
26
|
+
surfaceId: string('surfaceId').predicate(UDFS.surfaceId).notNull().default('default'),
|
|
27
|
+
title: string('title').predicate(DCTerms.title),
|
|
28
|
+
prompt: string('prompt').predicate(UDFS.prompt).notNull(),
|
|
29
|
+
thread: uri('thread').predicate(UDFS.inThread).link(threadResource),
|
|
30
|
+
workspace: uri('workspace').predicate(UDFS.workspace).notNull(),
|
|
31
|
+
runner: string('runner').predicate(UDFS.runner).notNull(),
|
|
32
|
+
status: string('status').predicate(UDFS.status).notNull().default(TaskStatus.ACTIVE),
|
|
33
|
+
triggerKind: string('triggerKind').predicate(UDFS.triggerKind).notNull().default(TaskTriggerKind.ONCE),
|
|
34
|
+
cron: string('cron').predicate(UDFS.cron),
|
|
35
|
+
intervalSeconds: integer('intervalSeconds').predicate(UDFS.intervalSeconds),
|
|
36
|
+
eventName: string('eventName').predicate(UDFS.eventName),
|
|
37
|
+
nextRunAt: timestamp('nextRunAt').predicate(UDFS.nextRunAt),
|
|
38
|
+
lastRunAt: timestamp('lastRunAt').predicate(UDFS.lastRunAt),
|
|
39
|
+
metadata: object('metadata').predicate(UDFS.metadata),
|
|
40
|
+
createdAt: timestamp('createdAt').predicate(DCTerms.created).notNull().defaultNow(),
|
|
41
|
+
updatedAt: timestamp('updatedAt').predicate(DCTerms.modified).notNull().defaultNow(),
|
|
42
|
+
}, {
|
|
43
|
+
base: '/.data/task/',
|
|
44
|
+
sparqlEndpoint: '/.data/task/-/sparql',
|
|
45
|
+
type: UDFS.Task,
|
|
46
|
+
namespace: UDFS,
|
|
47
|
+
});
|
|
48
|
+
// Compatibility alias. New model code should prefer `taskResource`.
|
|
49
|
+
export const taskTable = taskResource;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export declare const threadRepository: import("@undefineds.co/drizzle-solid/dist/core/repository").PodRepositoryDescriptor<import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
2
2
|
id: import("@undefineds.co/drizzle-solid/dist/core/schema").PodStringColumn<false, false>;
|
|
3
|
-
|
|
3
|
+
commandKind: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
4
|
+
surfaceId: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
5
|
+
chat: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
4
6
|
title: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
7
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
5
8
|
starred: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"boolean", null, false, true>;
|
|
6
9
|
workspace: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
7
10
|
metadata: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"object", null, false, false>;
|
|
@@ -9,17 +12,23 @@ export declare const threadRepository: import("@undefineds.co/drizzle-solid/dist
|
|
|
9
12
|
updatedAt: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"datetime", null, true, true>;
|
|
10
13
|
}>>, {
|
|
11
14
|
id: string;
|
|
15
|
+
commandKind: string;
|
|
16
|
+
surfaceId: string;
|
|
12
17
|
chat: string;
|
|
13
18
|
title: string;
|
|
19
|
+
status: string;
|
|
14
20
|
starred: boolean;
|
|
15
21
|
workspace: string;
|
|
16
22
|
metadata: Record<string, unknown>;
|
|
17
23
|
createdAt: Date;
|
|
18
24
|
updatedAt: Date;
|
|
19
25
|
}, {
|
|
20
|
-
chat: string;
|
|
21
26
|
id?: string | undefined;
|
|
27
|
+
commandKind?: string | undefined;
|
|
28
|
+
surfaceId?: string | undefined;
|
|
29
|
+
chat?: string | undefined;
|
|
22
30
|
title?: string | undefined;
|
|
31
|
+
status?: string | undefined;
|
|
23
32
|
starred?: boolean | undefined;
|
|
24
33
|
workspace?: string | undefined;
|
|
25
34
|
metadata?: Record<string, unknown> | undefined;
|
|
@@ -27,8 +36,11 @@ export declare const threadRepository: import("@undefineds.co/drizzle-solid/dist
|
|
|
27
36
|
updatedAt?: Date | undefined;
|
|
28
37
|
}, {
|
|
29
38
|
id?: string | null | undefined;
|
|
30
|
-
|
|
39
|
+
commandKind?: string | undefined;
|
|
40
|
+
surfaceId?: string | undefined;
|
|
41
|
+
chat?: string | null | undefined;
|
|
31
42
|
title?: string | null | undefined;
|
|
43
|
+
status?: string | undefined;
|
|
32
44
|
starred?: boolean | null | undefined;
|
|
33
45
|
workspace?: string | null | undefined;
|
|
34
46
|
metadata?: Record<string, unknown> | null | undefined;
|
package/dist/thread.schema.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export type ThreadStatusType = 'active' | 'locked' | 'closed';
|
|
2
|
+
export declare const ThreadStatus: {
|
|
3
|
+
readonly ACTIVE: "active";
|
|
4
|
+
readonly LOCKED: "locked";
|
|
5
|
+
readonly CLOSED: "closed";
|
|
6
|
+
};
|
|
1
7
|
/**
|
|
2
8
|
* Thread resource.
|
|
3
9
|
*
|
|
@@ -22,8 +28,11 @@
|
|
|
22
28
|
*/
|
|
23
29
|
export declare const threadResource: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
24
30
|
id: import("@undefineds.co/drizzle-solid/dist/core/schema").PodStringColumn<false, false>;
|
|
25
|
-
|
|
31
|
+
commandKind: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
32
|
+
surfaceId: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
33
|
+
chat: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
26
34
|
title: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
35
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
27
36
|
starred: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"boolean", null, false, true>;
|
|
28
37
|
workspace: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
29
38
|
metadata: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"object", null, false, false>;
|
|
@@ -32,8 +41,11 @@ export declare const threadResource: import("@undefineds.co/drizzle-solid/dist/c
|
|
|
32
41
|
}>>;
|
|
33
42
|
export declare const threadTable: import("@undefineds.co/drizzle-solid/dist/core/schema").PodTableWithColumns<import("@undefineds.co/drizzle-solid/dist/core/schema").ResolvedColumns<{
|
|
34
43
|
id: import("@undefineds.co/drizzle-solid/dist/core/schema").PodStringColumn<false, false>;
|
|
35
|
-
|
|
44
|
+
commandKind: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
45
|
+
surfaceId: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
46
|
+
chat: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
36
47
|
title: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, false, false>;
|
|
48
|
+
status: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"string", null, true, true>;
|
|
37
49
|
starred: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"boolean", null, false, true>;
|
|
38
50
|
workspace: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"uri", null, false, false>;
|
|
39
51
|
metadata: import("@undefineds.co/drizzle-solid/dist/core/schema").ColumnBuilder<"object", null, false, false>;
|
package/dist/thread.schema.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { uri, boolean, object, podTable, string, timestamp, id } from '@undefineds.co/drizzle-solid';
|
|
2
2
|
import { UDFS, DCTerms, SIOC } from './namespaces.js';
|
|
3
3
|
import { chatResource } from './chat.schema.js';
|
|
4
|
+
import { threadResourceId } from './resource-id-defaults.js';
|
|
5
|
+
export const ThreadStatus = {
|
|
6
|
+
ACTIVE: 'active',
|
|
7
|
+
LOCKED: 'locked',
|
|
8
|
+
CLOSED: 'closed',
|
|
9
|
+
};
|
|
4
10
|
/**
|
|
5
11
|
* Thread resource.
|
|
6
12
|
*
|
|
@@ -24,11 +30,14 @@ import { chatResource } from './chat.schema.js';
|
|
|
24
30
|
* container URI here and store portable metadata with that container/resource.
|
|
25
31
|
*/
|
|
26
32
|
export const threadResource = podTable('thread', {
|
|
27
|
-
id: id('id'),
|
|
33
|
+
id: id('id').default(threadResourceId),
|
|
34
|
+
commandKind: string('commandKind').predicate(UDFS.commandKind).notNull().default('chat'),
|
|
35
|
+
surfaceId: string('surfaceId').predicate(UDFS.surfaceId).notNull().default('default'),
|
|
28
36
|
// Belongs to chat/counterpart. Stored as an RDF URI; short ids are resolved via chatResource's URI template by the ORM.
|
|
29
|
-
chat: uri('chat').predicate(SIOC.has_parent).
|
|
37
|
+
chat: uri('chat').predicate(SIOC.has_parent).link(chatResource),
|
|
30
38
|
// Display / state
|
|
31
39
|
title: string('title').predicate(DCTerms.title),
|
|
40
|
+
status: string('status').predicate(UDFS.status).notNull().default(ThreadStatus.ACTIVE),
|
|
32
41
|
starred: boolean('starred').predicate(UDFS.favorite).default(false),
|
|
33
42
|
// Storage-layer execution context reference: container/resource URI
|
|
34
43
|
workspace: uri('workspace').predicate(UDFS.workspace),
|
|
@@ -37,11 +46,10 @@ export const threadResource = podTable('thread', {
|
|
|
37
46
|
createdAt: timestamp('createdAt').predicate(DCTerms.created).notNull().defaultNow(),
|
|
38
47
|
updatedAt: timestamp('updatedAt').predicate(DCTerms.modified).notNull().defaultNow(),
|
|
39
48
|
}, {
|
|
40
|
-
base: '/.data/
|
|
41
|
-
sparqlEndpoint: '/.data
|
|
49
|
+
base: '/.data/',
|
|
50
|
+
sparqlEndpoint: '/.data/-/sparql',
|
|
42
51
|
type: SIOC.Thread,
|
|
43
52
|
namespace: UDFS,
|
|
44
|
-
subjectTemplate: '{chat|id}/index.ttl#{id}',
|
|
45
53
|
});
|
|
46
54
|
// Compatibility alias. New model code should prefer `threadResource`.
|
|
47
55
|
export const threadTable = threadResource;
|
package/package.json
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@undefineds.co/models",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.28",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"pi-package",
|
|
10
|
+
"solid",
|
|
11
|
+
"rdf",
|
|
12
|
+
"pod",
|
|
13
|
+
"drizzle-solid",
|
|
14
|
+
"models"
|
|
15
|
+
],
|
|
16
|
+
"pi": {
|
|
17
|
+
"skills": [
|
|
18
|
+
"./skills"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"udfs": "./dist/bin/udfs.js"
|
|
23
|
+
},
|
|
8
24
|
"repository": {
|
|
9
25
|
"type": "git",
|
|
10
26
|
"url": "git+https://github.com/undefinedsco/models.git"
|
|
@@ -60,15 +76,17 @@
|
|
|
60
76
|
"build": "tsc -p tsconfig.json && node scripts/fix-dist-esm.mjs",
|
|
61
77
|
"lint": "echo \"lint not configured\"",
|
|
62
78
|
"pack:release": "node scripts/pack-release.mjs",
|
|
79
|
+
"skills:check": "node scripts/check-skills.mjs",
|
|
80
|
+
"skills:pack": "yarn skills:check && node scripts/pack-skills.mjs",
|
|
63
81
|
"sync:discovery:vercel": "node --experimental-strip-types scripts/sync-discovery-vercel.ts",
|
|
64
82
|
"test": "vitest run",
|
|
65
|
-
"test:ci": "vitest run tests/ai-config.test.ts tests/ai-runtime-schema.test.ts tests/client.test.ts tests/contracts-chat-contact.contract.test.ts tests/discovery-vercel.test.ts tests/discovery.test.ts tests/issue-schema.test.ts tests/profile.test.ts tests/repository.test.ts tests/resource-utils.test.ts tests/session-schema.test.ts tests/sidecar-events.contract.test.ts tests/resource-schema.test.ts",
|
|
83
|
+
"test:ci": "vitest run tests/ai-config.test.ts tests/ai-runtime-schema.test.ts tests/client.test.ts tests/contracts-chat-contact.contract.test.ts tests/discovery-vercel.test.ts tests/discovery.test.ts tests/issue-schema.test.ts tests/profile.test.ts tests/repository.test.ts tests/resource-utils.test.ts tests/session-schema.test.ts tests/sidecar-events.contract.test.ts tests/resource-schema.test.ts tests/resource-id-defaults.test.ts tests/pod-storage-descriptor.test.ts tests/udfs-cli.test.ts",
|
|
66
84
|
"test:pod": "dotenv -e ../linx-models/.env -- vitest run tests/pod.integration.test.ts"
|
|
67
85
|
},
|
|
68
86
|
"dependencies": {
|
|
69
87
|
"@comunica/query-sparql-solid": "^4.0.2",
|
|
70
88
|
"@inrupt/vocab-common-rdf": "^1.0.5",
|
|
71
|
-
"@undefineds.co/drizzle-solid": "^0.3.
|
|
89
|
+
"@undefineds.co/drizzle-solid": "^0.3.13",
|
|
72
90
|
"n3": "^1.26.0",
|
|
73
91
|
"zod": "^3.22.4"
|
|
74
92
|
},
|
|
@@ -77,9 +95,13 @@
|
|
|
77
95
|
"typescript": "^5.4.0",
|
|
78
96
|
"vitest": "^1.6.0"
|
|
79
97
|
},
|
|
98
|
+
"peerDependencies": {
|
|
99
|
+
"@undefineds.co/drizzle-solid": "^0.3.13"
|
|
100
|
+
},
|
|
80
101
|
"packageManager": "yarn@1.22.22",
|
|
81
102
|
"files": [
|
|
82
103
|
"dist",
|
|
104
|
+
"skills",
|
|
83
105
|
"README.md",
|
|
84
106
|
"package.json"
|
|
85
107
|
],
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Models Skills
|
|
2
|
+
|
|
3
|
+
This directory contains shared modeling skills owned by `@undefineds.co/models`.
|
|
4
|
+
|
|
5
|
+
`models` owns reusable Solid/RDF resource semantics for LinX, Xpod, and other
|
|
6
|
+
Pod-facing shells. Product shells should consume these skills and model
|
|
7
|
+
resources instead of keeping private copies of durable Pod modeling rules.
|
|
8
|
+
|
|
9
|
+
Current public skills:
|
|
10
|
+
|
|
11
|
+
- `solid-modeling` - shared Solid Pod, RDF, drizzle-solid, and resource-schema
|
|
12
|
+
modeling guidance.
|
|
13
|
+
|
|
14
|
+
Release automation validates this directory and packages:
|
|
15
|
+
|
|
16
|
+
- a generic skill archive for tools that understand `SKILL.md`
|
|
17
|
+
- a Codex plugin archive that contains the same skill source
|
|
18
|
+
- a Claude Code plugin archive that contains the same skill source
|
|
19
|
+
|
|
20
|
+
The publish workflow uploads those artifacts to the GitHub Release for the
|
|
21
|
+
version tag. It does not directly submit entries to Codex Marketplace or Claude
|
|
22
|
+
Code Marketplace.
|
|
23
|
+
|
|
24
|
+
Codex users can install the skill from the repository path once these files are
|
|
25
|
+
on `main`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx codex-marketplace add undefinedsco/models/skills/solid-modeling --skill --global
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Pi users can install the same skill through the package manifest:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pi install npm:@undefineds.co/models
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The npm package includes `skills/` and declares `pi.skills` in `package.json`,
|
|
38
|
+
so Pi discovers `skills/solid-modeling/SKILL.md` as a package skill.
|
|
39
|
+
|
|
40
|
+
Marketplace-specific submission steps should be added only when the target
|
|
41
|
+
platform has a documented publishing API or CLI.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: solid-modeling
|
|
3
|
+
description: Use when designing or reviewing shared Solid Pod, RDF, Linked Data, drizzle-solid, or @undefineds.co/models schemas; especially for URI vs id fields, default id functions, inverse links, chat/thread/message/task/run modeling, Pod persistence boundaries, and cross-app data semantics.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Solid Modeling
|
|
7
|
+
|
|
8
|
+
Use this skill when changing or reviewing shared Pod data models, RDF vocab
|
|
9
|
+
mappings, drizzle-solid schemas, repositories, or tests that assert durable
|
|
10
|
+
cross-app semantics.
|
|
11
|
+
|
|
12
|
+
## Core Stance
|
|
13
|
+
|
|
14
|
+
Model the Pod as a Linked Data graph, not as a relational database with foreign
|
|
15
|
+
keys.
|
|
16
|
+
|
|
17
|
+
- Use RDF/Pod relation fields for URI references.
|
|
18
|
+
- Use local ids only for UI state, runtime protocol keys, function parameters,
|
|
19
|
+
or the random key passed into an id default function.
|
|
20
|
+
- Treat durable `id` values as base-relative resource ids. If the storage path
|
|
21
|
+
or fragment is part of identity, the `id` must include it.
|
|
22
|
+
- Do not let a field named `xxxId` secretly behave like an RDF link.
|
|
23
|
+
- Prefer semantic relation names: `chat`, `thread`, `message`, `maker`,
|
|
24
|
+
`replyTo`, `workspace`, `task`, `run`, `agent`.
|
|
25
|
+
- UI-only state stays outside the Pod. Durable shared state belongs in the Pod.
|
|
26
|
+
|
|
27
|
+
## Package Ownership
|
|
28
|
+
|
|
29
|
+
`@undefineds.co/models` owns durable shared model semantics. `drizzle-solid`
|
|
30
|
+
owns the ORM/resource machinery. Product shells such as Xpod, LinX desktop,
|
|
31
|
+
CLI, mobile, or workers should not duplicate shared schemas.
|
|
32
|
+
|
|
33
|
+
- If a resource/schema/repository already exists in `models`, consume it.
|
|
34
|
+
- If a product needs a missing shared query, mutation, or id helper, add it to
|
|
35
|
+
`models` first with tests, then call it from the product shell.
|
|
36
|
+
- Keep product shells focused on interaction and adapter code: routing,
|
|
37
|
+
rendering, runtime protocol projection, local cache plumbing, and mapping
|
|
38
|
+
native runtime events into shared DTOs.
|
|
39
|
+
- Do not copy shared predicates, subject/id defaults, Turtle serializers, URI
|
|
40
|
+
builders, or resource lifecycle state machines into shells.
|
|
41
|
+
|
|
42
|
+
## ORM-First Pod Access
|
|
43
|
+
|
|
44
|
+
Do not hand-parse shared business TTL when a resource schema exists.
|
|
45
|
+
|
|
46
|
+
- Use `db.select().from(resource).where(...)` for list/subset reads.
|
|
47
|
+
- Use `db.findById`, `db.updateById`, and `db.deleteById` when callers hold a
|
|
48
|
+
canonical base-relative resource id.
|
|
49
|
+
- Use `db.findByIri`, `db.updateByIri`, and `db.deleteByIri` when the concrete
|
|
50
|
+
resource IRI is known.
|
|
51
|
+
- Use `db.findByResource`, `db.updateByResource`, and `db.deleteByResource`
|
|
52
|
+
only at adapter boundaries that intentionally accept mixed exact targets.
|
|
53
|
+
- Do not expose locator-shaped inputs in business APIs. `findByLocator`,
|
|
54
|
+
`updateByLocator`, and `deleteByLocator` are legacy compatibility surfaces.
|
|
55
|
+
- Raw Solid client or `fetch` access is acceptable only for protocol-level
|
|
56
|
+
adapters where no shared business resource exists yet.
|
|
57
|
+
|
|
58
|
+
## Ids, Defaults, and Subject Templates
|
|
59
|
+
|
|
60
|
+
The durable `id` is base-relative. It is not a fragment id.
|
|
61
|
+
|
|
62
|
+
Use an `id.default((key, row) => ...)` function when the id shape depends on
|
|
63
|
+
related resources, dates, command kind, workspace, or other row values. The
|
|
64
|
+
function should return the full base-relative resource id.
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
chatResourceId('default') === 'default/index.ttl#this'
|
|
70
|
+
messageResourceId('msg_1', row) === 'chat/default/2026/05/18/messages.ttl#msg_1'
|
|
71
|
+
runResourceId('run_1', row) === 'task/secretary/2026/05/18/runs.ttl#run_1'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Do not combine a full id default with a `subjectTemplate` that reparses or
|
|
75
|
+
wraps the same id. Exact ids should resolve directly against `base`.
|
|
76
|
+
|
|
77
|
+
Keep `subjectTemplate` only for simple resources where the id field is the
|
|
78
|
+
stable storage key and the template has no hidden dependency on another
|
|
79
|
+
resource. Prefer a default id function once the template needs parent paths,
|
|
80
|
+
date buckets, fragments, or associated resource ids.
|
|
81
|
+
|
|
82
|
+
If a user passes an explicit id, treat it as exact. Do not reinterpret it as a
|
|
83
|
+
random key or fragment id.
|
|
84
|
+
|
|
85
|
+
## URI Fields and Query Ergonomics
|
|
86
|
+
|
|
87
|
+
Schema storage semantics and app ergonomics are different layers.
|
|
88
|
+
|
|
89
|
+
### Pod Schema Layer
|
|
90
|
+
|
|
91
|
+
Use full URI relation fields:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
message.chat
|
|
95
|
+
message.thread
|
|
96
|
+
message.replyTo
|
|
97
|
+
thread.chat
|
|
98
|
+
run.thread
|
|
99
|
+
run.task
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Avoid persisted relation fields such as:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
message.chatId
|
|
106
|
+
message.threadId
|
|
107
|
+
thread.chatId
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
unless they are intentionally opaque literal protocol fields, not RDF links.
|
|
111
|
+
|
|
112
|
+
### Repository/API Layer
|
|
113
|
+
|
|
114
|
+
Short-id helpers are fine at API boundaries:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
messageRepository.listByThreadId(db, { chatId, threadId })
|
|
118
|
+
threadRepository.listByChatId(db, { chatId })
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
These helpers should derive canonical Pod IRIs or base-relative ids internally.
|
|
122
|
+
Do not force UI/CLI callers to manually construct Pod IRIs in every query.
|
|
123
|
+
|
|
124
|
+
## Chat, Task, Thread, Message, Run, Step
|
|
125
|
+
|
|
126
|
+
Use these concepts consistently across products:
|
|
127
|
+
|
|
128
|
+
- `Chat`: interactive command surface/counterpart. It answers who or what the
|
|
129
|
+
user is talking with.
|
|
130
|
+
- `Task`: task-style command surface, parallel to Chat. It describes recurring,
|
|
131
|
+
triggered, or one-off task intent.
|
|
132
|
+
- `Thread`: concrete timeline/place under a Chat or Task.
|
|
133
|
+
- `Message`: human/runtime communication item in a Thread, linked to the Chat
|
|
134
|
+
or Task surface when useful.
|
|
135
|
+
- `Run`: one concrete execution attempt by an Agent Runtime.
|
|
136
|
+
- `RunStep`: append-only execution facts for a Run.
|
|
137
|
+
|
|
138
|
+
Chat and Task are command surfaces. Run is the state center for execution.
|
|
139
|
+
RunStep is not a separate event store elsewhere; store it with Run when the
|
|
140
|
+
storage layout is date-bucketed.
|
|
141
|
+
|
|
142
|
+
## Solid Chat Relationship Guidance
|
|
143
|
+
|
|
144
|
+
Align with graph semantics:
|
|
145
|
+
|
|
146
|
+
| Concept | Preferred RDF direction | Typical predicate |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| chat contains message | `chat -> message` | `wf:message` / project vocabulary |
|
|
149
|
+
| thread contains message | `thread -> message` | `sioc:has_member` or equivalent |
|
|
150
|
+
| reply points to original | `replyMessage -> originalMessage` | `sioc:has_reply` / project predicate |
|
|
151
|
+
| author/maker | `message -> maker` | `foaf:maker` |
|
|
152
|
+
|
|
153
|
+
When inverse predicates are supported, use them for read/write symmetry. If the
|
|
154
|
+
ORM cannot safely express the inverse write, put the relation writer in the
|
|
155
|
+
repository and cover it with integration tests.
|
|
156
|
+
|
|
157
|
+
## Resource Naming
|
|
158
|
+
|
|
159
|
+
Use `Resource` names for shared models.
|
|
160
|
+
|
|
161
|
+
- Export `chatResource`, `messageResource`, `taskResource`, `runResource`.
|
|
162
|
+
- Keep `chatTable`-style aliases only for compatibility while downstream code
|
|
163
|
+
migrates.
|
|
164
|
+
- New shared-model code should prefer `solidResources` over table registries.
|
|
165
|
+
|
|
166
|
+
## Testing Expectations
|
|
167
|
+
|
|
168
|
+
For shared schema changes, verify both ergonomics and graph semantics:
|
|
169
|
+
|
|
170
|
+
1. Unit tests for id/default helpers and URI builders.
|
|
171
|
+
2. Resource tests that assert exact-id mode or the intended `subjectTemplate`.
|
|
172
|
+
3. Repository or Pod integration tests for relation read/write behavior.
|
|
173
|
+
4. Assertions that produced IRIs contain no unresolved template placeholders.
|
|
174
|
+
|
|
175
|
+
Do not preserve obsolete tests that encode abandoned storage paths. Rewrite
|
|
176
|
+
them around current Pod semantics.
|
|
177
|
+
|
|
178
|
+
## Product Boundary
|
|
179
|
+
|
|
180
|
+
Product-specific domain rules do not belong in this skill.
|
|
181
|
+
|
|
182
|
+
- Put product data semantics in owning schemas, repositories, and shared docs.
|
|
183
|
+
- Keep this skill limited to reusable Solid/RDF modeling guidance.
|
|
184
|
+
- If product terms such as `chat`, `task`, `run`, or `agent` become shared,
|
|
185
|
+
encode the durable semantics in `models`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Solid Modeling"
|
|
3
|
+
short_description: "Design shared Solid/RDF model schemas"
|
|
4
|
+
default_prompt: "Use $solid-modeling to review this shared Pod schema for RDF links, id defaults, and resource ownership."
|
|
5
|
+
policy:
|
|
6
|
+
allow_implicit_invocation: true
|