halfcode-compiler.xnl 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +11 -1
- package/dist/system-skills/resource-dsl/KindDefinitions/SkillCapsule/manifest.xnl +21 -0
- package/dist/system-skills/resource-dsl/KindDefinitions/WikiPage/manifest.xnl +10 -0
- package/dist/system-skills/resource-dsl/SkillCapsules/System/SKILL.metadata.yaml +2 -0
- package/dist/system-skills/resource-dsl/SkillCapsules/System/SKILL.template.ejs +20 -0
- package/dist/system-skills/resource-dsl/SkillCapsules/System/manifest.xnl +18 -0
- package/dist/system-skills/resource-dsl/SkillCapsules/System/resource-mappings.xnl +10 -0
- package/dist/system-skills/resource-dsl/WikiPages/documents/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/files/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/index/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/language/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/migration/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/projections/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/WikiPages/skill-capsules/manifest.xnl +6 -0
- package/dist/system-skills/resource-dsl/documents.md +119 -0
- package/dist/system-skills/resource-dsl/examples/function.xnl +12 -0
- package/dist/system-skills/resource-dsl/examples/index.md +17 -0
- package/dist/system-skills/resource-dsl/examples/kind-definition.xnl +12 -0
- package/dist/system-skills/resource-dsl/examples/resource-mappings.xnl +21 -0
- package/dist/system-skills/resource-dsl/examples/resource-package.xnl +19 -0
- package/dist/system-skills/resource-dsl/examples/skill-capsule-authoring.xnl +11 -0
- package/dist/system-skills/resource-dsl/examples/skill-capsule-devops.xnl +12 -0
- package/dist/system-skills/resource-dsl/examples/skill-capsule-kind-definition.xnl +27 -0
- package/dist/system-skills/resource-dsl/examples/skill-capsule-resource-dsl.xnl +8 -0
- package/dist/system-skills/resource-dsl/examples/skill-capsule-run.xnl +8 -0
- package/dist/system-skills/resource-dsl/files.md +47 -0
- package/dist/system-skills/resource-dsl/index.md +59 -0
- package/dist/system-skills/resource-dsl/language.md +64 -0
- package/dist/system-skills/resource-dsl/manifest.xnl +10 -0
- package/dist/system-skills/resource-dsl/migration.md +40 -0
- package/dist/system-skills/resource-dsl/projections.md +142 -0
- package/dist/system-skills/resource-dsl/skill-capsules.md +94 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,20 @@ Each capsule identity includes the XNL `apiVersion` and `version`. The planner g
|
|
|
38
38
|
|
|
39
39
|
The legacy `compileSkillCapsule` and `compileResourceSkillCapsule` APIs remain available from both the package root and `halfcode-compiler.xnl/skill-capsule`. The subpath also exports the new plan/apply APIs and `SkillCapsuleDependency` type.
|
|
40
40
|
|
|
41
|
+
The package root also exposes the canonical Resource DSL system Skill in two forms. Use the module descriptor when composing it as a typed sibling dependency in a larger application assembly; use the immutable bundled plan when installing it directly:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import {
|
|
45
|
+
loadHalfcodeResourceDslSystemSkillModule,
|
|
46
|
+
loadHalfcodeResourceDslSystemSkillPlan,
|
|
47
|
+
} from "halfcode-compiler.xnl"
|
|
48
|
+
|
|
49
|
+
const resourceDslModule = loadHalfcodeResourceDslSystemSkillModule()
|
|
50
|
+
const readyToInstall = await loadHalfcodeResourceDslSystemSkillPlan()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The module's resource root is contained in the installed npm package. Both forms are generated from that same packaged ResourcePackage during build, while `sys-halfcode-resource-dsl` keeps its independent `1.0.0` Skill version.
|
|
54
|
+
|
|
41
55
|
Lower-level APIs are available through explicit subpaths such as `halfcode-compiler.xnl/resource-core` and `halfcode-compiler.xnl/authoring-runtime`.
|
|
42
56
|
|
|
43
57
|
The resource-core subpath preserves the single-package loader and adds deterministic, read-only composition APIs:
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { A as buildResourceDependencySnapshot, B as ResourceTombstone, C as Buil
|
|
|
3
3
|
import { i as ResourceCompositionError, n as ResourceLayerContentIdentityInput, r as resolveEffectiveResourceContentIdentities, t as ResolveEffectiveResourceContentIdentitiesInput } from "./resource-core-Byhqyadq.js";
|
|
4
4
|
import { S as skillCapsuleDistributionProjection, _ as applySkillCapsuleDistributionPlan, a as PlannedSkillCapsule, b as compilerSkillPackage, c as SkillCapsuleContentDigest, d as SkillCapsuleDistributionReceipt, f as SkillCapsuleIdentity, g as SkillReference, h as SkillDescriptor, i as PlanSkillCapsuleDistributionInput, l as SkillCapsuleDistributionError, m as SkillCapsuleProvenanceManifest, n as CompileResourceSkillCapsuleInput, o as PlannedSkillFile, p as SkillCapsulePlan, r as CompileSkillCapsuleInput, s as SkillCapsuleApplyStep, t as ApplySkillCapsuleDistributionOptions, u as SkillCapsuleDistributionPlan, v as compileResourceSkillCapsule, x as planSkillCapsuleDistribution, y as compileSkillCapsule } from "./index-96qHPZj2.js";
|
|
5
5
|
//#region src/bundled-system-skills.d.ts
|
|
6
|
+
declare function loadHalfcodeResourceDslSystemSkillModule(): AuthoringModuleDescriptor;
|
|
6
7
|
declare function loadHalfcodeResourceDslSystemSkillPlan(): Promise<SkillCapsuleDistributionPlan>;
|
|
7
8
|
//#endregion
|
|
8
|
-
export { type ApplicationAssembly, type ApplicationScope, ApplySkillCapsuleDistributionOptions, type AssemblyPort, type AssemblyPortBinding, type AssemblyResource, type AuthoringModuleDescriptor, BuildResourceDependencySnapshotInput, type BusinessObjectResource, type BusinessObjectSopResource, type CodeBinding, CompileResourceSkillCapsuleInput, CompileSkillCapsuleInput, ComposeLayeredResourceRegistryInput, type ContractedCallableResource, CreateResourceContentIdentityInput, EffectiveKindDefinition, EffectiveResourceEntry, EffectiveResourceRegistry, type ExecuteObjectOperationRequest, type JsonObject, type JsonPrimitive, type JsonValue, type LoadApplicationAssemblyOptions, LoadResourceTreeOptions, LoadedResourceTree, LoadedResourceTreeBuildResult, type ObjectInvocation, type ObjectInvocationMode, type ObjectOperationBehavior, type ObjectOperationCall, type ObjectOperationCatalog, type ObjectOperationConfig, ObjectOperationContractError, type ObjectOperationDefinition, type ObjectOperationEffect, type ObjectOperationHandler, type ObjectOperationOwnerKind, type ObjectOperationTargetDeclaration, type ObjectTargetKindDefinition, type ObjectTargetRef, type ObjectTargets, type PageObjectResource, PlanSkillCapsuleDistributionInput, PlannedSkillCapsule, PlannedSkillFile, RegisteredKindDefinition, type ResolveApplicationAssemblyOptions, ResolveEffectiveResourceContentIdentitiesInput, type ResolvedAssemblyPortBinding, ResourceCompositionError, ResourceContentIdentity, ResourceDependencyEdge, ResourceDependencySnapshot, ResourceDescriptor, ResourceDiagnostic, ResourceDigestContribution, ResourceIdentity, type ResourceInclude, ResourceKindContract, ResourceLayerContentIdentityInput, ResourceLayerDescriptor, ResourceLayerInput, ResourceMetadata, ResourceNode, ResourceOrigin, ResourceRecord, ResourceRegistry, ResourceScalar, type ResourceSource, ResourceTombstone, ResourceTombstoneOrigin, ResourceTree, ResourceTreeBuildResult, ResourceValidationError, ResourceValue, ResourceValueList, ResourceValueMap, type Sha256Digest, SkillCapsuleApplyStep, SkillCapsuleContentDigest, type SkillCapsuleDependency, SkillCapsuleDistributionError, SkillCapsuleDistributionPlan, SkillCapsuleDistributionReceipt, SkillCapsuleIdentity, SkillCapsulePlan, SkillCapsuleProvenanceManifest, type SkillCapsuleResource, SkillDescriptor, SkillReference, SnapshotResource, SourceShape, type TextMaterial, type TextResource, applicationAssemblyPackage, applySkillCapsuleDistributionPlan, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, buildResourceDependencySnapshot, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, composeLayeredResourceRegistry, createResourceContentIdentity, loadApplicationAssembly, loadHalfcodeResourceDslSystemSkillPlan, loadResourceTree, planSkillCapsuleDistribution, resolveApplicationAssembly, resolveEffectiveResourceContentIdentities, resourceRefToFqn, sha256Digest, skillCapsuleDistributionProjection, validateResourceTree };
|
|
9
|
+
export { type ApplicationAssembly, type ApplicationScope, ApplySkillCapsuleDistributionOptions, type AssemblyPort, type AssemblyPortBinding, type AssemblyResource, type AuthoringModuleDescriptor, BuildResourceDependencySnapshotInput, type BusinessObjectResource, type BusinessObjectSopResource, type CodeBinding, CompileResourceSkillCapsuleInput, CompileSkillCapsuleInput, ComposeLayeredResourceRegistryInput, type ContractedCallableResource, CreateResourceContentIdentityInput, EffectiveKindDefinition, EffectiveResourceEntry, EffectiveResourceRegistry, type ExecuteObjectOperationRequest, type JsonObject, type JsonPrimitive, type JsonValue, type LoadApplicationAssemblyOptions, LoadResourceTreeOptions, LoadedResourceTree, LoadedResourceTreeBuildResult, type ObjectInvocation, type ObjectInvocationMode, type ObjectOperationBehavior, type ObjectOperationCall, type ObjectOperationCatalog, type ObjectOperationConfig, ObjectOperationContractError, type ObjectOperationDefinition, type ObjectOperationEffect, type ObjectOperationHandler, type ObjectOperationOwnerKind, type ObjectOperationTargetDeclaration, type ObjectTargetKindDefinition, type ObjectTargetRef, type ObjectTargets, type PageObjectResource, PlanSkillCapsuleDistributionInput, PlannedSkillCapsule, PlannedSkillFile, RegisteredKindDefinition, type ResolveApplicationAssemblyOptions, ResolveEffectiveResourceContentIdentitiesInput, type ResolvedAssemblyPortBinding, ResourceCompositionError, ResourceContentIdentity, ResourceDependencyEdge, ResourceDependencySnapshot, ResourceDescriptor, ResourceDiagnostic, ResourceDigestContribution, ResourceIdentity, type ResourceInclude, ResourceKindContract, ResourceLayerContentIdentityInput, ResourceLayerDescriptor, ResourceLayerInput, ResourceMetadata, ResourceNode, ResourceOrigin, ResourceRecord, ResourceRegistry, ResourceScalar, type ResourceSource, ResourceTombstone, ResourceTombstoneOrigin, ResourceTree, ResourceTreeBuildResult, ResourceValidationError, ResourceValue, ResourceValueList, ResourceValueMap, type Sha256Digest, SkillCapsuleApplyStep, SkillCapsuleContentDigest, type SkillCapsuleDependency, SkillCapsuleDistributionError, SkillCapsuleDistributionPlan, SkillCapsuleDistributionReceipt, SkillCapsuleIdentity, SkillCapsulePlan, SkillCapsuleProvenanceManifest, type SkillCapsuleResource, SkillDescriptor, SkillReference, SnapshotResource, SourceShape, type TextMaterial, type TextResource, applicationAssemblyPackage, applySkillCapsuleDistributionPlan, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, buildResourceDependencySnapshot, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, composeLayeredResourceRegistry, createResourceContentIdentity, loadApplicationAssembly, loadHalfcodeResourceDslSystemSkillModule, loadHalfcodeResourceDslSystemSkillPlan, loadResourceTree, planSkillCapsuleDistribution, resolveApplicationAssembly, resolveEffectiveResourceContentIdentities, resourceRefToFqn, sha256Digest, skillCapsuleDistributionProjection, validateResourceTree };
|
package/dist/index.js
CHANGED
|
@@ -3,11 +3,21 @@ import { a as assertObjectOperationCatalog, c as resolveApplicationAssembly, i a
|
|
|
3
3
|
import "./application-assembly.js";
|
|
4
4
|
import { composeLayeredResourceRegistry, resolveEffectiveResourceContentIdentities } from "./resource-core.js";
|
|
5
5
|
import { a as compilerSkillPackage, i as compileSkillCapsule, n as applySkillCapsuleDistributionPlan, o as planSkillCapsuleDistribution, r as compileResourceSkillCapsule, s as skillCapsuleDistributionProjection, t as SkillCapsuleDistributionError } from "./src-D1Bmq7Lo.js";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
6
7
|
//#region src/bundled-system-skills.ts
|
|
8
|
+
function loadHalfcodeResourceDslSystemSkillModule() {
|
|
9
|
+
return Object.freeze({
|
|
10
|
+
id: "ResourceDsl",
|
|
11
|
+
packageName: "halfcode-resource-dsl-system-skill",
|
|
12
|
+
family: "halfcode-resource-dsl",
|
|
13
|
+
scope: "shared",
|
|
14
|
+
resourceRootDir: fileURLToPath(new URL("./system-skills/resource-dsl/", import.meta.url))
|
|
15
|
+
});
|
|
16
|
+
}
|
|
7
17
|
async function loadHalfcodeResourceDslSystemSkillPlan() {
|
|
8
18
|
const bundled = await import(new URL("./system-skills/sys-halfcode-resource-dsl.plan.js", import.meta.url).href);
|
|
9
19
|
if (!bundled.default) throw new Error("HALFCODE_RESOURCE_DSL_SKILL_PLAN_MISSING: bundled plan has no default export");
|
|
10
20
|
return bundled.default;
|
|
11
21
|
}
|
|
12
22
|
//#endregion
|
|
13
|
-
export { ObjectOperationContractError, ResourceCompositionError, ResourceValidationError, SkillCapsuleDistributionError, applicationAssemblyPackage, applySkillCapsuleDistributionPlan, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, buildResourceDependencySnapshot, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, composeLayeredResourceRegistry, createResourceContentIdentity, loadApplicationAssembly, loadHalfcodeResourceDslSystemSkillPlan, loadResourceTree, planSkillCapsuleDistribution, resolveApplicationAssembly, resolveEffectiveResourceContentIdentities, resourceRefToFqn, sha256Digest, skillCapsuleDistributionProjection, validateResourceTree };
|
|
23
|
+
export { ObjectOperationContractError, ResourceCompositionError, ResourceValidationError, SkillCapsuleDistributionError, applicationAssemblyPackage, applySkillCapsuleDistributionPlan, assertExecuteObjectOperationRequest, assertObjectOperationCall, assertObjectOperationCatalog, assertObjectOperationDefinition, buildResourceDependencySnapshot, compileResourceSkillCapsule, compileSkillCapsule, compilerSkillPackage, composeLayeredResourceRegistry, createResourceContentIdentity, loadApplicationAssembly, loadHalfcodeResourceDslSystemSkillModule, loadHalfcodeResourceDslSystemSkillPlan, loadResourceTree, planSkillCapsuleDistribution, resolveApplicationAssembly, resolveEffectiveResourceContentIdentities, resourceRefToFqn, sha256Digest, skillCapsuleDistributionProjection, validateResourceTree };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<KindDefinition #Halfcode.ResourceDsl.KindDefinition.SkillCapsule apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Kind definition for the versioned Resource DSL consumer SkillCapsule."
|
|
4
|
+
resourceKind = "SkillCapsule"
|
|
5
|
+
sourceShapes = ["directory"]
|
|
6
|
+
currentApiVersion = "halfcode.resources/v1"
|
|
7
|
+
supportedApiVersions = ["halfcode.resources/v1"]
|
|
8
|
+
} (
|
|
9
|
+
<DescriptorContract (
|
|
10
|
+
<RequiredFiles [
|
|
11
|
+
<File { name = "SKILL.metadata.yaml" }>
|
|
12
|
+
<File { name = "SKILL.template.ejs" }>
|
|
13
|
+
<File { name = "resource-mappings.xnl" }>
|
|
14
|
+
]>
|
|
15
|
+
<IncludeContract {
|
|
16
|
+
collection = "Includes"
|
|
17
|
+
relation = "compiled-resource-selection"
|
|
18
|
+
dependencySemantics = false
|
|
19
|
+
}>
|
|
20
|
+
)>
|
|
21
|
+
)>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<KindDefinition #Halfcode.ResourceDsl.KindDefinition.WikiPage apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Kind definition for canonical documentation pages referenced from the Resource DSL package root."
|
|
4
|
+
resourceKind = "WikiPage"
|
|
5
|
+
sourceShapes = ["directory"]
|
|
6
|
+
currentApiVersion = "halfcode.resources/v1"
|
|
7
|
+
supportedApiVersions = ["halfcode.resources/v1"]
|
|
8
|
+
} (
|
|
9
|
+
<DescriptorContract>
|
|
10
|
+
)>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: <%= metadata.name %>
|
|
3
|
+
description: <%= metadata.description %>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# <%= metadata.title %>
|
|
7
|
+
|
|
8
|
+
Use this Skill for the generic XNL resource language and its deterministic compiler contracts. Product-specific authoring and runtime operations belong to their owner Skills.
|
|
9
|
+
|
|
10
|
+
## Progressive loading
|
|
11
|
+
|
|
12
|
+
1. Start with `references/resource-dsl/index.md`.
|
|
13
|
+
2. For XNL channels and source syntax, read `references/resource-dsl/language.md` and only the needed file under `references/resource-dsl/examples/`.
|
|
14
|
+
3. For ResourcePackage, Catalog or KindDefinition work, read `references/resource-dsl/documents.md` and `references/resource-dsl/files.md`.
|
|
15
|
+
4. For layered registries, content identities or snapshots, read `references/resource-dsl/projections.md`.
|
|
16
|
+
5. For SkillCapsule dependency/distribution work, read `references/resource-dsl/skill-capsules.md`.
|
|
17
|
+
6. Read `references/resource-dsl/migration.md` only for migration work.
|
|
18
|
+
7. Use `references/.halfcode/provenance.json` to verify source identity, version and payload digests.
|
|
19
|
+
|
|
20
|
+
Do not infer resource relationships from ordinary text. Use explicit catalogs, typed references and Kind-owned contracts, then rely on deterministic validation and compilation.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<SkillCapsule #Halfcode.ResourceDsl.Skill.System apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
name = "sys-halfcode-resource-dsl"
|
|
3
|
+
lifecycle = "Stable"
|
|
4
|
+
description = "Author and review XNL ResourcePackages, catalogs, KindDefinitions, VFS materials, projections and SkillCapsules using the canonical Halfcode Resource DSL."
|
|
5
|
+
} (
|
|
6
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
7
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
8
|
+
<ResourceMappings { href = "vfs://./resource-mappings.xnl" format = "xnl" }>
|
|
9
|
+
<Includes [
|
|
10
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.index" }>
|
|
11
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.language" }>
|
|
12
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.documents" }>
|
|
13
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.files" }>
|
|
14
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.projections" }>
|
|
15
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.skill-capsules" }>
|
|
16
|
+
<Include { kind = "WikiPage" ref = "resource://Halfcode.ResourceDsl.Wiki.migration" }>
|
|
17
|
+
]>
|
|
18
|
+
)>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<ResourceMappings #Halfcode.ResourceDsl.ResourceMappings.System apiVersion="halfcode.resources/v1" version="1.0.0" (
|
|
2
|
+
<ReferenceTargets [
|
|
3
|
+
<ReferenceTarget { kind = "WikiPage" target = "references/resource-dsl/" }>
|
|
4
|
+
]>
|
|
5
|
+
<SourceRoots [
|
|
6
|
+
<SourceRoot #CanonicalExamples { sourceRoot = "vfs://module/ResourceDsl/" } [
|
|
7
|
+
<CopyDirectory { from = "examples" to = "references/resource-dsl/examples" }>
|
|
8
|
+
]>
|
|
9
|
+
]>
|
|
10
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.documents apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Resource documents, package catalogs and KindDefinition contracts."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/documents.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.files apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Resource source shapes, VFS containment and file provenance."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/files.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.index apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Resource DSL overview and progressive documentation index."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/index.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.language apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "XNL language channels and authority projection rules."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/language.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.migration apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Migration guidance from non-canonical resource representations."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/migration.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.projections apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Normalized, layered, content identity and dependency snapshot projections."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/projections.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<WikiPage #Halfcode.ResourceDsl.Wiki.skill-capsules apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "SkillCapsule dependencies, deterministic plans and atomic distribution."
|
|
4
|
+
} (
|
|
5
|
+
<Instruction { href = "vfs://@/skill-capsules.md" format = "markdown" }>
|
|
6
|
+
)>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Resource Document Families
|
|
2
|
+
|
|
3
|
+
## ResourcePackage 与 Catalogs
|
|
4
|
+
|
|
5
|
+
一个 package 有且只有一个 `ResourcePackage` authority root。它拥有唯一 `Catalogs` 子域;每个 `Catalog` 声明一种资源的逻辑根与目录入口:
|
|
6
|
+
|
|
7
|
+
```xnl
|
|
8
|
+
<ResourcePackage #demo.resource_workflow.authoring apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
9
|
+
lifecycle = "Active"
|
|
10
|
+
description = "Demo authoring resource package"
|
|
11
|
+
} (
|
|
12
|
+
<Catalogs [
|
|
13
|
+
<Catalog #kind_definitions {
|
|
14
|
+
kind = "KindDefinition"
|
|
15
|
+
shape = "directory"
|
|
16
|
+
root = "vfs://./KindDefinitions/"
|
|
17
|
+
entry = "manifest.xnl"
|
|
18
|
+
}>
|
|
19
|
+
<Catalog #functions {
|
|
20
|
+
kind = "Function"
|
|
21
|
+
shape = "directory"
|
|
22
|
+
root = "vfs://./Functions/"
|
|
23
|
+
entry = "manifest.xnl"
|
|
24
|
+
}>
|
|
25
|
+
]>
|
|
26
|
+
)>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
catalog 只描述组织,不复制每个 descriptor 的内容。`shape` 取 `single-file|directory|manifest`;后两者必须声明目录入口 `entry`。`single-file` 缺省扫描 `root` 下全部 `.xnl` 文件,也可以用可选 `entry = "<name>.xnl"` 精确选择同目录中的一个 authority 文件;该 entry 必须是无路径片段的 XNL 文件名。loader 用根 tag/`#id` 确认 kind/identity。
|
|
30
|
+
|
|
31
|
+
## KindDefinition
|
|
32
|
+
|
|
33
|
+
`KindDefinition` 声明 source shape 与 descriptor contract:
|
|
34
|
+
|
|
35
|
+
```xnl
|
|
36
|
+
<KindDefinition #halfcode.resource_kind.Function apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
37
|
+
lifecycle = "Stable"
|
|
38
|
+
sourceShapes = ["single-file" "directory"]
|
|
39
|
+
currentApiVersion = "halfcode.resources/v1"
|
|
40
|
+
supportedApiVersions = ["halfcode.resources/v1"]
|
|
41
|
+
} (
|
|
42
|
+
<DescriptorContract (
|
|
43
|
+
<Identity { required = true form = "fqn" }>
|
|
44
|
+
<CodeBinding { property = "src" scheme = "vfs" exportFragmentRequired = true }>
|
|
45
|
+
<Instruction { required = false source = "inline-or-vfs" }>
|
|
46
|
+
)>
|
|
47
|
+
)>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`currentApiVersion` 是新资源和迁移目标版本,`supportedApiVersions` 是 loader 可直接读取的兼容集合,且必须包含 current。未知版本必须先经过调用方在代码侧注册的确定性 migration,再交给 loader;可执行转换不写入 XNL。
|
|
51
|
+
|
|
52
|
+
`documentCardinality` 缺省为 `"one"`。只有 `sourceShapes = ["single-file"]` 的 Kind 可以声明 `documentCardinality = "many"`,表示一个 authority 文档允许包含多个并列的同 Kind 根;它不是对所有 XNL 文件放宽根约束。
|
|
53
|
+
|
|
54
|
+
Kind contract 可以按自身语义约束 lifecycle、description、instruction、code binding 与 includes;除 `#id` 和 `apiVersion` 外,这些字段都不是通用 loader 强加给所有 Kind 的共同要求。
|
|
55
|
+
|
|
56
|
+
加载成功后,consumer 从 `ResourceTree.registry.kindDefinitions` 按 `resourceKind` 取得规范化 contract。该 projection 包含 version、source shape、cardinality、required files 以及 KindDefinition 自身的 `resourceId`/`documentUri` provenance;KindDefinition 不混入业务资源的 `registry.byKind`。
|
|
57
|
+
|
|
58
|
+
## Resource descriptor
|
|
59
|
+
|
|
60
|
+
descriptor 根 tag 直接使用 kind,`#id` 是资源 FQN。唯一概念进入 `()`;重复成员进入 `[]`:
|
|
61
|
+
|
|
62
|
+
```xnl
|
|
63
|
+
<Function #demo.resource_workflow.prepare_data apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
64
|
+
lifecycle = "Active"
|
|
65
|
+
title = "Prepare workflow data"
|
|
66
|
+
} (
|
|
67
|
+
<Instruction ?instruction>
|
|
68
|
+
接收输入并产生下游 procedure 所需的规范数据。
|
|
69
|
+
</?instruction>
|
|
70
|
+
<CodeBinding {
|
|
71
|
+
src = "vfs://@/apps/demo-resource-workflow-authoring/src/procedures.ts#prepareProcedure"
|
|
72
|
+
}>
|
|
73
|
+
)>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
通用资源外壳只规定 identity、metadata channel、members/subdomains 和 provenance。各 Kind 的稳定领域字段及其 requiredness 由对应 `KindDefinition` 或 consumer contract 收窄;缺失的可选字段不会被填成空字符串。
|
|
77
|
+
|
|
78
|
+
允许 forest 的 Kind 仍逐根执行同样的 kind、identity 与 `apiVersion` 校验。例如 Decision Kind 可以显式声明:
|
|
79
|
+
|
|
80
|
+
```xnl
|
|
81
|
+
<KindDefinition #codument.resource_kind.Decision apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
82
|
+
lifecycle = "Stable"
|
|
83
|
+
sourceShapes = ["single-file"]
|
|
84
|
+
currentApiVersion = "codument.tech/v1alpha1"
|
|
85
|
+
supportedApiVersions = ["codument.tech/v1alpha1"]
|
|
86
|
+
documentCardinality = "many"
|
|
87
|
+
}>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
对应 authority 文件可以有多个并列 `<Decision ...>` 根。每个根归一化为独立 resource record,并共享该文件的 `documentUri` provenance;重复 `#id`、混合根 kind 或不受支持的版本仍是错误。
|
|
91
|
+
|
|
92
|
+
## ResourceMappings
|
|
93
|
+
|
|
94
|
+
mapping 根拥有多个唯一 collection subdomain;collection 的 `[]` 承载重复条目:
|
|
95
|
+
|
|
96
|
+
```xnl
|
|
97
|
+
<ResourceMappings #demo.resource_workflow.mappings apiVersion="halfcode.resources/v1" version="1.0.0" (
|
|
98
|
+
<ReferenceTargets [
|
|
99
|
+
<ReferenceTarget #function_dependency {
|
|
100
|
+
fromKind = "Function"
|
|
101
|
+
field = "dependsOn"
|
|
102
|
+
targetKind = "Function"
|
|
103
|
+
}>
|
|
104
|
+
]>
|
|
105
|
+
<CallableArtifacts [
|
|
106
|
+
<CallableArtifact #function_callable {
|
|
107
|
+
kind = "Function"
|
|
108
|
+
binding = "CodeBinding.src"
|
|
109
|
+
}>
|
|
110
|
+
]>
|
|
111
|
+
<SourceRoots [
|
|
112
|
+
<SourceRoot #authoring {
|
|
113
|
+
uri = "vfs://@/apps/demo-resource-workflow-authoring/resources/"
|
|
114
|
+
}>
|
|
115
|
+
]>
|
|
116
|
+
)>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
mapping key 是显式属性或 `#id`,不得把用户数据动态拼进 tag 名。
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<Function #demo.resource_workflow.prepare_data apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Active"
|
|
3
|
+
title = "Prepare workflow data"
|
|
4
|
+
} (
|
|
5
|
+
<Instruction ?instruction>
|
|
6
|
+
接收输入并产生下游 procedure 所需的规范数据。
|
|
7
|
+
</?instruction>
|
|
8
|
+
<CodeBinding {
|
|
9
|
+
src = "vfs://@/apps/demo-resource-workflow-authoring/src/procedures.ts#prepareProcedure"
|
|
10
|
+
}>
|
|
11
|
+
)>
|
|
12
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Parseable Examples
|
|
2
|
+
|
|
3
|
+
> 目录职责 · holds: 由当前 xnl-core parser 机械验证的规范 resource DSL 样例 · excludes: demo 业务资源与运行态 fixtures · tier: stable · ⬆from: resource DSL 文档实例 · ⬇to: parser/loader contract tests
|
|
4
|
+
|
|
5
|
+
| 文件 | 文档族 |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `resource-package.xnl` | package 与 catalogs |
|
|
8
|
+
| `kind-definition.xnl` | 通用 Function KindDefinition |
|
|
9
|
+
| `skill-capsule-kind-definition.xnl` | SkillCapsule exact dependency contract |
|
|
10
|
+
| `skill-capsule-devops.xnl` | 四 Skill 示例的 lifecycle root |
|
|
11
|
+
| `skill-capsule-authoring.xnl` | authoring -> shared resource DSL dependency |
|
|
12
|
+
| `skill-capsule-run.xnl` | 无 sibling dependency 的 run Skill |
|
|
13
|
+
| `skill-capsule-resource-dsl.xnl` | 被 authoring 复用的 shared resource DSL Skill |
|
|
14
|
+
| `function.xnl` | 带 instruction 与 code binding 的 descriptor |
|
|
15
|
+
| `resource-mappings.xnl` | reference/callable/source-root mappings |
|
|
16
|
+
|
|
17
|
+
这些文件由当前 `xnl-core` parser 做 parse/stringify/parse 验证。下游 resource-core track 会把相同检查变成持续测试。
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<KindDefinition #halfcode.resource_kind.Function apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
sourceShapes = ["single-file" "directory"]
|
|
4
|
+
currentApiVersion = "halfcode.resources/v1"
|
|
5
|
+
supportedApiVersions = ["halfcode.resources/v1"]
|
|
6
|
+
} (
|
|
7
|
+
<DescriptorContract (
|
|
8
|
+
<Identity { required = true form = "fqn" }>
|
|
9
|
+
<CodeBinding { property = "src" scheme = "vfs" exportFragmentRequired = true }>
|
|
10
|
+
<Instruction { required = false source = "inline-or-vfs" }>
|
|
11
|
+
)>
|
|
12
|
+
)>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<ResourceMappings #demo.resource_workflow.mappings apiVersion="halfcode.resources/v1" version="1.0.0" (
|
|
2
|
+
<ReferenceTargets [
|
|
3
|
+
<ReferenceTarget #function_dependency {
|
|
4
|
+
fromKind = "Function"
|
|
5
|
+
field = "dependsOn"
|
|
6
|
+
targetKind = "Function"
|
|
7
|
+
}>
|
|
8
|
+
]>
|
|
9
|
+
<CallableArtifacts [
|
|
10
|
+
<CallableArtifact #function_callable {
|
|
11
|
+
kind = "Function"
|
|
12
|
+
binding = "CodeBinding.src"
|
|
13
|
+
}>
|
|
14
|
+
]>
|
|
15
|
+
<SourceRoots [
|
|
16
|
+
<SourceRoot #authoring {
|
|
17
|
+
uri = "vfs://@/apps/demo-resource-workflow-authoring/resources/"
|
|
18
|
+
}>
|
|
19
|
+
]>
|
|
20
|
+
)>
|
|
21
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<ResourcePackage #demo.resource_workflow.authoring apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Active"
|
|
3
|
+
description = "Demo authoring resource package"
|
|
4
|
+
} (
|
|
5
|
+
<Catalogs [
|
|
6
|
+
<Catalog #kind_definitions {
|
|
7
|
+
kind = "KindDefinition"
|
|
8
|
+
shape = "directory"
|
|
9
|
+
root = "vfs://./KindDefinitions/"
|
|
10
|
+
entry = "manifest.xnl"
|
|
11
|
+
}>
|
|
12
|
+
<Catalog #functions {
|
|
13
|
+
kind = "Function"
|
|
14
|
+
shape = "directory"
|
|
15
|
+
root = "vfs://./Functions/"
|
|
16
|
+
entry = "manifest.xnl"
|
|
17
|
+
}>
|
|
18
|
+
]>
|
|
19
|
+
)>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<SkillCapsule #example.resource_lifecycle.skill.authoring apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
name = "example-resource-lifecycle-authoring"
|
|
3
|
+
lifecycle = "Active"
|
|
4
|
+
description = "Generic operations for resource creation and revision."
|
|
5
|
+
} (
|
|
6
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
7
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
8
|
+
<SkillDependencies [
|
|
9
|
+
<SkillDependency { ref = "resource://example.resource_lifecycle.skill.resource_dsl" version = "1.0.0" }>
|
|
10
|
+
]>
|
|
11
|
+
)>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<SkillCapsule #example.resource_lifecycle.skill.devops apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
name = "example-resource-lifecycle-devops"
|
|
3
|
+
lifecycle = "Active"
|
|
4
|
+
description = "Generic lifecycle root that routes authoring and run operations."
|
|
5
|
+
} (
|
|
6
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
7
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
8
|
+
<SkillDependencies [
|
|
9
|
+
<SkillDependency { ref = "resource://example.resource_lifecycle.skill.authoring" version = "1.0.0" }>
|
|
10
|
+
<SkillDependency { ref = "resource://example.resource_lifecycle.skill.run" version = "1.0.0" }>
|
|
11
|
+
]>
|
|
12
|
+
)>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<KindDefinition #halfcode.resource_kind.SkillCapsule apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Versioned Skill capsule with exact sibling dependencies."
|
|
4
|
+
resourceKind = "SkillCapsule"
|
|
5
|
+
sourceShapes = ["directory"]
|
|
6
|
+
currentApiVersion = "halfcode.resources/v1"
|
|
7
|
+
supportedApiVersions = ["halfcode.resources/v1"]
|
|
8
|
+
} (
|
|
9
|
+
<DescriptorContract (
|
|
10
|
+
<RequiredFiles [
|
|
11
|
+
<File { name = "SKILL.metadata.yaml" }>
|
|
12
|
+
<File { name = "SKILL.template.ejs" }>
|
|
13
|
+
]>
|
|
14
|
+
<SkillDependencyContract {
|
|
15
|
+
collection = "SkillDependencies"
|
|
16
|
+
member = "SkillDependency"
|
|
17
|
+
refScheme = "resource"
|
|
18
|
+
targetKind = "SkillCapsule"
|
|
19
|
+
versionBinding = "exact"
|
|
20
|
+
}>
|
|
21
|
+
<IncludeContract {
|
|
22
|
+
collection = "Includes"
|
|
23
|
+
relation = "compiled-resource-selection"
|
|
24
|
+
dependencySemantics = false
|
|
25
|
+
}>
|
|
26
|
+
)>
|
|
27
|
+
)>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<SkillCapsule #example.resource_lifecycle.skill.resource_dsl apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
name = "example-resource-lifecycle-dsl"
|
|
3
|
+
lifecycle = "Stable"
|
|
4
|
+
description = "Shared resource DSL reference used by authoring operations."
|
|
5
|
+
} (
|
|
6
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
7
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
8
|
+
)>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<SkillCapsule #example.resource_lifecycle.skill.run apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
name = "example-resource-lifecycle-run"
|
|
3
|
+
lifecycle = "Active"
|
|
4
|
+
description = "Generic operations for running an authored resource."
|
|
5
|
+
} (
|
|
6
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
7
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
8
|
+
)>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Files And Bundles
|
|
2
|
+
|
|
3
|
+
## 内容为真源
|
|
4
|
+
|
|
5
|
+
kind 与 identity 来自文件根 tag 和 `#id`。目录名、文件名和 catalog 路径只是布局;扫描器不得通过后缀或目录名补写资源语义。
|
|
6
|
+
|
|
7
|
+
## 两种定义形态
|
|
8
|
+
|
|
9
|
+
- 单文件 definition:任意描述性 `.xnl` 文件名,文件内有一个语义根。
|
|
10
|
+
- 目录 bundle:入口固定为 `manifest.xnl`,域文件使用描述性 `.xnl` 文件名。
|
|
11
|
+
|
|
12
|
+
目录 bundle 示例:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
Functions/
|
|
16
|
+
PrepareData/
|
|
17
|
+
manifest.xnl # <Function #demo.resource_workflow.prepare_data ...>
|
|
18
|
+
instruction.md # CodeBinding/Instruction 引用的 material
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`manifest.xnl` 的根决定 bundle kind 与 identity。独立子域可以从 manifest 的 `()` 原样外提为同型域文件;外提不改变 logical refs。
|
|
22
|
+
|
|
23
|
+
## 单文件 forest
|
|
24
|
+
|
|
25
|
+
单文件默认只有一个语义根。仅当对应 `KindDefinition` 同时声明 `sourceShapes = ["single-file"]` 与 `documentCardinality = "many"` 时,同一个 `.xnl` authority 文件才可以包含多个并列根。
|
|
26
|
+
|
|
27
|
+
forest 的每个根是独立资源,必须使用同一 Kind,具有独立 `#id`,并通过该 Kind 的版本契约。`ResourcePackage`、catalog、KindDefinition 与目录 bundle 入口始终保持单根。
|
|
28
|
+
|
|
29
|
+
## Provenance 与 logical path
|
|
30
|
+
|
|
31
|
+
loader 为每个 normalized descriptor 附加只读 provenance:
|
|
32
|
+
|
|
33
|
+
- `documentUri`:加载 authority 文档的 canonical VFS URI;
|
|
34
|
+
- `logicalPath`:相对 package catalog root 的逻辑路径;
|
|
35
|
+
- `packageId`:从 `ResourcePackage #id` 派生;
|
|
36
|
+
- `resourceId`:来自 descriptor 根 `#id`。
|
|
37
|
+
|
|
38
|
+
这些字段由 loader 拥有,author 不在 descriptor 中重复配置。consumer 可以记录 provenance 用于诊断,但不得修改后反写 XNL。
|
|
39
|
+
|
|
40
|
+
## 扫描边界
|
|
41
|
+
|
|
42
|
+
- 默认目录入口仅为 `manifest.xnl`。
|
|
43
|
+
- `single-file` catalog 缺省扫描 root 下全部 `.xnl`;声明 `entry = "name.xnl"` 时只加载该文件,便于多个不同 Kind 共用一个物理目录。
|
|
44
|
+
- 非入口 `.xnl` 文件只能作为显式域/物料被入口引用,不能被重复注册为第二资源。
|
|
45
|
+
- 多根文档必须由 KindDefinition 显式授权;loader 不根据文件名或根数量猜测 forest 语义。
|
|
46
|
+
- catalog root 必须是 `vfs://` URI。
|
|
47
|
+
- resource-core 负责 URI 解析、边界检查和重复 identity 诊断;consumer 不自行扫描磁盘。
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Halfcode XNL Resource DSL
|
|
2
|
+
|
|
3
|
+
## 目录职责
|
|
4
|
+
|
|
5
|
+
- **holds**:halfcode resource package、catalog、KindDefinition、descriptor、mapping、URI 与文件组织的 XNL authoring 真源。
|
|
6
|
+
- **excludes**:parser/registry 实现(→`packages/resource-core/`)、consumer 归一化逻辑(→各 consumer package)、运行态数据与 BusinessObject/PageObject 尚未稳定的专用 API。
|
|
7
|
+
- **tier**:`stable`
|
|
8
|
+
- **promotes_from**:Codument track `define-xnl-resource-dsl` 的 proposal、design、behavior 与 modeling delta。
|
|
9
|
+
- **promotes_to**:资源 authoring 文件、loader/validator、consumer contract tests 与公开文档。
|
|
10
|
+
|
|
11
|
+
本目录定义 halfcode 资源的 XNL-native 语言。XNL 文档是可持久化语义真源;normalized descriptors、application assembly、发布制品和运行快照都是可重建投影,不得反向成为第二份 authoring 定义。
|
|
12
|
+
|
|
13
|
+
## 核心公理
|
|
14
|
+
|
|
15
|
+
一个节点的完整形态是:
|
|
16
|
+
|
|
17
|
+
```xnl
|
|
18
|
+
<Tag #id apiVersion="halfcode.resources/v1" version="1.0.0" { properties } ( unique-subdomains ) [ repeated-or-ordered-members ]>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
| 通道 | 唯一职责 | 资源 DSL 用法 |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `Tag` | 节点类别 | `ResourcePackage`、`KindDefinition`、`Function`、`ResourceMappings` 等资源 kind |
|
|
24
|
+
| `#id` | 节点身份 | 可跨容器引用的 FQN;不从文件名推断 |
|
|
25
|
+
| metadata 位 | 系统级版本 | `apiVersion`、`version` |
|
|
26
|
+
| `{}` | 无序业务属性 | lifecycle、description、kind、src、root 等标量或内联结构 |
|
|
27
|
+
| `()` | 每父节点唯一的命名子域 | `Catalogs`、`DescriptorContract`、`Instruction`、`CodeBinding` 等 |
|
|
28
|
+
| `[]` | 直接、有序或可重复事实 | catalog 条目、mapping 条目、includes 等 |
|
|
29
|
+
|
|
30
|
+
规则的重点是语义分配,不是把 XML tag/attribute 机械换一种括号。consumer 不得读取 parser-private 字段,也不得重建 `@_attribute` 一类 XML 对象形状。
|
|
31
|
+
|
|
32
|
+
## 权威文档
|
|
33
|
+
|
|
34
|
+
| 文档 | 回答的问题 |
|
|
35
|
+
|---|---|
|
|
36
|
+
| [language.md](language.md) | XNL 通道、身份、引用、声明式边界与 normalized projection。 |
|
|
37
|
+
| [documents.md](documents.md) | package、catalog、KindDefinition、descriptor、mapping 各自长什么样。 |
|
|
38
|
+
| [files.md](files.md) | 单文件/目录 bundle、`manifest.xnl`、logical path 与 provenance。 |
|
|
39
|
+
| [projections.md](projections.md) | 单包 tree、ordered layers、tombstone、typed dependency 与 revision 的 authority 边界。 |
|
|
40
|
+
| [skill-capsules.md](skill-capsules.md) | SkillCapsule version authority、sibling dependency、closure plan/apply 与 host 边界。 |
|
|
41
|
+
| [migration.md](migration.md) | XML authority 如何迁移,哪些做法被明确拒绝。 |
|
|
42
|
+
| [examples/](examples/) | 由当前 `xnl-core` parser 验证的规范实例。 |
|
|
43
|
+
|
|
44
|
+
KindDefinition 同时拥有资源版本契约:`currentApiVersion` 指向当前 authoring 版本,`supportedApiVersions` 列出可直接加载的兼容版本。版本转换由 `halfcode-compiler.xnl/kind-definition` 的代码侧 migration registry 执行,XNL 不承载可执行转换。成功加载的规范化 contract 可从 `ResourceTree.registry.kindDefinitions` 读取,consumer 无需再次解析 Kind XNL。
|
|
45
|
+
|
|
46
|
+
多个 package 的组合不产生新的 authoring authority。canonical loader 在同一次 raw-byte read 中产生 `LoadedResourceTree.contentIdentities`;`resolveEffectiveResourceContentIdentities()` 再从 exact effective layer 选择 authority identity 并合并 Kind owner 的显式 digest contributions。`EffectiveResourceRegistry` 和 `ResourceDependencySnapshot` 都是由已验证 XNL、显式 tombstone、typed edge 与 digest contribution 重建的只读投影;它们不得被序列化回 XNL 作为第二份事实源。完整规则见 [projections.md](projections.md)。
|
|
47
|
+
|
|
48
|
+
本目录自身也是 `Halfcode.ResourceDsl.Package@1.0.0`:XNL descriptors 只登记 canonical Markdown/XNL materials,不复制正文。`Halfcode.ResourceDsl.Skill.System` 编译为 `sys-halfcode-resource-dsl@1.0.0`,供离线消费者按需加载这些文档;每个 capsule 的 `references/.halfcode/provenance.json` 绑定 source FQN/apiVersion/version、生成协议和 payload digests。
|
|
49
|
+
|
|
50
|
+
## 暂缓边界
|
|
51
|
+
|
|
52
|
+
BusinessObject 与 PageObject 的通用外壳仍服从本目录的 `Tag/#id/metadata/{}/()/[]` 公理,但以下内容在当前版本中**刻意不定义**:
|
|
53
|
+
|
|
54
|
+
- 专用字段与 operation/mutation/action 模型;
|
|
55
|
+
- application assembly 的二者专用 public types;
|
|
56
|
+
- 参考实现正在重构的 PageObject API 映射;
|
|
57
|
+
- 二者最终 KindDefinition descriptor contract。
|
|
58
|
+
|
|
59
|
+
这些内容由 mission `halfcode-compiler-xnl-migration` 的 `LATE-BO-PO` group 在重新观察参考实现后补充。
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Language Axioms
|
|
2
|
+
|
|
3
|
+
## 身份与分类
|
|
4
|
+
|
|
5
|
+
- 根 tag 是资源 kind;PascalCase 保留给 DSL 结构节点。
|
|
6
|
+
- 可跨容器复用的资源在 `#id` 使用点分 FQN,例如 `#demo.resource_workflow.prepare_data`。
|
|
7
|
+
- 文件路径只负责物理布局,不决定 kind 或 identity。移动文件不改变 `#id`。
|
|
8
|
+
- `apiVersion` 与 `version` 写在 metadata 位;title、lifecycle、description 等业务数据若属于该 Kind,则写入 `{}`。
|
|
9
|
+
- 通用资源边界只要求根 `#id` 与 `apiVersion`。`lifecycle`、`description` 的存在性和语义由具体 Kind 或 consumer contract 决定,resource-core 不提供虚假默认值。
|
|
10
|
+
- 每个 KindDefinition 显式声明 `currentApiVersion` 与 `supportedApiVersions`;loader 不猜测未知版本,也不自动执行迁移。具体系统通过公开 `ResourceMigrationRegistry` 注册纯转换函数,得到唯一版本链后再加载目标文档。
|
|
11
|
+
- XNL authority 默认单根。只有 source shape 严格为 `single-file` 的 Kind 可以通过 `documentCardinality = "many"` 授权同 Kind forest;每个顶层根仍是独立资源,`[]` 继续只表达节点内部的重复子项。
|
|
12
|
+
- 静态描述数据由所属节点自持,不寄存在另一域再引用回来。
|
|
13
|
+
|
|
14
|
+
## 子域与重复事实
|
|
15
|
+
|
|
16
|
+
`()` 表示父节点拥有的唯一子域概念。同一父节点的 `()` 中,同名 tag 只能出现一次。重复条目由复数子域的 `[]` 承载:
|
|
17
|
+
|
|
18
|
+
```xnl
|
|
19
|
+
<ResourcePackage #demo.package (
|
|
20
|
+
<Catalogs [
|
|
21
|
+
<Catalog #functions { kind = "Function" root = "vfs://./Functions/" entry = "manifest.xnl" }>
|
|
22
|
+
<Catalog #skills { kind = "SkillCapsule" root = "vfs://./Skills/" entry = "manifest.xnl" }>
|
|
23
|
+
]>
|
|
24
|
+
)>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
直接、有序或可重复的事实进入 `[]`。禁止为了凑层级增加没有领域语义的 `Nodes`、`Items` 或 `Block` 包装;复数容器必须确实代表一个唯一子域概念。
|
|
28
|
+
|
|
29
|
+
## URI 与代码引用
|
|
30
|
+
|
|
31
|
+
所有跨节点/文件引用都是引号字符串 URI:
|
|
32
|
+
|
|
33
|
+
| 目标 | canonical 形态 | 示例 |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| 当前 bundle 相对文件 | `vfs://./<path>` | `vfs://./instruction.md` |
|
|
36
|
+
| workspace 文件 | `vfs://@/<path>` | `vfs://@/apps/demo/src/procedures.ts` |
|
|
37
|
+
| TypeScript 导出 | `vfs://...#<ExportName>` | `vfs://@/apps/demo/src/procedures.ts#prepareProcedure` |
|
|
38
|
+
| 规范资源 identity | `resource://<FQN>` | `resource://demo.resource_workflow.prepare_data` |
|
|
39
|
+
| 当前容器 id | `<domain>://#<id>` | `catalog://#functions` |
|
|
40
|
+
|
|
41
|
+
代码引用必须包含 export fragment。XNL 只保存声明式 binding;函数、闭包、表达式字符串和 handler object 不得内嵌到 XNL。执行代码的协议和副作用由 runtime/component contract 定义,不属于 parser。
|
|
42
|
+
|
|
43
|
+
## Authoring 与 projection
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
XNL authority document
|
|
47
|
+
-> xnl-core node tree
|
|
48
|
+
-> validated normalized resource descriptor + provenance
|
|
49
|
+
-> registry / mapping / application assembly projections
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- authority:磁盘上的 `.xnl` 文档;唯一可编辑事实。
|
|
53
|
+
- parser tree:语法投影,只由 resource-core loader 消费。
|
|
54
|
+
- normalized descriptor:稳定领域边界,携带 `resourceId`、`kind`、metadata、members、subdomains、`documentUri`、`logicalPath`;Kind-owned 可选属性保持存在或缺失的原始事实。
|
|
55
|
+
- consumer projection:可重建;不得暴露 parser node 内部字段,也不得反写 authority。
|
|
56
|
+
|
|
57
|
+
package provenance 从 package manifest、document URI 与 logical path 派生。descriptor 不重复保存一份可由路径计算的 package identity。
|
|
58
|
+
|
|
59
|
+
## 声明式限制
|
|
60
|
+
|
|
61
|
+
- 一个 bundle 内的配置只使用 XNL,不引入 JSON/XML/YAML 第二配置入口。
|
|
62
|
+
- 动态代码保存在 `.ts` 等外部文件,通过 `vfs://...#Export` 挂接。
|
|
63
|
+
- 不允许将 XML attributes 转换成 `@_name` 或其他前缀键后暴露给 consumer。
|
|
64
|
+
- 不允许根据文件名猜测 kind;文件内容的 tag 才是 authority。
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<ResourcePackage #Halfcode.ResourceDsl.Package apiVersion="halfcode.resources/v1" version="1.0.0" {
|
|
2
|
+
lifecycle = "Stable"
|
|
3
|
+
description = "Canonical Halfcode Resource DSL documentation and consumer Skill resources."
|
|
4
|
+
} (
|
|
5
|
+
<Catalogs [
|
|
6
|
+
<Catalog #KindDefinitions { kind = "KindDefinition" shape = "directory" root = "vfs://./KindDefinitions/" entry = "manifest.xnl" }>
|
|
7
|
+
<Catalog #WikiPages { kind = "WikiPage" shape = "directory" root = "vfs://./WikiPages/" entry = "manifest.xnl" }>
|
|
8
|
+
<Catalog #SkillCapsules { kind = "SkillCapsule" shape = "directory" root = "vfs://./SkillCapsules/" entry = "manifest.xnl" }>
|
|
9
|
+
]>
|
|
10
|
+
)>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# XML To XNL Migration
|
|
2
|
+
|
|
3
|
+
## 迁移原则
|
|
4
|
+
|
|
5
|
+
迁移单位是“资源语义”,不是 tag/attribute 的逐字符替换:
|
|
6
|
+
|
|
7
|
+
| XML-era 表达 | XNL authority |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 根 element 名 | 根 tag(resource kind) |
|
|
10
|
+
| `Id`/`Name` 等身份 attribute | 根 `#id` FQN;display name 若存在则留在 `{}` |
|
|
11
|
+
| `Version`/schema version | metadata 位的 `version`/`apiVersion` |
|
|
12
|
+
| 普通 attributes | `{}` 中归节点所有的属性 |
|
|
13
|
+
| 唯一 child section | `()` 中的唯一子域 |
|
|
14
|
+
| 重复 child elements | 父 `[]` 或复数子域的 `[]` |
|
|
15
|
+
| 文件路径/code export | 引号字符串 `vfs://...#Export` |
|
|
16
|
+
| parser `@_foo`/XmlObject | 不迁移;在 normalized descriptor 边界消失 |
|
|
17
|
+
|
|
18
|
+
## 顺序
|
|
19
|
+
|
|
20
|
+
1. 用 `KindDefinition` 明确 kind contract。
|
|
21
|
+
- 声明 `currentApiVersion` 与 `supportedApiVersions`。
|
|
22
|
+
- 对不可直接兼容的历史版本,在代码侧 `ResourceMigrationRegistry` 注册唯一纯转换链;XNL 不内嵌 transformer。
|
|
23
|
+
2. 将 package/catalog authority 改为 XNL。
|
|
24
|
+
3. 逐个资源按领域语义分配 `{}`、`()`、`[]`,保留稳定 `#id`。
|
|
25
|
+
4. 将路径与代码引用规范为 VFS URI。
|
|
26
|
+
5. 通过 resource-core 得到 normalized descriptor,再迁移 consumer。
|
|
27
|
+
6. 删除兼容 XML 与 `fast-xml-parser`,以产品 XML inventory 清零作为关闭条件。
|
|
28
|
+
|
|
29
|
+
## 明确拒绝
|
|
30
|
+
|
|
31
|
+
- 在 TypeScript 中保留 `XmlObject`、`@_` 属性前缀或 XML child-array 作为公开类型。
|
|
32
|
+
- 同一资源同时维护 XML 与 XNL 两份长期 authority。
|
|
33
|
+
- 根据目录名/文件名猜 kind 或 identity。
|
|
34
|
+
- 在 XNL 内嵌函数、闭包或可执行表达式字符串。
|
|
35
|
+
- 用无语义的 wrapper 模拟 XML 层级。
|
|
36
|
+
- 在 BusinessObject/PageObject API 尚未稳定时提前设计二者的专用 XNL schema。
|
|
37
|
+
|
|
38
|
+
## 暂时兼容
|
|
39
|
+
|
|
40
|
+
后续实现 track 可以在内部短期 dual-read,用于小步迁移和 characterization test;兼容层不得进入 public API,并必须在 `close-xnl-only-product-surface` track 删除。
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Resource Projections and Dependency Authority
|
|
2
|
+
|
|
3
|
+
## Authority map
|
|
4
|
+
|
|
5
|
+
资源 authoring、组合与运行闭包是三个不同层次,不能互相替代:
|
|
6
|
+
|
|
7
|
+
| Fact | Authority owner | Halfcode projection |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| package、Catalog、KindDefinition、resource descriptor | XNL ResourcePackage | `LoadedResourceTree extends ResourceTree` |
|
|
10
|
+
| layer precedence | 调用方提供的有序 `ResourceLayerInput[]` | `EffectiveResourceRegistry.layers` |
|
|
11
|
+
| suppression | 调用方显式提供的 `ResourceTombstone` | effective/tombstone/shadow provenance |
|
|
12
|
+
| Kind-specific dependency semantics | 对应 Kind owner 或 consumer | `ResourceDependencyEdge[]` |
|
|
13
|
+
| XNL authority bytes | canonical loader 的同一次 raw-byte read | `LoadedResourceTree.contentIdentities` |
|
|
14
|
+
| Kind-specific material bytes | Kind owner 提供的显式 digest contribution | effective `ResourceContentIdentity` |
|
|
15
|
+
| roots 与 dependency closure | 调用方的显式 roots 加 typed edges | `ResourceDependencySnapshot` |
|
|
16
|
+
|
|
17
|
+
`ResourceTree` 是单个已验证 package 的规范化结果。`EffectiveResourceRegistry` 只是多个 tree 的确定性只读投影;它会 deep-clone/freeze record、metadata、node/value 与 KindDefinition facts,避免调用方之后修改输入而改变既有投影,但不会原地冻结或改写旧 `ResourceTree`。`ResourceDependencySnapshot` 又是某组 roots 在一个 content-sensitive registry revision 上的冻结闭包。两种投影都可由 authority facts 重建,不得反写任一 XNL package,也不得成为第二份 authoring 真源。
|
|
18
|
+
|
|
19
|
+
Snapshot builder 只接受同一 resource-core runtime 中由 `composeLayeredResourceRegistry()` 返回的 canonical immutable registry。手工构造、浅拷贝或改写 revision 字段的结构相似对象会 fail closed;需要跨进程恢复时,应从 XNL packages、ordered layers 与 tombstones 重新组合。Snapshot 会复制并冻结自己的 origin facts,不共享可变调用方引用。
|
|
20
|
+
|
|
21
|
+
## Ordered named layers
|
|
22
|
+
|
|
23
|
+
layer 只包含一个不透明、稳定的 `id` 和一个已验证 `ResourceTree`。数组从低 precedence 到高 precedence 排列,后一个 layer 优先。Halfcode 不保留特殊 layer 名称,不根据名称重排,也不拥有任何产品安装目录或机器路径策略;实际 roots 由 consumer 在调用 resource-core 之前绑定。
|
|
24
|
+
|
|
25
|
+
组合规则是:
|
|
26
|
+
|
|
27
|
+
1. 同一 `resourceId`、同一 kind 的高层资源成为 effective;低层 origin 留在 `shadowed`。
|
|
28
|
+
2. 同一 identity 跨 kind,或同一 resource kind 的规范化 KindDefinition contract 不兼容,组合失败并返回稳定 diagnostics。
|
|
29
|
+
3. 高层没有某个资源只表示“未提供”,绝不表示删除。
|
|
30
|
+
4. 删除语义必须通过 `ResourceTombstone { resourceId, expectedKind?, reason? }` 显式声明;tombstone origin 与历史保留在 projection 中。
|
|
31
|
+
5. `byKind` 只包含 effective resources;完整 effective、shadow 与 tombstone 证据由 `byId` 保存。
|
|
32
|
+
6. `documentUri` 必须是与安全相对 `logicalPath` 一致的 canonical `vfs://@/` URI;非 loader 来源的绝对机器路径或 traversal provenance 会 fail closed。
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import {
|
|
36
|
+
composeLayeredResourceRegistry,
|
|
37
|
+
type ResourceLayerInput,
|
|
38
|
+
} from "halfcode-compiler.xnl/resource-core"
|
|
39
|
+
|
|
40
|
+
declare const lowerPackage: ResourceLayerInput["tree"]
|
|
41
|
+
declare const higherPackage: ResourceLayerInput["tree"]
|
|
42
|
+
|
|
43
|
+
const registry = composeLayeredResourceRegistry({
|
|
44
|
+
layers: [
|
|
45
|
+
{ id: "base", tree: lowerPackage },
|
|
46
|
+
{
|
|
47
|
+
id: "override",
|
|
48
|
+
tree: higherPackage,
|
|
49
|
+
tombstones: [{ resourceId: "demo.retired", expectedKind: "Function" }],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
示例中的名字仅用于展示调用顺序,不携带预定义语义。consumer 可以选择任何稳定 id;改变数组顺序才会改变 precedence。
|
|
56
|
+
|
|
57
|
+
## Explicit content identity
|
|
58
|
+
|
|
59
|
+
canonical loader 对每个 XNL authority 文件只读取一次 raw bytes:同一次读取同时用于 fatal UTF-8 decode、XNL parse 和 SHA-256。成功加载后返回 additive `LoadedResourceTree`;其 `contentIdentities` 精确覆盖 `registry.byKind` 的业务 resources,不包含 package manifest 或 KindDefinition。multi-root document 的 roots 共享同一文件级 `authorityDigest`,但各自的 `resourceId` 和 `contentDigest` 独立。
|
|
60
|
+
|
|
61
|
+
`ResourceTree` 仍是兼容父接口,手工 structural tree 仍可参与 generic layer composition。只有 canonical loader 返回并由当前 runtime 登记的 `LoadedResourceTree` 才能进入 `resolveEffectiveResourceContentIdentities()`。projector exact 核对 registry 的 layer id、顺序、package 与 effective origin,从每个 effective layer 选择 loader identity;shadowed non-effective resource 与 tombstone 不进入结果。Kind owner 再把 prompt、schema、instruction 等 material 作为带稳定 `key`、`digest` 和可选 `sourceUri` 的 contribution 显式提供。
|
|
62
|
+
|
|
63
|
+
`createResourceContentIdentity()` 按 UTF-16 code-unit key 顺序 canonicalize contributions,并拒绝任何重复 key;即使 digest 相同,重复或不同 provenance 也不是可静默折叠的合法事实。snapshot builder 会对全部 effective resources 重新规范化 authority/contribution facts、重算 `contentDigest` 并核对 claim;它不会只验证 roots 可达的 identity,也不会信任调用方构造的对象。`sourceUri` 是 provenance,不允许机器绝对路径进入 content revision;调用方应使用 Resource DSL 定义的逻辑 URI。
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import {
|
|
67
|
+
composeLayeredResourceRegistry,
|
|
68
|
+
loadResourceTree,
|
|
69
|
+
resolveEffectiveResourceContentIdentities,
|
|
70
|
+
} from "halfcode-compiler.xnl/resource-core"
|
|
71
|
+
|
|
72
|
+
declare const lowerPackageRoot: string
|
|
73
|
+
declare const higherPackageRoot: string
|
|
74
|
+
declare const contributions: Parameters<typeof resolveEffectiveResourceContentIdentities>[0]["contributions"]
|
|
75
|
+
|
|
76
|
+
const lowerPackage = await loadResourceTree({ rootDir: lowerPackageRoot })
|
|
77
|
+
const higherPackage = await loadResourceTree({ rootDir: higherPackageRoot })
|
|
78
|
+
const registry = composeLayeredResourceRegistry({
|
|
79
|
+
layers: [
|
|
80
|
+
{ id: "lower", tree: lowerPackage },
|
|
81
|
+
{ id: "higher", tree: higherPackage },
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const identities = resolveEffectiveResourceContentIdentities({
|
|
86
|
+
registry,
|
|
87
|
+
layers: [
|
|
88
|
+
{ id: "lower", tree: lowerPackage },
|
|
89
|
+
{ id: "higher", tree: higherPackage },
|
|
90
|
+
],
|
|
91
|
+
contributions,
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
示例中的 `lowerPackageRoot`、`higherPackageRoot` 与 `contributions` 由 consumer 在调用边界绑定。Halfcode 不定义机器安装目录或 layer precedence policy,也不会重复读取 XNL authority。projector 的结果可直接传给 snapshot builder;snapshot builder 仍不执行隐藏 IO。
|
|
96
|
+
|
|
97
|
+
## Typed dependency closure
|
|
98
|
+
|
|
99
|
+
依赖的字段语义属于 Kind owner。它负责把自己的 descriptor contract 转成 `ResourceDependencyEdge { fromResourceId, toResourceId, relation, declaredBy }`。resource-core 只校验 endpoint、从显式 roots 沿这些边遍历、拒绝可达 cycle,并生成稳定排序的 snapshot。
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import {
|
|
103
|
+
buildResourceDependencySnapshot,
|
|
104
|
+
type EffectiveResourceRegistry,
|
|
105
|
+
type ResourceDependencyEdge,
|
|
106
|
+
type ResourceContentIdentity,
|
|
107
|
+
} from "halfcode-compiler.xnl/resource-core"
|
|
108
|
+
|
|
109
|
+
declare const registry: EffectiveResourceRegistry
|
|
110
|
+
declare const workflowIdentity: ResourceContentIdentity
|
|
111
|
+
declare const schemaIdentity: ResourceContentIdentity
|
|
112
|
+
|
|
113
|
+
const edges: readonly ResourceDependencyEdge[] = [{
|
|
114
|
+
fromResourceId: workflowIdentity.resourceId,
|
|
115
|
+
toResourceId: schemaIdentity.resourceId,
|
|
116
|
+
relation: "uses-schema",
|
|
117
|
+
declaredBy: "WorkflowKindDefinition",
|
|
118
|
+
}]
|
|
119
|
+
|
|
120
|
+
const snapshot = buildResourceDependencySnapshot({
|
|
121
|
+
registry,
|
|
122
|
+
roots: [workflowIdentity.resourceId],
|
|
123
|
+
edges,
|
|
124
|
+
contentIdentities: new Map([
|
|
125
|
+
[workflowIdentity.resourceId, workflowIdentity],
|
|
126
|
+
[schemaIdentity.resourceId, schemaIdentity],
|
|
127
|
+
]),
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
普通文本、instruction 或 `ResourceNode` property 即使看起来像资源 URI,只要 Kind owner 没有提供 typed edge,就不会进入 closure。resource-core 不遍历任意字符串、不匹配自然语言关键词,也不猜测引用字段。
|
|
132
|
+
|
|
133
|
+
## Deterministic revisions
|
|
134
|
+
|
|
135
|
+
- content revision 覆盖 resource identity、authority digest 与按 key 排序的 material digests。
|
|
136
|
+
- `compositionRevision` 覆盖显式 layer 顺序、effective identity/presence、shadow/tombstone facts、选定 KindDefinition 的 authority `resourceId`/兼容 contract 与 canonical `documentUri/logicalPath` provenance;`EffectiveResourceRegistry.revision` 是它的精确兼容别名。ResourceRecord descriptor/node/metadata bytes 不进入该摘要,而由显式 content identity 负责。不同 definition identity 不会自行把相同 normalized Kind contract 变成冲突。
|
|
137
|
+
- snapshot 的 `registryRevision` 覆盖 `compositionRevision` 与全部 effective resource 的已验证 content revisions,包括当前 roots 不可达的资源。
|
|
138
|
+
- `snapshotRevision` 覆盖显式 root 顺序、可达资源 content revisions、参与闭包的 typed edges 与 `registryRevision`。
|
|
139
|
+
- revisions 使用带算法前缀的 SHA-256 形式;逻辑 provenance 在 projection 中保留,机器绝对路径不得进入摘要。
|
|
140
|
+
- canonical object key、resource、kind、edge 与 contribution 排序固定使用 ECMAScript UTF-16 code-unit 顺序,不依赖 locale、ICU、文件枚举或 Map 插入顺序。
|
|
141
|
+
|
|
142
|
+
缺失 endpoint、缺失 content identity、identity-kind/KindDefinition conflict、矛盾 digest 或 dependency cycle 都会 fail closed;调用方不会收到看似完整的 partial snapshot。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# SkillCapsule Dependencies And Distribution
|
|
2
|
+
|
|
3
|
+
## Identity authority
|
|
4
|
+
|
|
5
|
+
新的 `SkillCapsule` descriptor 由 XNL 根节点独占 FQN、consumer-facing `name`、`apiVersion` 与 `version`。`SKILL.metadata.yaml` 只保存 title/description 等呈现字段,不重复 name/version;assembly 会把 canonical XNL name/version 投影给模板。若 descriptor 已声明 `name` 而 YAML 仍重复该字段,assembly 在 compiler 写入前以 `SKILL_CAPSULE_NAME_DUPLICATE` 失败。历史 descriptor 未声明 XNL name 时,既有 YAML name 与 FQN 尾段 fallback 继续兼容;新资源不得采用该兼容路径。
|
|
6
|
+
|
|
7
|
+
XNL `version` 也是 capsule identity 与 dependency binding 的唯一 version authority。历史 YAML 若仍带 `version`,必须与 XNL 严格相等,否则 assembly 以 `SKILL_CAPSULE_VERSION_CONFLICT` 失败。
|
|
8
|
+
|
|
9
|
+
```xnl
|
|
10
|
+
<SkillCapsule #example.resource_lifecycle.skill.authoring
|
|
11
|
+
apiVersion="halfcode.resources/v1"
|
|
12
|
+
version="1.0.0" {
|
|
13
|
+
name = "example-resource-authoring"
|
|
14
|
+
description = "Generic resource authoring operations."
|
|
15
|
+
} (
|
|
16
|
+
<SkillMetadata { href = "vfs://./SKILL.metadata.yaml" format = "yaml" }>
|
|
17
|
+
<Template { href = "vfs://./SKILL.template.ejs" format = "ejs" }>
|
|
18
|
+
)>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
对应 YAML 只保存呈现字段:
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
title: Example Resource Authoring
|
|
25
|
+
description: Generic resource authoring operations.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## `SkillDependencies` 与 `Includes`
|
|
29
|
+
|
|
30
|
+
两种关系不可互换,也不做名称或文本推断:
|
|
31
|
+
|
|
32
|
+
- `SkillDependencies/SkillDependency` 声明同一个 `ApplicationAssembly.byFqn` resource universe 中的 sibling `SkillCapsule`。`ref` 必须是 `resource://<FQN>`,目标 kind 必须是 `SkillCapsule`,`version` 是必填的精确 binding;当前版本不解释 semver range。
|
|
33
|
+
- `Includes/Include` 选择要编入当前 capsule 的 Function、PromptFragment 等普通资源。即便一个 Include 写了 `kind = "SkillCapsule"`,planner 也不会把它提升为 sibling dependency。
|
|
34
|
+
|
|
35
|
+
```xnl
|
|
36
|
+
<SkillDependencies [
|
|
37
|
+
<SkillDependency {
|
|
38
|
+
ref = "resource://example.resource_lifecycle.skill.resource_dsl"
|
|
39
|
+
version = "1.0.0"
|
|
40
|
+
}>
|
|
41
|
+
]>
|
|
42
|
+
<Includes [
|
|
43
|
+
<Include {
|
|
44
|
+
kind = "PromptFragment"
|
|
45
|
+
ref = "resource://example.resource_lifecycle.prompt.authoring_prelude"
|
|
46
|
+
}>
|
|
47
|
+
]>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
缺失目标、错误 kind、重复 dependency、精确版本不匹配和 cycle 都会 fail closed。依赖解析只读取既有 application assembly,不创建第二份 catalog 或 scanner。
|
|
51
|
+
|
|
52
|
+
## 四 Skill canonical topology
|
|
53
|
+
|
|
54
|
+
规范示例使用与具体产品无关的四个 Skill:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
resource DSL -> authoring -> devops/root
|
|
58
|
+
run -> devops/root
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `devops/root` 显式依赖 `authoring` 与 `run`;
|
|
62
|
+
- `authoring` 显式依赖共享 `resource DSL`;
|
|
63
|
+
- `run` 与 `resource DSL` 没有 sibling dependency。
|
|
64
|
+
|
|
65
|
+
完整 descriptor 分别位于 [skill-capsule-devops.xnl](examples/skill-capsule-devops.xnl)、[skill-capsule-authoring.xnl](examples/skill-capsule-authoring.xnl)、[skill-capsule-run.xnl](examples/skill-capsule-run.xnl) 和 [skill-capsule-resource-dsl.xnl](examples/skill-capsule-resource-dsl.xnl)。可加载、可规划的 bundle fixture 位于 `apps/demo-resource-workflow-authoring/resources-xnl/SkillCapsules/Topology*`。所有 consumer name 与 version 都由 XNL 声明,dependency 绑定 `1.0.0`,YAML 不重复 identity 字段。
|
|
66
|
+
|
|
67
|
+
## Deterministic plan 与 atomic apply
|
|
68
|
+
|
|
69
|
+
`planSkillCapsuleDistribution` 与 `applySkillCapsuleDistributionPlan` 是两个独立阶段:
|
|
70
|
+
|
|
71
|
+
1. planner 从显式 roots 解析传递闭包,按固定 code-unit 顺序生成 dependency-first topology;
|
|
72
|
+
2. planner 读取所有 generated/mapped bytes,并将 canonical bytes 保存为不可变、可序列化的 `contentBase64` authority;兼容字段 `content` 每次读取只返回新的 defensive copy;
|
|
73
|
+
3. planner 对所有会进入 SKILL/reference/callable bytes 的资源集合按 FQN 使用固定 UTF-16 code-unit comparator 排序,并对完整 closure 做重复 output name、相同 target 与文件/目录 prefix collision preflight;
|
|
74
|
+
4. plan 保存 versioned content/capsule/closure digest,且不含绝对路径、时间戳或函数对象;plan 成功或失败都不写目标 root;
|
|
75
|
+
5. applier 先 fail-closed 校验非空 roots、root 可达的完整闭包、canonical base64 与全部 digest,再在 caller 提供的 `outputRoot` 同父目录 stage、readback,以 backup/rename/rollback 成组切换。
|
|
76
|
+
|
|
77
|
+
每个 planned capsule 还必须包含固定路径 `references/.halfcode/provenance.json`。该文件由 compiler 生成,不由模板维护;它记录 `halfcode.skill-provenance/v1` format、`halfcode.skill-distribution/v1` generator、SkillCapsule XNL 的 FQN/apiVersion/version,以及除自身以外全部 payload files 的 canonical path/content digest。manifest 自身作为普通 planned file 进入 capsule/closure digest,因此不需要自引用摘要。applier 会在任何目标写入前从 plan 重建并 exact 校验这些 facts。
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const plan = await planSkillCapsuleDistribution({
|
|
81
|
+
assembly,
|
|
82
|
+
rootSkillFqns: ["example.resource_lifecycle.skill.devops"],
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
await applySkillCapsuleDistributionPlan(plan, { outputRoot })
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Halfcode 只拥有通用 resource dependency、plan 与 atomic apply contract;目标 root、安装位置、生命周期阶段和升级策略都由 caller/host 决定。compiler 不推导这些 policy,也不把它们写进资源 authority。
|
|
89
|
+
|
|
90
|
+
## Consumer Resource DSL Skill
|
|
91
|
+
|
|
92
|
+
`docs/resource-dsl/manifest.xnl` 将本目录的 canonical 文档登记为 ResourcePackage/WikiPage resources,并声明 `Halfcode.ResourceDsl.Skill.System`。compiler 从这些原始文档生成 `sys-halfcode-resource-dsl@1.0.0` 的 references;`SKILL.md` 只提供渐进加载顺序,不复制规范正文,也不包含仓库维护命令或 host 安装操作。仓库维护者继续使用 `skills/framework-resource-dsl`,两者职责不可互换。
|
|
93
|
+
|
|
94
|
+
既有 `compileSkillCapsule`、`compileResourceSkillCapsule` 与 `SkillCapsulePlan` 保持兼容。新 planner/applier 和类型从 package root 及 `halfcode-compiler.xnl/skill-capsule` additive 导出。
|