@agentproto/identity 0.1.0-alpha.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 agentproto contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # @agentproto/identity
2
+
3
+ AIP-23 `IDENTITY.md` reference implementation. A workspace AIP that defines layered, composable agent identity — typed layers as AIP-18 collections, confidence-scored items, optional temporal entries, and compression-artifact tiers — owning only the workspace root manifest, layer registry, compression policy, junction rules, and cross-AIP composition.
4
+
5
+ > **Status: 0.1.0-alpha.** Generated by `scripts/scaffold-aip.mjs` — `build()` and `validate()` bodies are TODOs.
6
+
7
+ Spec: <https://agentproto.sh/docs/aip-23>
8
+
9
+ ## Usage
10
+
11
+ ```ts
12
+ import { defineIdentity } from "@agentproto/identity"
13
+
14
+ const x = defineIdentity({
15
+ id: "my-identity",
16
+ description: "Short purpose.",
17
+ // ...
18
+ })
19
+ ```
20
+
21
+ ## License
22
+
23
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,35 @@
1
+ import { z } from 'zod';
2
+ import { createDoctype } from '@agentproto/define-doctype';
3
+
4
+ /**
5
+ * @agentproto/identity v0.1.0-alpha
6
+ * AIP-23 IDENTITY.md `defineIdentity` reference implementation.
7
+ */
8
+
9
+ var identityFrontmatterSchema = z.object({ "schema": z.literal("identity.workspace/v1").describe("Discriminator for the AIP-23 workspace doctype."), "name": z.string().regex(new RegExp("^[a-z][a-z0-9-]*[a-z0-9]$")).min(2).max(96).describe("Stable kebab-case identifier for the identity or view."), "title": z.string().min(1).max(200).describe("Human-readable title of the identity."), "description": z.string().min(1).max(2e3).describe("One-paragraph statement of purpose: what this identity captures, who or what it is about."), "version": z.string().regex(new RegExp("^[0-9]+\\.[0-9]+\\.[0-9]+(-[A-Za-z0-9.-]+)?$")).describe("Semantic version of the WORKSPACE shape. Bump on collection / artifact-tier / binding / lint / defaults changes. Independent of any individual layer item's version (AIP-18-side)."), "extends": z.string().regex(new RegExp("^(\\.\\./|\\./)[^\\s]+/IDENTITY\\.md$")).min(1).max(512).describe("OPTIONAL \u2014 relative path to a parent IDENTITY.md. Presence makes the manifest a VIEW; absence makes it a WORKSPACE ROOT. Recursive composition; maximum chain depth is 8.").optional(), "appliesTo": z.array(z.string().regex(new RegExp("^(ws://(operators|companies|personas|skills)/[a-z][a-z0-9-]*|\\.\\./[^\\s]+)$")).describe("Either a ws:// ref to an AIP-9 operator, AIP-22 company, AIP-25 persona, or AIP-3 skill, or a relative path to a consumer workspace folder.")).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("OPTIONAL \u2014 list of consumers this VIEW adapts the identity for. Hosts MUST refuse the view if any binding does not resolve. Not inherited; views declare their own scope.").optional(), "executor": z.string().regex(new RegExp("^ws://operators/[a-z][a-z0-9-]*$")).describe("OPTIONAL \u2014 AIP-9 operator the identity is *about* or activates against. The host loads this operator when the identity is opened.").optional(), "governance": z.string().min(1).max(512).describe("OPTIONAL \u2014 AIP-7 policy or audit binding. May be a path to an AIP-7 policy file or a ws:// ref. Identity-level approvals (layer mutations, confidence elevation, persona binding) flow through this ref.").optional(), "work": z.string().regex(new RegExp("^ws://workspaces/[a-z][a-z0-9-]*$")).describe("OPTIONAL \u2014 AIP-20 work tracker the identity participates in (an operator's task queue, a company's program plan).").optional(), "knowledge": z.string().regex(new RegExp("^ws://wikis/[a-z][a-z0-9-]*(/KNOWLEDGE\\.md)?$")).describe("OPTIONAL \u2014 AIP-10 KNOWLEDGE.md ref. The identity's narrative wiki, dossier, exemplars.").optional(), "collections": z.array(z.any()).describe("Layer collections enabled by this identity. Each entry is one AIP-18 collection describing ONE layer kind. Three forms supported: inline (full COLLECTION.md frontmatter), file ref, or registry import. Merge-by-effective-name (alias if set, otherwise the collection's name) across the extends chain.").default([]), "layers": z.object({ "defaultConfidence": z.number().gte(0).lte(1).describe("OPTIONAL \u2014 minimum confidence (0..1) the workspace will store. New items below the floor are refused with identity_confidence_below_floor (HARD). Default is 0.0 (no floor). Workspaces with strict identity standards SHOULD set this to 0.5 or higher.").default(0), "versioning": z.enum(["enabled", "disabled"]).describe("Whether layer items carry an incrementing version on update. ONE-WAY SWITCH: once 'enabled' at any ancestor, descendants MUST NOT set 'disabled'. Refusal: identity_versioning_disable (HARD).").default("enabled"), "temporal": z.object({ "enabled": z.boolean().describe("OPTIONAL \u2014 whether temporal-entry companion items are supported for layers marked temporal: true on their own collection.").default(false), "field": z.string().regex(new RegExp("^[a-z][a-zA-Z0-9_]*$")).describe("OPTIONAL \u2014 field name on temporal-entry items carrying expiry. Hosts walk this field on read to exclude expired entries.").default("validUntil"), "sourceVocabulary": z.array(z.string().regex(new RegExp("^[a-z][a-z0-9-]*[a-z0-9]$"))).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Controlled vocabulary for temporal-entry.source. APPEND-ONLY across ancestors: descendants MAY add new values but MUST NOT remove existing ones.").default(["configured", "observed", "inferred", "self-reported"]) }).strict().describe("Temporal-layer behaviour at the workspace level.").optional() }).strict().describe("Layer behaviour configuration. Confidence floor, versioning posture, temporal-entry contract.").optional(), "artifacts": z.object({ "enabled": z.boolean().describe("Whether the host generates compression artifacts for layer items.").default(false), "tiers": z.array(z.object({ "id": z.string().regex(new RegExp("^[a-z][a-z0-9-]*$")).describe("Stable kebab-case tier id. Conventional values: short, medium, full. Merge key vs parent."), "maxTokens": z.number().int().gte(1).lte(32768).describe("Target maximum tokens for this tier's artifact. Tiers MUST be MONOTONIC: each tier's maxTokens MUST be strictly greater than the previous tier's. The host re-validates monotonicity after merge."), "strategy": z.string().regex(new RegExp("^[a-z][a-z0-9-]*$")).describe("OPTIONAL \u2014 compression algorithm id. Conventional values: aaak, bullet-list, markdown, or a host-defined string.").optional() }).strict()).describe("Compression tiers. Merge-by-id vs parent; child tier with same id overrides parent's. Monotonicity (strictly increasing maxTokens) is re-validated after merge.").default([]), "locales": z.array(z.string().regex(new RegExp("^[a-z]{2}(-[A-Z]{2})?$"))).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Locales for which artifacts are generated. ISO 639-1 (e.g. 'en') with optional ISO 3166-1 region (e.g. 'en-US'). When non-empty, the host produces one artifact per (layer, tier, locale) triple.").default([]), "refreshPolicy": z.enum(["on-write", "scheduled", "manual"]).describe("When the host regenerates artifacts. on-write = immediately after layer item mutation (correctness); scheduled = host-defined cadence (cheap, eventually consistent); manual = no auto-refresh.").default("on-write") }).strict().describe("Compression artifact policy. AIP-23's first distinctive contribution.").optional(), "binding": z.object({ "allowedEntities": z.array(z.enum(["operator", "company", "persona", "user", "skill"])).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Bearer entity kinds allowed to bind layer items. Workspaces narrow to fit their domain (companion-style: [user, persona]; operator-fleet style: [operator, company]). Cross-references: operator \u2192 AIP-9, company \u2192 AIP-22, persona \u2192 AIP-25, skill \u2192 AIP-3, user \u2192 host-defined.").default(["operator"]), "exclusivity": z.literal("per-entity-and-layer").describe("Binding exclusivity rule. ONE-WAY SWITCH on relaxation: once 'per-entity-and-layer' (or stricter, when added) at any ancestor, descendants MUST NOT replace with a more permissive value. Refusal: identity_binding_loosen (HARD). Currently only 'per-entity-and-layer' is defined; future values may add stricter forms.").default("per-entity-and-layer"), "verifyExistence": z.boolean().describe("Whether the host verifies the bearer entity exists before allowing the binding. ONE-WAY SWITCH on relaxation: once 'true' at any ancestor, descendants MUST NOT set false. Refusal: identity_binding_verify_relax (HARD). Setting false is permitted for ephemeral / sandbox deployments but SHOULD never be used in production.").default(true) }).strict().describe("Junction policy. Which bearer entity kinds may bind layer items as their identity, and how exclusively.").optional(), "lints": z.array(z.object({ "id": z.string().regex(new RegExp("^[a-z][a-z0-9-]*$")).describe("Stable kebab-case lint id. Merge key when composing with extends parent."), "kind": z.enum(["orphan-layer", "low-confidence-pinned", "stale-temporal", "unbound-layer", "missing-required-layer", "custom"]).describe("Workspace-spanning lint algorithm. AIP-18 per-collection lints (missing-owner, overdue, required-field, etc.) live on COLLECTION.md and are NOT redeclared here. 'custom' delegates to a host-defined check identified by `id`."), "severity": z.enum(["error", "warn", "info"]).describe("Lint severity. Children may soften; governance policies MAY forbid softening below `error`."), "params": z.record(z.string(), z.any()).describe("Kind-specific parameters. e.g. { layers: [soul, personality] } for missing-required-layer; { days: 30 } for stale-temporal; { threshold: 0.5 } for low-confidence-pinned.").default({}) }).strict()).describe("Workspace-spanning lints. Merge-by-id vs parent.").default([]), "defaults": z.object({ "approvalClass": z.string().regex(new RegExp("^(auto|always|on-mutate|policy:[A-Za-z0-9_./:-]+)$")).describe("Approval class for layer mutations. 'auto' = no gate; 'always' = every mutation requires approval; 'on-mutate' = approval on field-level mutations; 'policy:<ref>' = delegate to an AIP-7 policy.").optional(), "auditMutations": z.boolean().describe("Whether layer mutations are audited. ONE-WAY SWITCH: once true at any ancestor, descendants MUST NOT set false. Refusal: identity_audit_downgrade (HARD).").default(false) }).strict().describe("Default approval and audit posture.").optional(), "display": z.object({ "homePage": z.string().regex(new RegExp("^[A-Za-z0-9][A-Za-z0-9_:-]*$")).describe("OPTIONAL \u2014 id of the layer or item to use as the identity landing page (e.g. SOUL-acme-founder).").optional(), "defaultGrouping": z.enum(["layer", "entity"]).describe("Default grouping for list views. 'layer' = one section per layer kind; 'entity' = one section per bearer entity.").optional() }).strict().describe("Display hints for UIs that render the identity. Runtime-agnostic.").optional(), "metadata": z.record(z.string(), z.any()).describe("Vendor-specific extensions, namespaced under <vendor>. Deep-merged across the extends chain. MUST NOT change the meaning of any spec field.").default({}) }).strict().and(z.any().describe("A view (any manifest with appliesTo set) MUST extend a parent. A workspace-root manifest has neither field.")).describe("Validates the YAML frontmatter portion of an AIP-23 IDENTITY.md (workspace root or per-context view). The single doctype 'identity.workspace/v1' is used in both modes; the host distinguishes by checking whether `extends` is set. Per-layer-kind schemas are delegated to AIP-18 (COLLECTION.md / ITEM.md). Items in any layer collection MUST carry a `confidence` field in 0..1; that requirement is enforced at item-load time by the host, not by this schema (which validates the workspace manifest only).");
10
+ var defineIdentity = createDoctype({
11
+ aip: 23,
12
+ name: "identity",
13
+ readIdentity: (def) => def.name,
14
+ validate(def) {
15
+ const d = def;
16
+ if (Array.isArray(d.appliesTo) && d.appliesTo.length > 0 && d.extends == null) {
17
+ throw new Error(
18
+ `defineIdentity (AIP-23): appliesTo is non-empty \u2014 extends MUST be set`
19
+ );
20
+ }
21
+ const result = identityFrontmatterSchema.safeParse(def);
22
+ if (!result.success) {
23
+ throw new Error(
24
+ `defineIdentity (AIP-23): ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
25
+ );
26
+ }
27
+ },
28
+ build(def) {
29
+ return { ...def };
30
+ }
31
+ });
32
+
33
+ export { defineIdentity, identityFrontmatterSchema };
34
+ //# sourceMappingURL=chunk-4ZC5U7ML.mjs.map
35
+ //# sourceMappingURL=chunk-4ZC5U7ML.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/define-identity.ts"],"names":[],"mappings":"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","file":"chunk-4ZC5U7ML.mjs","sourcesContent":["/**\n * AIP-23 IDENTITY.md frontmatter zod schema.\n *\n * Generated from `resources/aip-23/draft/IDENTITY.schema.json` via\n * json-schema-to-zod. Imported by both `define-identity.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-identity.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const identityFrontmatterSchema = z.object({ \"schema\": z.literal(\"identity.workspace/v1\").describe(\"Discriminator for the AIP-23 workspace doctype.\"), \"name\": z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*[a-z0-9]$\")).min(2).max(96).describe(\"Stable kebab-case identifier for the identity or view.\"), \"title\": z.string().min(1).max(200).describe(\"Human-readable title of the identity.\"), \"description\": z.string().min(1).max(2000).describe(\"One-paragraph statement of purpose: what this identity captures, who or what it is about.\"), \"version\": z.string().regex(new RegExp(\"^[0-9]+\\\\.[0-9]+\\\\.[0-9]+(-[A-Za-z0-9.-]+)?$\")).describe(\"Semantic version of the WORKSPACE shape. Bump on collection / artifact-tier / binding / lint / defaults changes. Independent of any individual layer item's version (AIP-18-side).\"), \"extends\": z.string().regex(new RegExp(\"^(\\\\.\\\\./|\\\\./)[^\\\\s]+/IDENTITY\\\\.md$\")).min(1).max(512).describe(\"OPTIONAL — relative path to a parent IDENTITY.md. Presence makes the manifest a VIEW; absence makes it a WORKSPACE ROOT. Recursive composition; maximum chain depth is 8.\").optional(), \"appliesTo\": z.array(z.string().regex(new RegExp(\"^(ws://(operators|companies|personas|skills)/[a-z][a-z0-9-]*|\\\\.\\\\./[^\\\\s]+)$\")).describe(\"Either a ws:// ref to an AIP-9 operator, AIP-22 company, AIP-25 persona, or AIP-3 skill, or a relative path to a consumer workspace folder.\")).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"OPTIONAL — list of consumers this VIEW adapts the identity for. Hosts MUST refuse the view if any binding does not resolve. Not inherited; views declare their own scope.\").optional(), \"executor\": z.string().regex(new RegExp(\"^ws://operators/[a-z][a-z0-9-]*$\")).describe(\"OPTIONAL — AIP-9 operator the identity is *about* or activates against. The host loads this operator when the identity is opened.\").optional(), \"governance\": z.string().min(1).max(512).describe(\"OPTIONAL — AIP-7 policy or audit binding. May be a path to an AIP-7 policy file or a ws:// ref. Identity-level approvals (layer mutations, confidence elevation, persona binding) flow through this ref.\").optional(), \"work\": z.string().regex(new RegExp(\"^ws://workspaces/[a-z][a-z0-9-]*$\")).describe(\"OPTIONAL — AIP-20 work tracker the identity participates in (an operator's task queue, a company's program plan).\").optional(), \"knowledge\": z.string().regex(new RegExp(\"^ws://wikis/[a-z][a-z0-9-]*(/KNOWLEDGE\\\\.md)?$\")).describe(\"OPTIONAL — AIP-10 KNOWLEDGE.md ref. The identity's narrative wiki, dossier, exemplars.\").optional(), \"collections\": z.array(z.any()).describe(\"Layer collections enabled by this identity. Each entry is one AIP-18 collection describing ONE layer kind. Three forms supported: inline (full COLLECTION.md frontmatter), file ref, or registry import. Merge-by-effective-name (alias if set, otherwise the collection's name) across the extends chain.\").default([] as never), \"layers\": z.object({ \"defaultConfidence\": z.number().gte(0).lte(1).describe(\"OPTIONAL — minimum confidence (0..1) the workspace will store. New items below the floor are refused with identity_confidence_below_floor (HARD). Default is 0.0 (no floor). Workspaces with strict identity standards SHOULD set this to 0.5 or higher.\").default(0), \"versioning\": z.enum([\"enabled\",\"disabled\"]).describe(\"Whether layer items carry an incrementing version on update. ONE-WAY SWITCH: once 'enabled' at any ancestor, descendants MUST NOT set 'disabled'. Refusal: identity_versioning_disable (HARD).\").default(\"enabled\"), \"temporal\": z.object({ \"enabled\": z.boolean().describe(\"OPTIONAL — whether temporal-entry companion items are supported for layers marked temporal: true on their own collection.\").default(false), \"field\": z.string().regex(new RegExp(\"^[a-z][a-zA-Z0-9_]*$\")).describe(\"OPTIONAL — field name on temporal-entry items carrying expiry. Hosts walk this field on read to exclude expired entries.\").default(\"validUntil\"), \"sourceVocabulary\": z.array(z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*[a-z0-9]$\"))).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Controlled vocabulary for temporal-entry.source. APPEND-ONLY across ancestors: descendants MAY add new values but MUST NOT remove existing ones.\").default([\"configured\",\"observed\",\"inferred\",\"self-reported\"]) }).strict().describe(\"Temporal-layer behaviour at the workspace level.\").optional() }).strict().describe(\"Layer behaviour configuration. Confidence floor, versioning posture, temporal-entry contract.\").optional(), \"artifacts\": z.object({ \"enabled\": z.boolean().describe(\"Whether the host generates compression artifacts for layer items.\").default(false), \"tiers\": z.array(z.object({ \"id\": z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*$\")).describe(\"Stable kebab-case tier id. Conventional values: short, medium, full. Merge key vs parent.\"), \"maxTokens\": z.number().int().gte(1).lte(32768).describe(\"Target maximum tokens for this tier's artifact. Tiers MUST be MONOTONIC: each tier's maxTokens MUST be strictly greater than the previous tier's. The host re-validates monotonicity after merge.\"), \"strategy\": z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*$\")).describe(\"OPTIONAL — compression algorithm id. Conventional values: aaak, bullet-list, markdown, or a host-defined string.\").optional() }).strict()).describe(\"Compression tiers. Merge-by-id vs parent; child tier with same id overrides parent's. Monotonicity (strictly increasing maxTokens) is re-validated after merge.\").default([] as never), \"locales\": z.array(z.string().regex(new RegExp(\"^[a-z]{2}(-[A-Z]{2})?$\"))).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Locales for which artifacts are generated. ISO 639-1 (e.g. 'en') with optional ISO 3166-1 region (e.g. 'en-US'). When non-empty, the host produces one artifact per (layer, tier, locale) triple.\").default([] as never), \"refreshPolicy\": z.enum([\"on-write\",\"scheduled\",\"manual\"]).describe(\"When the host regenerates artifacts. on-write = immediately after layer item mutation (correctness); scheduled = host-defined cadence (cheap, eventually consistent); manual = no auto-refresh.\").default(\"on-write\") }).strict().describe(\"Compression artifact policy. AIP-23's first distinctive contribution.\").optional(), \"binding\": z.object({ \"allowedEntities\": z.array(z.enum([\"operator\",\"company\",\"persona\",\"user\",\"skill\"])).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Bearer entity kinds allowed to bind layer items. Workspaces narrow to fit their domain (companion-style: [user, persona]; operator-fleet style: [operator, company]). Cross-references: operator → AIP-9, company → AIP-22, persona → AIP-25, skill → AIP-3, user → host-defined.\").default([\"operator\"]), \"exclusivity\": z.literal(\"per-entity-and-layer\").describe(\"Binding exclusivity rule. ONE-WAY SWITCH on relaxation: once 'per-entity-and-layer' (or stricter, when added) at any ancestor, descendants MUST NOT replace with a more permissive value. Refusal: identity_binding_loosen (HARD). Currently only 'per-entity-and-layer' is defined; future values may add stricter forms.\").default(\"per-entity-and-layer\"), \"verifyExistence\": z.boolean().describe(\"Whether the host verifies the bearer entity exists before allowing the binding. ONE-WAY SWITCH on relaxation: once 'true' at any ancestor, descendants MUST NOT set false. Refusal: identity_binding_verify_relax (HARD). Setting false is permitted for ephemeral / sandbox deployments but SHOULD never be used in production.\").default(true) }).strict().describe(\"Junction policy. Which bearer entity kinds may bind layer items as their identity, and how exclusively.\").optional(), \"lints\": z.array(z.object({ \"id\": z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*$\")).describe(\"Stable kebab-case lint id. Merge key when composing with extends parent.\"), \"kind\": z.enum([\"orphan-layer\",\"low-confidence-pinned\",\"stale-temporal\",\"unbound-layer\",\"missing-required-layer\",\"custom\"]).describe(\"Workspace-spanning lint algorithm. AIP-18 per-collection lints (missing-owner, overdue, required-field, etc.) live on COLLECTION.md and are NOT redeclared here. 'custom' delegates to a host-defined check identified by `id`.\"), \"severity\": z.enum([\"error\",\"warn\",\"info\"]).describe(\"Lint severity. Children may soften; governance policies MAY forbid softening below `error`.\"), \"params\": z.record(z.string(), z.any()).describe(\"Kind-specific parameters. e.g. { layers: [soul, personality] } for missing-required-layer; { days: 30 } for stale-temporal; { threshold: 0.5 } for low-confidence-pinned.\").default({} as never) }).strict()).describe(\"Workspace-spanning lints. Merge-by-id vs parent.\").default([] as never), \"defaults\": z.object({ \"approvalClass\": z.string().regex(new RegExp(\"^(auto|always|on-mutate|policy:[A-Za-z0-9_./:-]+)$\")).describe(\"Approval class for layer mutations. 'auto' = no gate; 'always' = every mutation requires approval; 'on-mutate' = approval on field-level mutations; 'policy:<ref>' = delegate to an AIP-7 policy.\").optional(), \"auditMutations\": z.boolean().describe(\"Whether layer mutations are audited. ONE-WAY SWITCH: once true at any ancestor, descendants MUST NOT set false. Refusal: identity_audit_downgrade (HARD).\").default(false) }).strict().describe(\"Default approval and audit posture.\").optional(), \"display\": z.object({ \"homePage\": z.string().regex(new RegExp(\"^[A-Za-z0-9][A-Za-z0-9_:-]*$\")).describe(\"OPTIONAL — id of the layer or item to use as the identity landing page (e.g. SOUL-acme-founder).\").optional(), \"defaultGrouping\": z.enum([\"layer\",\"entity\"]).describe(\"Default grouping for list views. 'layer' = one section per layer kind; 'entity' = one section per bearer entity.\").optional() }).strict().describe(\"Display hints for UIs that render the identity. Runtime-agnostic.\").optional(), \"metadata\": z.record(z.string(), z.any()).describe(\"Vendor-specific extensions, namespaced under <vendor>. Deep-merged across the extends chain. MUST NOT change the meaning of any spec field.\").default({} as never) }).strict().and(z.any().describe(\"A view (any manifest with appliesTo set) MUST extend a parent. A workspace-root manifest has neither field.\")).describe(\"Validates the YAML frontmatter portion of an AIP-23 IDENTITY.md (workspace root or per-context view). The single doctype 'identity.workspace/v1' is used in both modes; the host distinguishes by checking whether `extends` is set. Per-layer-kind schemas are delegated to AIP-18 (COLLECTION.md / ITEM.md). Items in any layer collection MUST carry a `confidence` field in 0..1; that requirement is enforced at item-load time by the host, not by this schema (which validates the workspace manifest only).\")\n\nexport type IdentityFrontmatter = z.infer<typeof identityFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { identityFrontmatterSchema } from \"./schema.js\"\nimport type { IdentityDefinition, IdentityHandle } from \"./types.js\"\n\n/**\n * AIP-23 reference implementation of `defineIdentity`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"defineIdentity (AIP-23): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the input. Same source of truth as the .md\n * path uses (`parseIdentityManifest`), so a malformed TS-authored\n * definition fails with the same diagnostic as a malformed manifest.\n * Cross-field rules go in `validate(def)` after the zod check.\n *\n * Identity / description extractors detected from the JSON Schema:\n * readIdentity: def.name\n * readDescription: def.description.\n */\nexport const defineIdentity = createDoctype<IdentityDefinition, IdentityHandle>({\n aip: 23,\n name: \"identity\",\n readIdentity: (def) => def.name,\n validate(def) {\n // Cross-field rules run BEFORE field-level zod so structural\n // errors surface before the cascade of \"missing required field\".\n //\n // AIP-23 rule: appliesTo non-empty ⇒ extends required.\n const d = def as { appliesTo?: readonly unknown[]; extends?: unknown }\n if (\n Array.isArray(d.appliesTo) &&\n d.appliesTo.length > 0 &&\n d.extends == null\n ) {\n throw new Error(\n `defineIdentity (AIP-23): appliesTo is non-empty — extends MUST be set`,\n )\n }\n const result = identityFrontmatterSchema.safeParse(def)\n if (!result.success) {\n throw new Error(\n `defineIdentity (AIP-23): ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n },\n build(def) {\n // Default build: spread the validated definition into a fresh object.\n // Hand-tune for nested freezing (Object.freeze on arrays/objects) and\n // for fields that need defaults applied — see @agentproto/operator\n // for a reference shape.\n return { ...def } as IdentityHandle\n },\n})\n"]}
@@ -0,0 +1,37 @@
1
+ import { I as IdentityDefinition } from './types-CoPDmRyr.js';
2
+ export { a as IdentityHandle } from './types-CoPDmRyr.js';
3
+
4
+ /**
5
+ * AIP-23 reference implementation of `defineIdentity`.
6
+ *
7
+ * Built on `createDoctype` so the cross-AIP invariants (id pattern,
8
+ * description length, top-level freeze, "defineIdentity (AIP-23): …"
9
+ * error prefix) run uniformly with every other AIP defineX.
10
+ *
11
+ * Field-level validation runs the schema-derived zod from
12
+ * `./schema.ts` against the input. Same source of truth as the .md
13
+ * path uses (`parseIdentityManifest`), so a malformed TS-authored
14
+ * definition fails with the same diagnostic as a malformed manifest.
15
+ * Cross-field rules go in `validate(def)` after the zod check.
16
+ *
17
+ * Identity / description extractors detected from the JSON Schema:
18
+ * readIdentity: def.name
19
+ * readDescription: def.description.
20
+ */
21
+ declare const defineIdentity: (def: IdentityDefinition) => Readonly<IdentityDefinition>;
22
+
23
+ /**
24
+ * @agentproto/identity — AIP-23 IDENTITY.md `defineIdentity` reference impl.
25
+ *
26
+ * A workspace AIP that defines layered, composable agent identity — typed layers as AIP-18 collections, confidence-scored items, optional temporal entries, and compression-artifact tiers — owning only the workspace root manifest, layer registry, compression policy, junction rules, and cross-AIP composition.
27
+ *
28
+ * Spec: https://agentproto.sh/docs/aip-23
29
+ *
30
+ * Authoring paths:
31
+ * - TS: `defineIdentity({...})` → `IdentityHandle`
32
+ * - MD: `parseIdentityManifest(src) → identityFromManifest({...})` → `IdentityHandle`
33
+ */
34
+ declare const SPEC_NAME: "agentidentity/v1";
35
+ declare const SPEC_VERSION: "1.0.0-alpha";
36
+
37
+ export { IdentityDefinition, SPEC_NAME, SPEC_VERSION, defineIdentity };
package/dist/index.mjs ADDED
@@ -0,0 +1,14 @@
1
+ export { defineIdentity } from './chunk-4ZC5U7ML.mjs';
2
+
3
+ /**
4
+ * @agentproto/identity v0.1.0-alpha
5
+ * AIP-23 IDENTITY.md `defineIdentity` reference implementation.
6
+ */
7
+
8
+ // src/index.ts
9
+ var SPEC_NAME = "agentidentity/v1";
10
+ var SPEC_VERSION = "1.0.0-alpha";
11
+
12
+ export { SPEC_NAME, SPEC_VERSION };
13
+ //# sourceMappingURL=index.mjs.map
14
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAYO,IAAM,SAAA,GAAY;AAClB,IAAM,YAAA,GAAe","file":"index.mjs","sourcesContent":["/**\n * @agentproto/identity — AIP-23 IDENTITY.md `defineIdentity` reference impl.\n *\n * A workspace AIP that defines layered, composable agent identity — typed layers as AIP-18 collections, confidence-scored items, optional temporal entries, and compression-artifact tiers — owning only the workspace root manifest, layer registry, compression policy, junction rules, and cross-AIP composition.\n *\n * Spec: https://agentproto.sh/docs/aip-23\n *\n * Authoring paths:\n * - TS: `defineIdentity({...})` → `IdentityHandle`\n * - MD: `parseIdentityManifest(src) → identityFromManifest({...})` → `IdentityHandle`\n */\n\nexport const SPEC_NAME = \"agentidentity/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport { defineIdentity } from \"./define-identity.js\"\nexport type { IdentityDefinition, IdentityHandle } from \"./types.js\"\n"]}
@@ -0,0 +1,122 @@
1
+ import { z } from 'zod';
2
+ import { a as IdentityHandle } from '../types-CoPDmRyr.js';
3
+
4
+ /**
5
+ * AIP-23 IDENTITY.md frontmatter zod schema.
6
+ *
7
+ * Generated from `resources/aip-23/draft/IDENTITY.schema.json` via
8
+ * json-schema-to-zod. Imported by both `define-identity.ts` (TS path
9
+ * validation) and `manifest/index.ts` (.md path validation) so every
10
+ * field-level constraint runs in both authoring paths from a single
11
+ * source of truth — re-run scaffold-aip to refresh after spec changes.
12
+ *
13
+ * Cross-field rules (if/then/allOf in JSON Schema) don't translate
14
+ * cleanly and live in `define-identity.ts`'s `validate(def)` instead.
15
+ */
16
+
17
+ declare const identityFrontmatterSchema: z.ZodIntersection<z.ZodObject<{
18
+ schema: z.ZodLiteral<"identity.workspace/v1">;
19
+ name: z.ZodString;
20
+ title: z.ZodString;
21
+ description: z.ZodString;
22
+ version: z.ZodString;
23
+ extends: z.ZodOptional<z.ZodString>;
24
+ appliesTo: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ executor: z.ZodOptional<z.ZodString>;
26
+ governance: z.ZodOptional<z.ZodString>;
27
+ work: z.ZodOptional<z.ZodString>;
28
+ knowledge: z.ZodOptional<z.ZodString>;
29
+ collections: z.ZodDefault<z.ZodArray<z.ZodAny>>;
30
+ layers: z.ZodOptional<z.ZodObject<{
31
+ defaultConfidence: z.ZodDefault<z.ZodNumber>;
32
+ versioning: z.ZodDefault<z.ZodEnum<{
33
+ enabled: "enabled";
34
+ disabled: "disabled";
35
+ }>>;
36
+ temporal: z.ZodOptional<z.ZodObject<{
37
+ enabled: z.ZodDefault<z.ZodBoolean>;
38
+ field: z.ZodDefault<z.ZodString>;
39
+ sourceVocabulary: z.ZodDefault<z.ZodArray<z.ZodString>>;
40
+ }, z.core.$strict>>;
41
+ }, z.core.$strict>>;
42
+ artifacts: z.ZodOptional<z.ZodObject<{
43
+ enabled: z.ZodDefault<z.ZodBoolean>;
44
+ tiers: z.ZodDefault<z.ZodArray<z.ZodObject<{
45
+ id: z.ZodString;
46
+ maxTokens: z.ZodNumber;
47
+ strategy: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strict>>>;
49
+ locales: z.ZodDefault<z.ZodArray<z.ZodString>>;
50
+ refreshPolicy: z.ZodDefault<z.ZodEnum<{
51
+ "on-write": "on-write";
52
+ scheduled: "scheduled";
53
+ manual: "manual";
54
+ }>>;
55
+ }, z.core.$strict>>;
56
+ binding: z.ZodOptional<z.ZodObject<{
57
+ allowedEntities: z.ZodDefault<z.ZodArray<z.ZodEnum<{
58
+ operator: "operator";
59
+ company: "company";
60
+ persona: "persona";
61
+ user: "user";
62
+ skill: "skill";
63
+ }>>>;
64
+ exclusivity: z.ZodDefault<z.ZodLiteral<"per-entity-and-layer">>;
65
+ verifyExistence: z.ZodDefault<z.ZodBoolean>;
66
+ }, z.core.$strict>>;
67
+ lints: z.ZodDefault<z.ZodArray<z.ZodObject<{
68
+ id: z.ZodString;
69
+ kind: z.ZodEnum<{
70
+ custom: "custom";
71
+ "orphan-layer": "orphan-layer";
72
+ "low-confidence-pinned": "low-confidence-pinned";
73
+ "stale-temporal": "stale-temporal";
74
+ "unbound-layer": "unbound-layer";
75
+ "missing-required-layer": "missing-required-layer";
76
+ }>;
77
+ severity: z.ZodEnum<{
78
+ error: "error";
79
+ warn: "warn";
80
+ info: "info";
81
+ }>;
82
+ params: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
83
+ }, z.core.$strict>>>;
84
+ defaults: z.ZodOptional<z.ZodObject<{
85
+ approvalClass: z.ZodOptional<z.ZodString>;
86
+ auditMutations: z.ZodDefault<z.ZodBoolean>;
87
+ }, z.core.$strict>>;
88
+ display: z.ZodOptional<z.ZodObject<{
89
+ homePage: z.ZodOptional<z.ZodString>;
90
+ defaultGrouping: z.ZodOptional<z.ZodEnum<{
91
+ layer: "layer";
92
+ entity: "entity";
93
+ }>>;
94
+ }, z.core.$strict>>;
95
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
96
+ }, z.core.$strict>, z.ZodAny>;
97
+ type IdentityFrontmatter = z.infer<typeof identityFrontmatterSchema>;
98
+
99
+ /**
100
+ * AIP-23 IDENTITY.md sidecar parser + manifest-to-handle constructor.
101
+ *
102
+ * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:
103
+ * the .md provides metadata; the TS module supplies any spec-specific
104
+ * runtime bits (schemas, execute bodies, …) that can't live in
105
+ * frontmatter. Both inputs end up in `defineIdentity` so the cross-AIP
106
+ * invariants run uniformly.
107
+ *
108
+ *
109
+ * The frontmatter zod schema below was generated from
110
+ * `resources/aip-23/draft/IDENTITY.schema.json` via json-schema-to-zod.
111
+ * Re-run scaffold-aip to refresh after spec changes (or hand-tune
112
+ * any constraint the converter doesn't capture cleanly).
113
+ */
114
+
115
+ interface IdentityManifest {
116
+ frontmatter: IdentityFrontmatter;
117
+ body: string;
118
+ }
119
+ declare function parseIdentityManifest(source: string): IdentityManifest;
120
+ declare function identityFromManifest(manifest: IdentityManifest): IdentityHandle;
121
+
122
+ export { type IdentityFrontmatter, type IdentityManifest, identityFromManifest, identityFrontmatterSchema, parseIdentityManifest };
@@ -0,0 +1,28 @@
1
+ import { identityFrontmatterSchema, defineIdentity } from '../chunk-4ZC5U7ML.mjs';
2
+ export { identityFrontmatterSchema } from '../chunk-4ZC5U7ML.mjs';
3
+ import matter from 'gray-matter';
4
+
5
+ /**
6
+ * @agentproto/identity v0.1.0-alpha
7
+ * AIP-23 IDENTITY.md `defineIdentity` reference implementation.
8
+ */
9
+ function parseIdentityManifest(source) {
10
+ const parsed = matter(source);
11
+ if (Object.keys(parsed.data).length === 0) {
12
+ throw new Error("parseIdentityManifest: missing or empty frontmatter");
13
+ }
14
+ const result = identityFrontmatterSchema.safeParse(parsed.data);
15
+ if (!result.success) {
16
+ throw new Error(
17
+ `parseIdentityManifest: invalid frontmatter \u2014 ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
18
+ );
19
+ }
20
+ return { frontmatter: result.data, body: parsed.content };
21
+ }
22
+ function identityFromManifest(manifest) {
23
+ return defineIdentity(manifest.frontmatter);
24
+ }
25
+
26
+ export { identityFromManifest, parseIdentityManifest };
27
+ //# sourceMappingURL=index.mjs.map
28
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":";;;;;;;;AA8BO,SAAS,sBAAsB,MAAA,EAAkC;AACtE,EAAA,MAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC5B,EAAA,IAAI,OAAO,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AACA,EAAA,MAAM,MAAA,GAAS,yBAAA,CAA0B,SAAA,CAAU,MAAA,CAAO,IAAI,CAAA;AAC9D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kDAAA,EAAgD,OAAO,KAAA,CAAM,MAAA,CAC1D,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KACf;AAAA,EACF;AACA,EAAA,OAAO,EAAE,WAAA,EAAa,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,OAAO,OAAA,EAAQ;AAC1D;AAEO,SAAS,qBAAqB,QAAA,EAA4C;AAK/E,EAAA,OAAO,cAAA,CAAe,SAAS,WAA4C,CAAA;AAC7E","file":"index.mjs","sourcesContent":["/**\n * AIP-23 IDENTITY.md sidecar parser + manifest-to-handle constructor.\n *\n * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:\n * the .md provides metadata; the TS module supplies any spec-specific\n * runtime bits (schemas, execute bodies, …) that can't live in\n * frontmatter. Both inputs end up in `defineIdentity` so the cross-AIP\n * invariants run uniformly.\n *\n *\n * The frontmatter zod schema below was generated from\n * `resources/aip-23/draft/IDENTITY.schema.json` via json-schema-to-zod.\n * Re-run scaffold-aip to refresh after spec changes (or hand-tune\n * any constraint the converter doesn't capture cleanly).\n */\n\nimport matter from \"gray-matter\"\nimport { identityFrontmatterSchema, type IdentityFrontmatter } from \"../schema.js\"\nimport { defineIdentity } from \"../define-identity.js\"\nimport type { IdentityDefinition, IdentityHandle } from \"../types.js\"\n\n// Re-export so consumers can import the schema + inferred type either\n// from \"@@agentproto/identity/manifest\" or directly from \"@@agentproto/identity/schema\".\nexport { identityFrontmatterSchema, type IdentityFrontmatter }\n\nexport interface IdentityManifest {\n frontmatter: IdentityFrontmatter\n body: string\n}\n\nexport function parseIdentityManifest(source: string): IdentityManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parseIdentityManifest: missing or empty frontmatter\")\n }\n const result = identityFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parseIdentityManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\nexport function identityFromManifest(manifest: IdentityManifest): IdentityHandle {\n // The zod-validated frontmatter is structurally compatible with\n // IdentityDefinition; the cast pins the typing once the manifest\n // schema and the TS interface diverge (e.g. handle has frozen fields\n // a literal config doesn't carry yet).\n return defineIdentity(manifest.frontmatter as unknown as IdentityDefinition)\n}\n"]}
@@ -0,0 +1,473 @@
1
+ /**
2
+ * AIP-23 IdentityDefinition + IdentityHandle.
3
+ *
4
+ * `IdentityDefinition` was generated from
5
+ * `resources/aip-23/draft/IDENTITY.schema.json` via json-schema-to-typescript.
6
+ * `IdentityHandle` is the readonly view of the same shape; tighten it
7
+ * by hand for fields that get defaults applied in build().
8
+ */
9
+ /**
10
+ * Validates the YAML frontmatter portion of an AIP-23 IDENTITY.md (workspace root or per-context view). The single doctype 'identity.workspace/v1' is used in both modes; the host distinguishes by checking whether `extends` is set. Per-layer-kind schemas are delegated to AIP-18 (COLLECTION.md / ITEM.md). Items in any layer collection MUST carry a `confidence` field in 0..1; that requirement is enforced at item-load time by the host, not by this schema (which validates the workspace manifest only).
11
+ */
12
+ type IdentityDefinition = {
13
+ [k: string]: unknown;
14
+ } & {
15
+ /**
16
+ * Discriminator for the AIP-23 workspace doctype.
17
+ */
18
+ schema: "identity.workspace/v1";
19
+ /**
20
+ * Stable kebab-case identifier for the identity or view.
21
+ */
22
+ name: string;
23
+ /**
24
+ * Human-readable title of the identity.
25
+ */
26
+ title: string;
27
+ /**
28
+ * One-paragraph statement of purpose: what this identity captures, who or what it is about.
29
+ */
30
+ description: string;
31
+ /**
32
+ * Semantic version of the WORKSPACE shape. Bump on collection / artifact-tier / binding / lint / defaults changes. Independent of any individual layer item's version (AIP-18-side).
33
+ */
34
+ version: string;
35
+ /**
36
+ * OPTIONAL — relative path to a parent IDENTITY.md. Presence makes the manifest a VIEW; absence makes it a WORKSPACE ROOT. Recursive composition; maximum chain depth is 8.
37
+ */
38
+ extends?: string;
39
+ /**
40
+ * OPTIONAL — list of consumers this VIEW adapts the identity for. Hosts MUST refuse the view if any binding does not resolve. Not inherited; views declare their own scope.
41
+ */
42
+ appliesTo?: string[];
43
+ /**
44
+ * OPTIONAL — AIP-9 operator the identity is *about* or activates against. The host loads this operator when the identity is opened.
45
+ */
46
+ executor?: string;
47
+ /**
48
+ * OPTIONAL — AIP-7 policy or audit binding. May be a path to an AIP-7 policy file or a ws:// ref. Identity-level approvals (layer mutations, confidence elevation, persona binding) flow through this ref.
49
+ */
50
+ governance?: string;
51
+ /**
52
+ * OPTIONAL — AIP-20 work tracker the identity participates in (an operator's task queue, a company's program plan).
53
+ */
54
+ work?: string;
55
+ /**
56
+ * OPTIONAL — AIP-10 KNOWLEDGE.md ref. The identity's narrative wiki, dossier, exemplars.
57
+ */
58
+ knowledge?: string;
59
+ /**
60
+ * Layer collections enabled by this identity. Each entry is one AIP-18 collection describing ONE layer kind. Three forms supported: inline (full COLLECTION.md frontmatter), file ref, or registry import. Merge-by-effective-name (alias if set, otherwise the collection's name) across the extends chain.
61
+ */
62
+ collections?: CollectionEntry[];
63
+ /**
64
+ * Layer behaviour configuration. Confidence floor, versioning posture, temporal-entry contract.
65
+ */
66
+ layers?: {
67
+ /**
68
+ * OPTIONAL — minimum confidence (0..1) the workspace will store. New items below the floor are refused with identity_confidence_below_floor (HARD). Default is 0.0 (no floor). Workspaces with strict identity standards SHOULD set this to 0.5 or higher.
69
+ */
70
+ defaultConfidence?: number;
71
+ /**
72
+ * Whether layer items carry an incrementing version on update. ONE-WAY SWITCH: once 'enabled' at any ancestor, descendants MUST NOT set 'disabled'. Refusal: identity_versioning_disable (HARD).
73
+ */
74
+ versioning?: "enabled" | "disabled";
75
+ /**
76
+ * Temporal-layer behaviour at the workspace level.
77
+ */
78
+ temporal?: {
79
+ /**
80
+ * OPTIONAL — whether temporal-entry companion items are supported for layers marked temporal: true on their own collection.
81
+ */
82
+ enabled?: boolean;
83
+ /**
84
+ * OPTIONAL — field name on temporal-entry items carrying expiry. Hosts walk this field on read to exclude expired entries.
85
+ */
86
+ field?: string;
87
+ /**
88
+ * Controlled vocabulary for temporal-entry.source. APPEND-ONLY across ancestors: descendants MAY add new values but MUST NOT remove existing ones.
89
+ */
90
+ sourceVocabulary?: string[];
91
+ };
92
+ };
93
+ /**
94
+ * Compression artifact policy. AIP-23's first distinctive contribution.
95
+ */
96
+ artifacts?: {
97
+ /**
98
+ * Whether the host generates compression artifacts for layer items.
99
+ */
100
+ enabled?: boolean;
101
+ /**
102
+ * Compression tiers. Merge-by-id vs parent; child tier with same id overrides parent's. Monotonicity (strictly increasing maxTokens) is re-validated after merge.
103
+ */
104
+ tiers?: {
105
+ /**
106
+ * Stable kebab-case tier id. Conventional values: short, medium, full. Merge key vs parent.
107
+ */
108
+ id: string;
109
+ /**
110
+ * Target maximum tokens for this tier's artifact. Tiers MUST be MONOTONIC: each tier's maxTokens MUST be strictly greater than the previous tier's. The host re-validates monotonicity after merge.
111
+ */
112
+ maxTokens: number;
113
+ /**
114
+ * OPTIONAL — compression algorithm id. Conventional values: aaak, bullet-list, markdown, or a host-defined string.
115
+ */
116
+ strategy?: string;
117
+ }[];
118
+ /**
119
+ * Locales for which artifacts are generated. ISO 639-1 (e.g. 'en') with optional ISO 3166-1 region (e.g. 'en-US'). When non-empty, the host produces one artifact per (layer, tier, locale) triple.
120
+ */
121
+ locales?: string[];
122
+ /**
123
+ * When the host regenerates artifacts. on-write = immediately after layer item mutation (correctness); scheduled = host-defined cadence (cheap, eventually consistent); manual = no auto-refresh.
124
+ */
125
+ refreshPolicy?: "on-write" | "scheduled" | "manual";
126
+ };
127
+ /**
128
+ * Junction policy. Which bearer entity kinds may bind layer items as their identity, and how exclusively.
129
+ */
130
+ binding?: {
131
+ /**
132
+ * Bearer entity kinds allowed to bind layer items. Workspaces narrow to fit their domain (companion-style: [user, persona]; operator-fleet style: [operator, company]). Cross-references: operator → AIP-9, company → AIP-22, persona → AIP-25, skill → AIP-3, user → host-defined.
133
+ */
134
+ allowedEntities?: ("operator" | "company" | "persona" | "user" | "skill")[];
135
+ /**
136
+ * Binding exclusivity rule. ONE-WAY SWITCH on relaxation: once 'per-entity-and-layer' (or stricter, when added) at any ancestor, descendants MUST NOT replace with a more permissive value. Refusal: identity_binding_loosen (HARD). Currently only 'per-entity-and-layer' is defined; future values may add stricter forms.
137
+ */
138
+ exclusivity?: "per-entity-and-layer";
139
+ /**
140
+ * Whether the host verifies the bearer entity exists before allowing the binding. ONE-WAY SWITCH on relaxation: once 'true' at any ancestor, descendants MUST NOT set false. Refusal: identity_binding_verify_relax (HARD). Setting false is permitted for ephemeral / sandbox deployments but SHOULD never be used in production.
141
+ */
142
+ verifyExistence?: boolean;
143
+ };
144
+ /**
145
+ * Workspace-spanning lints. Merge-by-id vs parent.
146
+ */
147
+ lints?: {
148
+ /**
149
+ * Stable kebab-case lint id. Merge key when composing with extends parent.
150
+ */
151
+ id: string;
152
+ /**
153
+ * Workspace-spanning lint algorithm. AIP-18 per-collection lints (missing-owner, overdue, required-field, etc.) live on COLLECTION.md and are NOT redeclared here. 'custom' delegates to a host-defined check identified by `id`.
154
+ */
155
+ kind: "orphan-layer" | "low-confidence-pinned" | "stale-temporal" | "unbound-layer" | "missing-required-layer" | "custom";
156
+ /**
157
+ * Lint severity. Children may soften; governance policies MAY forbid softening below `error`.
158
+ */
159
+ severity: "error" | "warn" | "info";
160
+ /**
161
+ * Kind-specific parameters. e.g. { layers: [soul, personality] } for missing-required-layer; { days: 30 } for stale-temporal; { threshold: 0.5 } for low-confidence-pinned.
162
+ */
163
+ params?: {
164
+ [k: string]: unknown;
165
+ };
166
+ }[];
167
+ /**
168
+ * Default approval and audit posture.
169
+ */
170
+ defaults?: {
171
+ /**
172
+ * Approval class for layer mutations. 'auto' = no gate; 'always' = every mutation requires approval; 'on-mutate' = approval on field-level mutations; 'policy:<ref>' = delegate to an AIP-7 policy.
173
+ */
174
+ approvalClass?: string;
175
+ /**
176
+ * Whether layer mutations are audited. ONE-WAY SWITCH: once true at any ancestor, descendants MUST NOT set false. Refusal: identity_audit_downgrade (HARD).
177
+ */
178
+ auditMutations?: boolean;
179
+ };
180
+ /**
181
+ * Display hints for UIs that render the identity. Runtime-agnostic.
182
+ */
183
+ display?: {
184
+ /**
185
+ * OPTIONAL — id of the layer or item to use as the identity landing page (e.g. SOUL-acme-founder).
186
+ */
187
+ homePage?: string;
188
+ /**
189
+ * Default grouping for list views. 'layer' = one section per layer kind; 'entity' = one section per bearer entity.
190
+ */
191
+ defaultGrouping?: "layer" | "entity";
192
+ };
193
+ /**
194
+ * Vendor-specific extensions, namespaced under <vendor>. Deep-merged across the extends chain. MUST NOT change the meaning of any spec field.
195
+ */
196
+ metadata?: {
197
+ [k: string]: unknown;
198
+ };
199
+ };
200
+ /**
201
+ * One layer-collection declaration. Either an inline AIP-18 collection schema, or a ref (path or ws:// URI) optionally aliased and version-pinned.
202
+ */
203
+ type CollectionEntry = CollectionInline | CollectionRef;
204
+ /**
205
+ * Full AIP-18 collection.schema/v1 frontmatter, parsed in-place. The host registers the layer collection directly via AIP-18's defineCollection without loading a separate file.
206
+ */
207
+ type Schema = {
208
+ [k: string]: unknown;
209
+ } & {
210
+ /**
211
+ * Discriminator for a collection definition.
212
+ */
213
+ schema: "collection.schema/v1";
214
+ /**
215
+ * Stable kebab-case identifier. Items reference this name via their `collection:` field.
216
+ */
217
+ name: string;
218
+ /**
219
+ * Human-readable collection title.
220
+ */
221
+ title: string;
222
+ /**
223
+ * One-paragraph statement of purpose: what this collection captures and when an item belongs here vs another collection.
224
+ */
225
+ description: string;
226
+ /**
227
+ * Semantic version of the SHAPE. Bump on field/status/lint changes. Independent of the collection's content.
228
+ */
229
+ version: string;
230
+ /**
231
+ * OPTIONAL — relative path to a parent COLLECTION.md. Recursive composition; maximum chain depth is 8.
232
+ */
233
+ extends?: string;
234
+ /**
235
+ * OPTIONAL — list of consumers this collection adapts for. Hosts MUST refuse if any binding does not resolve. Not inherited; each child declares its own scope.
236
+ */
237
+ appliesTo?: string[];
238
+ /**
239
+ * Item field schema. Merge-by-name vs parent: a child entry with the same `name` replaces the parent's (subject to type-drift refusal); new names are appended.
240
+ */
241
+ fields?: FieldDef[];
242
+ /**
243
+ * Status state machine. Merge-by-id vs parent. Children may add statuses, mark inherited statuses terminal, or narrow `transitionsTo`; they MUST NOT remove an inherited status.
244
+ */
245
+ statuses?: {
246
+ /**
247
+ * Stable kebab-case status id. Merge key when composing.
248
+ */
249
+ id: string;
250
+ /**
251
+ * Human-readable status label.
252
+ */
253
+ label: string;
254
+ /**
255
+ * Whether items in this status are considered closed. Lints like `overdue` typically skip terminal statuses.
256
+ */
257
+ terminal?: boolean;
258
+ /**
259
+ * OPTIONAL — allowed next status ids. If omitted, all transitions are permitted.
260
+ */
261
+ transitionsTo?: string[];
262
+ }[];
263
+ /**
264
+ * OPTIONAL — default status assigned to new items. MUST refer to a status declared (locally or inherited) by this collection.
265
+ */
266
+ initialStatus?: string;
267
+ /**
268
+ * Ownership rules. Each leaf field overrides independently across the chain.
269
+ */
270
+ ownership?: {
271
+ /**
272
+ * How many owners an item may carry. `none` = no ownership concept; `single` = one owner; `multiple` = list of owners.
273
+ */
274
+ cardinality?: "none" | "single" | "multiple";
275
+ /**
276
+ * Item field name that holds the owner ref.
277
+ */
278
+ role?: string;
279
+ /**
280
+ * Whether items MUST declare an owner.
281
+ */
282
+ required?: boolean;
283
+ };
284
+ /**
285
+ * Deadline rules. Each leaf field overrides independently.
286
+ */
287
+ deadline?: {
288
+ /**
289
+ * Deadline shape. `none` = no deadline concept; `target-date` = single date; `window` = start+end; `recurrent` = repeating.
290
+ */
291
+ kind?: "none" | "target-date" | "window" | "recurrent";
292
+ /**
293
+ * Whether items MUST declare a deadline value.
294
+ */
295
+ required?: boolean;
296
+ /**
297
+ * Item field name that holds the deadline value.
298
+ */
299
+ fieldName?: string;
300
+ };
301
+ /**
302
+ * Lint rules. Merge-by-id vs parent.
303
+ */
304
+ lints?: {
305
+ /**
306
+ * Stable kebab-case lint id. Merge key when composing.
307
+ */
308
+ id: string;
309
+ /**
310
+ * Lint algorithm. `custom` delegates to a host-defined check identified by `id`.
311
+ */
312
+ kind: "missing-owner" | "overdue" | "orphan" | "broken-ref" | "stale" | "required-field" | "custom";
313
+ /**
314
+ * Always '*' — items belong to one collection, so the lint always applies to all items of this collection. The field is preserved for symmetry with AIP-10's lint shape.
315
+ */
316
+ appliesTo: "*";
317
+ /**
318
+ * Lint severity. Children may soften; governance policies MAY forbid softening below `error`.
319
+ */
320
+ severity: "error" | "warn" | "info";
321
+ /**
322
+ * Kind-specific parameters. e.g. { days: 30 } for `stale`; { field: 'severity' } for `required-field`.
323
+ */
324
+ params?: {
325
+ [k: string]: unknown;
326
+ };
327
+ }[];
328
+ /**
329
+ * Item identity & filing rules.
330
+ */
331
+ identity?: {
332
+ /**
333
+ * How to derive an item's slug. Either a field name (e.g. 'title'), the literal 'random', the literal 'sequence', or 'hash:<comma-separated-source-fields>' (e.g. 'hash:title,createdAt').
334
+ */
335
+ slugSource?: string;
336
+ /**
337
+ * Template for where items are filed on disk. Tokens: {collection}, {slug}, {year}, {month}. e.g. 'items/{collection}/{slug}.md'.
338
+ */
339
+ filingPath?: string;
340
+ };
341
+ /**
342
+ * Vendor-specific extensions, namespaced under <vendor>. Deep-merged across the extends chain.
343
+ */
344
+ metadata?: {
345
+ [k: string]: unknown;
346
+ };
347
+ };
348
+ /**
349
+ * Inline layer-collection declaration. Full AIP-18 schema embedded; hosts MUST validate it against the AIP-18 COLLECTION schema before registration.
350
+ */
351
+ interface CollectionInline {
352
+ inline: Schema;
353
+ }
354
+ /**
355
+ * Definition of one field on a collection's item schema. Merge-by-name. Type drift between parent and child is HARD refused.
356
+ */
357
+ interface FieldDef {
358
+ /**
359
+ * kebab-or-camel-case field name. Merge key when composing.
360
+ */
361
+ name: string;
362
+ /**
363
+ * Field type. Drift across composition (parent string -> child number) is HARD refused (`collection_field_type_drift`).
364
+ */
365
+ type: "string" | "number" | "boolean" | "enum" | "date" | "datetime" | "text" | "url" | "ref" | "array";
366
+ /**
367
+ * Whether items MUST declare this field. A child may narrow false -> true; loosening true -> false is permitted (it removes a constraint without invalidating instances).
368
+ */
369
+ required?: boolean;
370
+ /**
371
+ * Prose describing what the field captures.
372
+ */
373
+ description?: string;
374
+ /**
375
+ * Required when type=enum. Children may narrow to a subset; widening to a superset is permitted (it does not invalidate instances).
376
+ */
377
+ enum?: string[];
378
+ items?: FieldDef1;
379
+ /**
380
+ * Required when type=ref. The target collection's `name`. Hosts validate that ref values point at items of this collection.
381
+ */
382
+ refKind?: string;
383
+ /**
384
+ * OPTIONAL regex constraint. Only valid when type=string.
385
+ */
386
+ pattern?: string;
387
+ /**
388
+ * OPTIONAL minimum. For type=number: minimum value. For type=array: minimum length.
389
+ */
390
+ min?: number;
391
+ /**
392
+ * OPTIONAL maximum. For type=number: maximum value. For type=array: maximum length.
393
+ */
394
+ max?: number;
395
+ /**
396
+ * OPTIONAL named format. Common values: email, uri, semver, uuid, slug. Only valid when type=string. Hosts MAY interpret unknown formats as advisory.
397
+ */
398
+ format?: string;
399
+ /**
400
+ * OPTIONAL deprecation flag. A child may set false to mark an inherited field deprecated; the host preserves the field in the resolved schema (so existing items still validate) but flags new uses via lint. Setting enabled:false on a field a child does not inherit is invalid.
401
+ */
402
+ enabled?: boolean;
403
+ }
404
+ /**
405
+ * Required when type=array. Recursive shape — describes the inner item type.
406
+ */
407
+ interface FieldDef1 {
408
+ /**
409
+ * kebab-or-camel-case field name. Merge key when composing.
410
+ */
411
+ name: string;
412
+ /**
413
+ * Field type. Drift across composition (parent string -> child number) is HARD refused (`collection_field_type_drift`).
414
+ */
415
+ type: "string" | "number" | "boolean" | "enum" | "date" | "datetime" | "text" | "url" | "ref" | "array";
416
+ /**
417
+ * Whether items MUST declare this field. A child may narrow false -> true; loosening true -> false is permitted (it removes a constraint without invalidating instances).
418
+ */
419
+ required?: boolean;
420
+ /**
421
+ * Prose describing what the field captures.
422
+ */
423
+ description?: string;
424
+ /**
425
+ * Required when type=enum. Children may narrow to a subset; widening to a superset is permitted (it does not invalidate instances).
426
+ */
427
+ enum?: string[];
428
+ items?: FieldDef1;
429
+ /**
430
+ * Required when type=ref. The target collection's `name`. Hosts validate that ref values point at items of this collection.
431
+ */
432
+ refKind?: string;
433
+ /**
434
+ * OPTIONAL regex constraint. Only valid when type=string.
435
+ */
436
+ pattern?: string;
437
+ /**
438
+ * OPTIONAL minimum. For type=number: minimum value. For type=array: minimum length.
439
+ */
440
+ min?: number;
441
+ /**
442
+ * OPTIONAL maximum. For type=number: maximum value. For type=array: maximum length.
443
+ */
444
+ max?: number;
445
+ /**
446
+ * OPTIONAL named format. Common values: email, uri, semver, uuid, slug. Only valid when type=string. Hosts MAY interpret unknown formats as advisory.
447
+ */
448
+ format?: string;
449
+ /**
450
+ * OPTIONAL deprecation flag. A child may set false to mark an inherited field deprecated; the host preserves the field in the resolved schema (so existing items still validate) but flags new uses via lint. Setting enabled:false on a field a child does not inherit is invalid.
451
+ */
452
+ enabled?: boolean;
453
+ }
454
+ /**
455
+ * Layer-collection ref declaration. Either a file path (./.. /COLLECTION.md) or a registry URI (ws://collections/<slug>).
456
+ */
457
+ interface CollectionRef {
458
+ /**
459
+ * Either a relative path to a COLLECTION.md (file ref) or a ws://collections/<slug> URI (registry import). The host loads the referenced collection via AIP-18 and registers it under its name (or the alias, if set).
460
+ */
461
+ ref: string;
462
+ /**
463
+ * OPTIONAL — workspace-local name to expose the layer collection under. Two collections resolving to the same effective name (alias or upstream) is a HARD failure: identity_collection_alias_conflict.
464
+ */
465
+ alias?: string;
466
+ /**
467
+ * OPTIONAL — semver range (e.g. "1.x", "^1.2", "1.2.0"). When set, schema bumps outside the range fail with collection_item_schema_pinned_drift (HARD, AIP-18 vocabulary) at item load time.
468
+ */
469
+ version?: string;
470
+ }
471
+ type IdentityHandle = Readonly<IdentityDefinition>;
472
+
473
+ export type { IdentityDefinition as I, IdentityHandle as a };
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@agentproto/identity",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "@agentproto/identity — AIP-23 IDENTITY.md reference implementation. A workspace AIP that defines layered, composable agent identity — typed layers as AIP-18 collections, confidence-scored items, optional temporal entries, and compression-artifact tiers — owning only the workspace root manifest, layer registry, compression policy, junction rules, and cross-AIP composition.",
5
+ "keywords": [
6
+ "agentproto",
7
+ "aip-23",
8
+ "identity",
9
+ "defineIdentity",
10
+ "open-standard",
11
+ "agentic"
12
+ ],
13
+ "homepage": "https://agentproto.sh/docs/aip-23",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/agentproto/ts",
17
+ "directory": "packages/identity"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/agentproto/ts/issues"
21
+ },
22
+ "license": "MIT",
23
+ "type": "module",
24
+ "main": "dist/index.mjs",
25
+ "module": "dist/index.mjs",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.mjs",
31
+ "default": "./dist/index.mjs"
32
+ },
33
+ "./manifest": {
34
+ "types": "./dist/manifest/index.d.ts",
35
+ "import": "./dist/manifest/index.mjs",
36
+ "default": "./dist/manifest/index.mjs"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "dependencies": {
49
+ "gray-matter": "^4.0.3",
50
+ "zod": "^4.4.3",
51
+ "@agentproto/define-doctype": "0.1.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.6.2",
55
+ "tsup": "^8.5.1",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^3.2.4",
58
+ "@agentproto/tooling": "0.1.0-alpha.0"
59
+ },
60
+ "scripts": {
61
+ "dev": "tsup --watch",
62
+ "build": "tsup",
63
+ "clean": "rm -rf dist",
64
+ "check-types": "tsc --noEmit",
65
+ "test": "vitest run --passWithNoTests",
66
+ "test:watch": "vitest"
67
+ }
68
+ }