feat: State of Affairs (SoA) ontology for knowledge representation#704
feat: State of Affairs (SoA) ontology for knowledge representation#704data-bot-coasys wants to merge 6 commits intodevfrom
Conversation
Introduces the SoA schema as a top-level AD4M project with: - StateOfAffair: universal base class for propositions with modalities (belief, observation, intention, vision, plan, skill) - SoARelationship: typed edges between SoA nodes (supports, contradicts, similar, same, requires, enables, parent, refines, blocks) - TypeScript model classes using Ad4mModel decorators (for UIs/Flux) - JSON schemas with x-ad4m extensions (for MCP/programmatic access) Designed to work for both human and AI agent knowledge trees, supporting the Eve collective intelligence architecture. Part of the State of Affairs trees concept from the Eve vision.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a new State of Affairs (SoA) ontology package: TypeScript Ad4mModel for SoA, canonical soa:// expressions registry, a read-only language adapter and UI wiring, package manifests and build scripts, TypeScript configs, and documentation for predicates, modalities, and usage. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
soa/src/Relationship.ts (1)
51-57: UseSoARelationshipTypeforrelationshipTypeinstead ofstring.The union already exists but isn’t applied, so invalid relationship values compile.
Type-safe field
- relationshipType: string; + relationshipType: SoARelationshipType;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/src/Relationship.ts` around lines 51 - 57, The relationshipType property in Relationship (the `@Property-decorated` field) is incorrectly typed as string; change its TypeScript type to the existing union SoARelationshipType (i.e., relationshipType: SoARelationshipType) and add the appropriate import for SoARelationshipType if not already in the file so invalid relationship values fail type checking.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@soa/package.json`:
- Around line 5-6: The package.json currently points "main" and "types" at
TypeScript sources (main/types) which will break consumers; add a tsconfig.json
at the soa root that emits compiled JS and declaration files to dist (set outDir
to ./dist and declaration true, include src), add a "build" script in
soa/package.json that runs tsc, update "main" to "dist/index.js" and "types" to
"dist/index.d.ts", and add an "exports" field mapping "." to { "types":
"./dist/index.d.ts", "default": "./dist/index.js" } so Node resolution works for
published packages.
In `@soa/README.md`:
- Around line 67-70: The TypeScript snippet uses incorrect field names on
SoARelationship; update the assignment lines that set rel.type, rel.source, and
rel.target to use the correct properties rel.relationshipType, rel.sourceRef,
and rel.targetRef respectively, keeping the same values (e.g.,
belief.baseExpression and goal.baseExpression) so the example matches the
SoARelationship interface/implementation.
- Around line 24-33: The README relationship table lists a `child` relationship
that isn't present in the exported type/schema; update the docs to match the
schema by removing the `child` entry (or replacing the "parent / child" row with
just `parent`) in the Relationship table so only supported relationships (e.g.,
`parent`) are documented; ensure you edit the table row containing the "`parent`
/ `child`" text in the README to reflect the actual exported symbol `parent`.
- Around line 36-47: The README.md fenced directory block lacks a language
identifier and triggers markdownlint MD040; update the opening fence for the
block shown (the triple-backtick block containing the soa/ tree) to include a
language identifier such as "text" (i.e., change ``` to ```text) so the code
block is explicitly typed and the linter warning is resolved.
In `@soa/src/Relationship.ts`:
- Around line 82-117: The TypeScript model currently marks strength, note,
author, and createdAt as required but the JSON schema makes them optional;
update the Relationship model by adding the optional marker to those properties
(change strength, note, author, createdAt to strength?, note?, author?,
createdAt?) where they are declared with the `@Property` decorator in
Relationship.ts so the TS model aligns with soa/schemas/Relationship.json.
In `@soa/src/StateOfAffair.ts`:
- Around line 47-152: The class properties currently use incorrect types and
requiredness: change the modality property's type from string to SoAModality
(import SoAModality where needed) and mark all other properties except title and
modality as optional (use ? on description, confidence, status, author,
createdAt, updatedAt, tags, priority, source) so the TypeScript class aligns
with soa/schemas/StateOfAffair.json; ensure Property decorators remain but
update the TypeScript signatures for modality and the optional fields (refer to
symbols modality, title, description, confidence, status, author, createdAt,
updatedAt, tags, priority, source).
---
Nitpick comments:
In `@soa/src/Relationship.ts`:
- Around line 51-57: The relationshipType property in Relationship (the
`@Property-decorated` field) is incorrectly typed as string; change its TypeScript
type to the existing union SoARelationshipType (i.e., relationshipType:
SoARelationshipType) and add the appropriate import for SoARelationshipType if
not already in the file so invalid relationship values fail type checking.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
soa/README.mdsoa/package.jsonsoa/schemas/Relationship.jsonsoa/schemas/StateOfAffair.jsonsoa/src/Relationship.tssoa/src/StateOfAffair.tssoa/src/index.ts
soa/package.json
Outdated
| "main": "src/index.ts", | ||
| "types": "src/index.ts", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
jq '{main,types,exports,files}' soa/package.json
echo "---- tsconfig compiler options ----"
fd 'tsconfig.*json' soa | xargs -r -I{} sh -c 'echo "## {}"; jq ".compilerOptions | {outDir,declaration,emitDeclarationOnly,module,target}" "{}"'
echo "---- existing built entry artifacts ----"
fd 'index.(js|d.ts)$' soaRepository: coasys/ad4m
Length of output: 251
🏁 Script executed:
#!/bin/bash
# Check for root-level tsconfig
echo "---- Root tsconfig ----"
jq ".compilerOptions | {outDir,declaration,emitDeclarationOnly,module,target}" tsconfig.json 2>/dev/null || echo "No root tsconfig.json"
# Check soa package.json build scripts
echo "---- soa package.json build scripts ----"
jq '.scripts' soa/package.json
# Check if dist/ exists at root or soa level
echo "---- Checking for dist/ ----"
ls -la soa/dist 2>/dev/null || echo "No soa/dist/"
ls -la dist 2>/dev/null || echo "No root dist/"
# Check workspaces/monorepo setup
echo "---- Root package.json workspaces ----"
jq '.workspaces // .packages // "no workspaces field"' package.jsonRepository: coasys/ad4m
Length of output: 465
🏁 Script executed:
#!/bin/bash
# Check README or package.json description for soa
echo "---- soa package.json description ----"
jq '.description // "no description"' soa/package.json
# Check if soa is referenced as a dependency elsewhere
echo "---- References to soa in other packages ----"
rg '"soa"' --type json | head -20
# Check if there's any .npmignore or publish config
echo "---- Files in soa root ----"
ls -la soa/ | grep -E "npm|publish"
# Check git history or README in soa
echo "---- soa/README if exists ----"
cat soa/README.md 2>/dev/null || echo "No README.md"
</parameter>Repository: coasys/ad4m
Length of output: 3888
Publishing entrypoints require a build process and proper output configuration.
The main and types fields point to TypeScript source, which breaks consumers expecting transpiled JavaScript and type definitions. This package appears intended for npm publishing (per the README usage examples), but lacks the build infrastructure to support it.
To fix this, the package needs:
- A TypeScript configuration (tsconfig.json in soa/)
- A build script in package.json to generate dist/ with compiled JS and .d.ts files
- Update main/types to point to dist/ outputs
- Add the
exportsfield for modern Node.js resolution:
Example configuration
soa/tsconfig.json (minimal):
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"declaration": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"]
}soa/package.json:
{
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"scripts": {
"build": "tsc"
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@soa/package.json` around lines 5 - 6, The package.json currently points
"main" and "types" at TypeScript sources (main/types) which will break
consumers; add a tsconfig.json at the soa root that emits compiled JS and
declaration files to dist (set outDir to ./dist and declaration true, include
src), add a "build" script in soa/package.json that runs tsc, update "main" to
"dist/index.js" and "types" to "dist/index.d.ts", and add an "exports" field
mapping "." to { "types": "./dist/index.d.ts", "default": "./dist/index.js" } so
Node resolution works for published packages.
soa/src/Relationship.ts
Outdated
| @Property({ | ||
| through: 'soa://relationship_strength', | ||
| resolveLanguage: 'literal', | ||
| writable: true, | ||
| }) | ||
| strength: number; | ||
|
|
||
| /** | ||
| * Optional annotation explaining the relationship. | ||
| */ | ||
| @Property({ | ||
| through: 'soa://relationship_note', | ||
| resolveLanguage: 'literal', | ||
| writable: true, | ||
| }) | ||
| note: string; | ||
|
|
||
| /** | ||
| * Who asserted this relationship. | ||
| */ | ||
| @Property({ | ||
| through: 'soa://relationship_author', | ||
| resolveLanguage: 'literal', | ||
| writable: true, | ||
| }) | ||
| author: string; | ||
|
|
||
| /** | ||
| * ISO 8601 timestamp of creation. | ||
| */ | ||
| @Property({ | ||
| through: 'soa://relationship_created_at', | ||
| resolveLanguage: 'literal', | ||
| writable: true, | ||
| }) | ||
| createdAt: string; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -path "*/soa/schemas/Relationship.json" -type fRepository: coasys/ad4m
Length of output: 86
🏁 Script executed:
find . -path "*/soa/src/Relationship.ts" -type fRepository: coasys/ad4m
Length of output: 80
🏁 Script executed:
cat -n ./soa/schemas/Relationship.jsonRepository: coasys/ad4m
Length of output: 3191
🏁 Script executed:
cat -n ./soa/src/Relationship.tsRepository: coasys/ad4m
Length of output: 3643
Model requiredness is stricter than schema requiredness.
The fields strength, note, author, and createdAt are optional in soa/schemas/Relationship.json (only relationshipType, sourceRef, and targetRef are in the required array), but typed as required in the TypeScript model. Add the optional marker ? to align with the schema.
Align TS model with schema optional fields
- strength: number;
+ strength?: number;
...
- note: string;
+ note?: string;
...
- author: string;
+ author?: string;
...
- createdAt: string;
+ createdAt?: string;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Property({ | |
| through: 'soa://relationship_strength', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| strength: number; | |
| /** | |
| * Optional annotation explaining the relationship. | |
| */ | |
| @Property({ | |
| through: 'soa://relationship_note', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| note: string; | |
| /** | |
| * Who asserted this relationship. | |
| */ | |
| @Property({ | |
| through: 'soa://relationship_author', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| author: string; | |
| /** | |
| * ISO 8601 timestamp of creation. | |
| */ | |
| @Property({ | |
| through: 'soa://relationship_created_at', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| createdAt: string; | |
| `@Property`({ | |
| through: 'soa://relationship_strength', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| strength?: number; | |
| /** | |
| * Optional annotation explaining the relationship. | |
| */ | |
| `@Property`({ | |
| through: 'soa://relationship_note', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| note?: string; | |
| /** | |
| * Who asserted this relationship. | |
| */ | |
| `@Property`({ | |
| through: 'soa://relationship_author', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| author?: string; | |
| /** | |
| * ISO 8601 timestamp of creation. | |
| */ | |
| `@Property`({ | |
| through: 'soa://relationship_created_at', | |
| resolveLanguage: 'literal', | |
| writable: true, | |
| }) | |
| createdAt?: string; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@soa/src/Relationship.ts` around lines 82 - 117, The TypeScript model
currently marks strength, note, author, and createdAt as required but the JSON
schema makes them optional; update the Relationship model by adding the optional
marker to those properties (change strength, note, author, createdAt to
strength?, note?, author?, createdAt?) where they are declared with the
`@Property` decorator in Relationship.ts so the TS model aligns with
soa/schemas/Relationship.json.
soa/schemas/Relationship.json
Outdated
| "flag": { | ||
| "through": "soa://entry_type", | ||
| "value": "soa://relationship" | ||
| } |
There was a problem hiding this comment.
Do we really need a flag? I actually think that's an anti-pattern. The graph shape with used language ('soa' here) already provides enough constraints.
soa/schemas/Relationship.json
Outdated
| "through": "soa://relationship_type", | ||
| "resolveLanguage": "literal", | ||
| "writable": true | ||
| } |
There was a problem hiding this comment.
I think what might be more elegant would be to just use one link for relationships and have the 'soa' language have those types as expressions. I.e. soa://rel_supports, soa://rel_contradicts..
There was a problem hiding this comment.
Then we don't need a Relationship type at all. But we should talk about actually implementing that soa language (as a static language - just defining those static expressions which resolve to documentation :))
soa/schemas/Relationship.json
Outdated
| } | ||
| }, | ||
| "author": { | ||
| "type": "string", |
There was a problem hiding this comment.
not needed. every link that constitutes this shape is a link expression with author and timestamp. and there could be multiple authors (by multiple users creating that SoA even independently).
lucksus
left a comment
There was a problem hiding this comment.
Should the json be a shacl JSON representation?
- Remove Flag decorator (anti-pattern; graph shape + soa:// namespace suffices) - Remove Relationship model entirely — relationships are just AD4M links with soa://rel_* predicates (supports, contradicts, parent, etc.) - Remove author/createdAt/updatedAt fields — link expressions carry provenance - Remove JSON schema files — SHACL is auto-generated from decorators - Export relationship predicate constants (SoA.REL_SUPPORTS, etc.) - Mark optional fields with ? to match intended schema - Use SoAModality type instead of string for modality field Much simpler and more AD4M-native. The soa language should be implemented as a static language with these expressions resolving to documentation.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
soa/package.json (1)
5-12:⚠️ Potential issue | 🟠 MajorEntrypoints still target TypeScript source instead of build artifacts.
main/typespoint tosrc/index.ts, and published files only includesrc/. That will break plain Node/JS consumers unless they transpile your package themselves.Suggested packaging fix
- "main": "src/index.ts", - "types": "src/index.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, @@ - "files": [ - "src/" - ], + "files": [ + "dist/", + "src/" + ],#!/bin/bash set -e echo "== package entrypoints ==" jq '{main,types,exports,files,scripts}' soa/package.json echo "== tsconfig under soa ==" fd 'tsconfig.*json' soa --exec sh -c 'echo "## $1"; jq ".compilerOptions | {outDir,declaration,emitDeclarationOnly,module,target}" "$1"' sh {} echo "== built artifacts ==" fd 'index.(js|d.ts)$' soa/dist || true🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/package.json` around lines 5 - 12, The package.json currently points entry fields ("main" and "types") at the TypeScript source (src/index.ts) and publishes only src/, which breaks consumers; update package.json to point "main" to the compiled JS artifact (e.g. dist/index.js) and "types" to the generated declaration file (e.g. dist/index.d.ts), add dist to "files", and ensure the "build" script and tsconfig produce JS + .d.ts (enable declaration and set outDir) so the published package contains transpiled artifacts consumers can require.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@soa/package.json`:
- Around line 5-12: The package.json currently points entry fields ("main" and
"types") at the TypeScript source (src/index.ts) and publishes only src/, which
breaks consumers; update package.json to point "main" to the compiled JS
artifact (e.g. dist/index.js) and "types" to the generated declaration file
(e.g. dist/index.d.ts), add dist to "files", and ensure the "build" script and
tsconfig produce JS + .d.ts (enable declaration and set outDir) so the published
package contains transpiled artifacts consumers can require.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
soa/README.mdsoa/package.jsonsoa/src/StateOfAffair.tssoa/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- soa/src/index.ts
- soa/README.md
|
Hey Nico — all your review points are addressed in commit
The SoA language itself (defining those static expressions like |
Adds the soa:// language as a static, self-documenting vocabulary. Every soa:// expression resolves to structured documentation with: - name, description, kind (property vs relationship) - valueType for properties, examples as AD4M link triples - agentNotes: guidance specifically for AI agents This is a ReadOnlyLanguage — no new expressions can be created. All expressions are immutable and cacheable. Also serves as a pattern/template for how AD4M languages can act as self-documenting semantic vocabularies for any domain.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
soa/language/src/index.ts (2)
9-9: Unused import:SOA_EXPRESSIONS.
SOA_EXPRESSIONSis imported but never used in this file. It's only needed inadapter.ts.♻️ Remove unused import
import SoAExpressionAdapter from "./adapter.ts"; -import { SOA_EXPRESSIONS } from "./expressions.ts";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/language/src/index.ts` at line 9, Remove the unused import SOA_EXPRESSIONS from soa/language/src/index.ts; it’s not referenced in this file (only used in adapter.ts), so delete the import line "import { SOA_EXPRESSIONS } from \"./expressions.ts\";" to eliminate the unused symbol and any linter warnings.
66-74: Usesatisfies Languageto validate object shape while preserving type safety.The current
as Languagetype assertion suppresses type checking. Usingsatisfies Languageinstead validates that the object conforms to theLanguageinterface at compile-time without hiding potential type mismatches, which is the preferred TypeScript pattern.♻️ Use satisfies for type safety
- return { + const language = { name, expressionAdapter, expressionUI, iconFor, constructorIcon, isImmutableExpression, interactions, - } as Language; + } satisfies Language; + return language;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/language/src/index.ts` around lines 66 - 74, Replace the type assertion "as Language" on the returned object with the TypeScript "satisfies Language" operator so the compiler validates the object shape without widening types; update the return expression that currently includes name, expressionAdapter, expressionUI, iconFor, constructorIcon, isImmutableExpression, interactions to end with "satisfies Language" instead of "as Language".soa/language/src/adapter.ts (2)
58-63:addressOfimplementation could produce unexpected addresses.The fallback to
JSON.stringify(content)when neitherkeynoraddressis present may produce addresses that don't match any entry inSOA_EXPRESSIONS. Consider validating the address format or documenting the expected content structure.♻️ Proposed improvement for type safety
class SoAReadOnly implements ReadOnlyLanguage { async addressOf(content: object): Promise<Address> { - // For a read-only language, the address is the key itself - const c = content as Record<string, string>; - return c.key || c.address || JSON.stringify(content); + // For a read-only language, the address is the key itself + const c = content as { key?: string; address?: string }; + const addr = c.key ?? c.address; + if (!addr) { + throw new Error('SoA content must have a "key" or "address" property'); + } + return addr; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/language/src/adapter.ts` around lines 58 - 63, The current SoAReadOnly.addressOf implementation can return unpredictable JSON-stringified addresses which may not match SOA_EXPRESSIONS; update addressOf (class SoAReadOnly implementing ReadOnlyLanguage) to validate input and returned address: check for content.key or content.address and if absent either throw a clear validation error or normalize/derive a predictable address format, or validate the derived address against the expected pattern or membership in SOA_EXPRESSIONS before returning; include a brief error message referencing the missing key/address to aid callers and ensure the function never returns an arbitrary JSON string as the final Address.
31-55: Consider whether returning an error expression vs.nullis the intended behavior.Currently, unknown addresses return a signed error expression rather than
null. This is helpful for discoverability but may cause issues if callers expectnullfor non-existent addresses (the standard pattern forget()in most AD4M languages). Ensure consumers of this language handle both cases.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@soa/language/src/adapter.ts` around lines 31 - 55, The get(address: Address) method currently returns a signed error expression for unknown keys from SOA_EXPRESSIONS rather than the conventional null; change this to return null for unknown addresses to follow standard get() semantics, and move the signed error-expression creation into a separate helper (e.g., createNotFoundExpression) or keep the existing createSignedExpression call available for callers who want a verbose error; update get() to first strip the prefix, look up SOA_EXPRESSIONS[key], and if missing simply return null (while preserving createSignedExpression usage for any explicit callers that need an error payload).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@soa/language/package.json`:
- Around line 6-11: The package.json in soa/language is misconfigured: change
"main" to point to the compiled output (e.g., dist/index.js) rather than
src/index.ts, fix the "build" script so it references a real build entry (create
esbuild.ts in soa/language or change scripts.build to call an existing build
file), add esbuild to devDependencies so the build can run, declare the runtime
dependency for `@perspect3vism/ad4m` in dependencies (or remove/replace the CDN
import in source), and add soa/language to the root package.json workspaces
array so the monorepo recognizes the package; update the package.json fields
"main", "scripts.build", "devDependencies", and "dependencies" accordingly and
ensure a corresponding esbuild.ts or build task exists.
---
Nitpick comments:
In `@soa/language/src/adapter.ts`:
- Around line 58-63: The current SoAReadOnly.addressOf implementation can return
unpredictable JSON-stringified addresses which may not match SOA_EXPRESSIONS;
update addressOf (class SoAReadOnly implementing ReadOnlyLanguage) to validate
input and returned address: check for content.key or content.address and if
absent either throw a clear validation error or normalize/derive a predictable
address format, or validate the derived address against the expected pattern or
membership in SOA_EXPRESSIONS before returning; include a brief error message
referencing the missing key/address to aid callers and ensure the function never
returns an arbitrary JSON string as the final Address.
- Around line 31-55: The get(address: Address) method currently returns a signed
error expression for unknown keys from SOA_EXPRESSIONS rather than the
conventional null; change this to return null for unknown addresses to follow
standard get() semantics, and move the signed error-expression creation into a
separate helper (e.g., createNotFoundExpression) or keep the existing
createSignedExpression call available for callers who want a verbose error;
update get() to first strip the prefix, look up SOA_EXPRESSIONS[key], and if
missing simply return null (while preserving createSignedExpression usage for
any explicit callers that need an error payload).
In `@soa/language/src/index.ts`:
- Line 9: Remove the unused import SOA_EXPRESSIONS from
soa/language/src/index.ts; it’s not referenced in this file (only used in
adapter.ts), so delete the import line "import { SOA_EXPRESSIONS } from
\"./expressions.ts\";" to eliminate the unused symbol and any linter warnings.
- Around line 66-74: Replace the type assertion "as Language" on the returned
object with the TypeScript "satisfies Language" operator so the compiler
validates the object shape without widening types; update the return expression
that currently includes name, expressionAdapter, expressionUI, iconFor,
constructorIcon, isImmutableExpression, interactions to end with "satisfies
Language" instead of "as Language".
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3bc01b33-f3fc-4faf-acaf-2cce0dfbe158
📒 Files selected for processing (5)
soa/README.mdsoa/language/package.jsonsoa/language/src/adapter.tssoa/language/src/expressions.tssoa/language/src/index.ts
✅ Files skipped from review due to trivial changes (1)
- soa/README.md
soa/language/package.json
Outdated
| "main": "src/index.ts", | ||
| "scripts": { | ||
| "build": "node esbuild.ts" | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": {} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if esbuild.ts exists in the language directory
fd -t f "esbuild.ts" soa/language
# Check if there's a shared esbuild config at repo root
fd -t f "esbuild" -d 2Repository: coasys/ad4m
Length of output: 74
🏁 Script executed:
# Check the soa/language directory structure
ls -la soa/language/
# Look at root package.json for dependencies
cat -n package.json | head -50
# Check if there's an esbuild.ts in soa/language
ls -la soa/language/esbuild.ts 2>/dev/null || echo "esbuild.ts not found in soa/language"
# Check the imports in soa/language/src/index.ts
cat -n soa/language/src/index.tsRepository: coasys/ad4m
Length of output: 5393
🏁 Script executed:
# Find where soa/language actually is in the repo
find . -type d -name "soa" 2>/dev/null
# Check if there's a bootstrap-languages directory
ls -la bootstrap-languages/ 2>/dev/null || echo "No bootstrap-languages directory at root"
# Check git status to see file structure
git ls-files | grep -E "(soa|bootstrap)" | head -20Repository: coasys/ad4m
Length of output: 2333
🏁 Script executed:
# Check perspective-language structure
ls -la soa/perspective-language/
# Check if perspective-language has esbuild.ts
ls -la soa/perspective-language/esbuild.ts 2>/dev/null || echo "No esbuild.ts in perspective-language"
# Check perspective-language package.json
cat -n soa/perspective-language/package.jsonRepository: coasys/ad4m
Length of output: 252
Package configuration is incomplete and build script will fail.
- The
mainfield points to TypeScript source (src/index.ts) rather than compiled output, which consumers may not be able to import directly. - The build script references
esbuild.ts, but this file does not exist insoa/language/. devDependenciesis empty, butesbuildis required for the build script to execute.- The code imports
@perspect3vism/ad4mvia CDN (https://esm.sh/...) but no dependency is declared inpackage.json.
Additionally, soa/language is not included in the root package.json workspaces configuration, which may cause issues with monorepo tooling.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@soa/language/package.json` around lines 6 - 11, The package.json in
soa/language is misconfigured: change "main" to point to the compiled output
(e.g., dist/index.js) rather than src/index.ts, fix the "build" script so it
references a real build entry (create esbuild.ts in soa/language or change
scripts.build to call an existing build file), add esbuild to devDependencies so
the build can run, declare the runtime dependency for `@perspect3vism/ad4m` in
dependencies (or remove/replace the CDN import in source), and add soa/language
to the root package.json workspaces array so the monorepo recognizes the
package; update the package.json fields "main", "scripts.build",
"devDependencies", and "dependencies" accordingly and ensure a corresponding
esbuild.ts or build task exists.
- Remove unused SOA_EXPRESSIONS import from language/src/index.ts - Use 'satisfies Language' instead of 'as Language' for type safety - Improve addressOf to throw error instead of returning JSON.stringify fallback - Fix soa/package.json main/types to point to dist/, add exports field - Add tsconfig.json for proper TypeScript compilation - Fix soa/language/package.json with proper dependencies and devDependencies - Add esbuild.ts build script for language package
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@soa/language/esbuild.ts`:
- Around line 1-7: The build script uses import.meta.dirname (seen in the
esbuild.build call for entryPoints and outfile) which is unsupported on Node
16–20.10; replace usage with a Node-compatible resolution: derive a file path
from import.meta.url using fileURLToPath and path.dirname (import fileURLToPath
from "url" and use path.join) and then use that derived dirname in the
esbuild.build entryPoints and outfile options so the script runs on Node 16+.
In `@soa/language/src/adapter.ts`:
- Around line 36-45: ExpressionAdapter.get() currently creates and returns a
signed error expression for unknown addresses (inside the branch where doc is
falsy), but the method's contract requires returning null for unresolved
addresses; change the branch that builds an expression via
this.#agent.createSignedExpression(...) to simply return null when doc is not
found (remove the signed-expression creation in that path). Keep SOA_EXPRESSIONS
and knownKeys logic if you want to expose a dedicated discovery/known-address
endpoint, but do not return a truthy/expressive result from
ExpressionAdapter.get() — ensure the function returns null for unknown keys so
callers can distinguish "missing" from "found".
- Around line 59-66: The addressOf function currently returns the raw key or
address which creates duplicate identities; update the addressOf(content:
object): Promise<Address> implementation to canonicalize the result to the
soa:// form: extract the candidate from content.key or content.address (same
selection logic is fine), validate it exists, and if it does not already start
with the "soa://" scheme, prepend "soa://" before returning so both bare keys
and full addresses normalize to the same canonical Address; ensure you avoid
double-prefixing if the input already includes "soa://".
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: bb967fb6-4a43-4d46-af0c-b849605d3cda
📒 Files selected for processing (7)
package.jsonsoa/language/esbuild.tssoa/language/package.jsonsoa/language/src/adapter.tssoa/language/src/index.tssoa/package.jsonsoa/tsconfig.json
✅ Files skipped from review due to trivial changes (1)
- soa/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (3)
- soa/package.json
- soa/language/src/index.ts
- soa/language/package.json
- Replace import.meta.dirname with Node 16+ compatible path resolution - Return null for unknown addresses per ExpressionAdapter contract - Canonicalize addressOf to soa:// scheme to avoid duplicate identities
Fix applied: Node 18-compatible path resolution in esbuild.ts
Summary by CodeRabbit
New Features