@praxis-ai/praxis 0.1.5 → 0.1.6

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.
@@ -29,6 +29,8 @@ import { buildMcpServerProfilesFromManifest, createMcpApplicationStateView, crea
29
29
  export { PromptPack, PraxisAgent, PraxisAgentArchetype, STATE_PLANE_STANDARD_CONTROLS, append, compileAgent, endpoint, harness, inspectAgentManifest, loop, mainLoop, markdown, markdownFile, model, modelFleet, overwrite, policy, prepend, replaceLastLines, sandbox, session, statePlane, storage, tool, toolPolicies, tools, validateAgentManifest, type AgentCompileErrorCode, type AgentCompileResult, type AgentIdentity, type AgentManifest, type AgentManifestInspection, type AgentManifestValidationResult, type BaseToolPolicyDecision, type BaseToolPolicyMatrixSpec, type BaseToolPolicyProfile, type BaseToolPolicyRisk, type BaseToolPolicyRule, type HarnessSpec, type FrameworkCoreContractSpec, type LoopSpec, type MainLoopSpec, type ModelEndpointSpec, type ModelFleetSpec, type ModelSpec, type PolicySpec, type PraxisAgentClass, type PraxisAgentInput, type PromptMaterialSource, type PromptPackSpec, type PromptPatchSpec, type SandboxSpec, type SandboxIsolationLevel, type SandboxMountPolicy, type SandboxNetworkRuntimePolicy, type SandboxPlatformSupport, type SandboxPlatformSupportStatus, type SandboxProcessPolicy, type SandboxProviderFamily, type SessionSpec, type StatePlaneSpec, type StorageSpec, type ToolSpec, type ToolPolicyCustomInput, } from "../runtimeImplementation/runtimeAgentManifest.js";
30
30
  export { buildMcpServerProfilesFromManifest, createMcpApplicationStateView, createFileMcpPlusProfileStore, createFileMcpPlusSkillStore, createInMemoryMcpPlusOverlayStore, createInMemoryMcpPlusProfileStore, createInMemoryMcpPlusSkillStore, mcp, planMcpHarnessExposure, };
31
31
  export type { McpApplicationServerView, McpApplicationServerInput, McpApplicationStateView, McpHarnessExposurePlan, McpHarnessModuleSpec, McpHarnessServerMode, McpHarnessServerSpec, McpPlusLearnedProfile, McpPlusApplicationServerInput, McpPlusOverlayStore, McpPlusOverlayStoreKey, McpPlusProfileProposal, McpPlusProfileStore, McpPlusProfileStoreKey, McpPlusRuntimeOverlay, McpPlusSkillNote, McpPlusSkillStore, McpTransportSpec, } from "../runtimeImplementation/runtime.mcpPlane/index.js";
32
+ export { adviseSkillPromotion, createFileSkillPlaneStore, createInMemorySkillPlaneStore, createSkillWriteProposal, loadSkillHeadsFromSource, loadSkillHeadsFromSources, renderSkillIndexMaterial, skill, } from "../runtimeImplementation/runtime.skillPlane/index.js";
33
+ export type { SkillBody, SkillHead, SkillPlaneBodyLoadPolicy, SkillPlaneIndexPolicy, SkillPlaneLifecyclePolicy, SkillPlaneModuleSpec, SkillPlanePromotionState, SkillPlaneSourceResolutionInput, SkillPlaneScope, SkillPlaneStore, SkillSourceSpec, SkillPromotionAdvice, SkillWriteProposal, } from "../runtimeImplementation/runtime.skillPlane/index.js";
32
34
  export { createMemoryPlane, memoryPlane, };
33
35
  export type { MemoryArtifactRef, MemoryIndexStatus, MemoryLayout, MemoryPlane, MemoryPlaneOptions, MemoryPolicyRisk, MemoryProfile, MemoryPromptGuide, MemoryReindexResult, MemoryRiskMetadata, MemoryScope, MemorySearchGuide, MemorySearchRequest, MemorySourceType, } from "../memory_managementPool/index.js";
34
36
  export { capabilities, capability, createProvisionPlan, dependencies, dependencyAuthoring, provisionRuntimeDescriptor, type CapabilityFallbackSpec, type CapabilityInput, type CapabilityKind, type CapabilityPolicySpec, type CapabilityReadiness, type CapabilitySpec, type CodeIntelligenceCapabilityInput, type ProvisionPlan, type SandboxCapabilityInput, } from "../runtimeImplementation/runtime.provisionPlane/index.js";
@@ -670,6 +672,22 @@ export declare const praxis: Readonly<{
670
672
  sqlite(input?: Omit<import("../runtimeImplementation/runtimeAgentManifest.js").StorageSpec, "kind">): import("../runtimeImplementation/runtimeAgentManifest.js").StorageSpec;
671
673
  raxWorkspace(input?: Omit<import("../runtimeImplementation/runtimeAgentManifest.js").StorageSpec, "kind">): import("../runtimeImplementation/runtimeAgentManifest.js").StorageSpec;
672
674
  };
675
+ skill: {
676
+ readonly directory: (directoryPath: string, input?: {
677
+ scope?: import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneScope;
678
+ }) => import("../runtimeImplementation/runtime.skillPlane/index.js").SkillSourceSpec;
679
+ readonly package: (packageName: string, input?: {
680
+ scope?: import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneScope;
681
+ }) => import("../runtimeImplementation/runtime.skillPlane/index.js").SkillSourceSpec;
682
+ readonly inline: (heads: readonly import("../runtimeImplementation/runtime.skillPlane/index.js").SkillHead[]) => import("../runtimeImplementation/runtime.skillPlane/index.js").SkillSourceSpec;
683
+ readonly module: (input?: {
684
+ sources?: readonly import("../runtimeImplementation/runtime.skillPlane/index.js").SkillSourceSpec[];
685
+ indexPolicy?: Partial<import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneIndexPolicy>;
686
+ bodyLoadPolicy?: Partial<import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneBodyLoadPolicy>;
687
+ lifecycle?: Partial<import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneLifecyclePolicy>;
688
+ metadata?: Readonly<Record<string, unknown>>;
689
+ }) => import("../runtimeImplementation/runtime.skillPlane/index.js").SkillPlaneModuleSpec;
690
+ };
673
691
  memory: Readonly<{
674
692
  create: typeof createMemoryPlane;
675
693
  initialize: (options?: import("../memory_managementPool/types.js").MemoryPlaneOptions) => Promise<import("../memory_managementPool/types.js").MemoryIndexStatus>;
@@ -32,8 +32,10 @@ import { createObservationMaterial, } from "../executionEngine/coreLogic/observa
32
32
  import { runtimeAuth, } from "../runtimeImplementation/runtime.authPlane/index.js";
33
33
  import { createMemoryPlane, memoryPlane, } from "../memory_managementPool/index.js";
34
34
  import { buildMcpServerProfilesFromManifest, createMcpApplicationStateView, createFileMcpPlusProfileStore, createFileMcpPlusSkillStore, createInMemoryMcpPlusOverlayStore, createInMemoryMcpPlusProfileStore, createInMemoryMcpPlusSkillStore, mcp, planMcpHarnessExposure, } from "../runtimeImplementation/runtime.mcpPlane/index.js";
35
+ import { skill, } from "../runtimeImplementation/runtime.skillPlane/index.js";
35
36
  export { PromptPack, PraxisAgent, PraxisAgentArchetype, STATE_PLANE_STANDARD_CONTROLS, append, compileAgent, endpoint, harness, inspectAgentManifest, loop, mainLoop, markdown, markdownFile, model, modelFleet, overwrite, policy, prepend, replaceLastLines, sandbox, session, statePlane, storage, tool, toolPolicies, tools, validateAgentManifest, } from "../runtimeImplementation/runtimeAgentManifest.js";
36
37
  export { buildMcpServerProfilesFromManifest, createMcpApplicationStateView, createFileMcpPlusProfileStore, createFileMcpPlusSkillStore, createInMemoryMcpPlusOverlayStore, createInMemoryMcpPlusProfileStore, createInMemoryMcpPlusSkillStore, mcp, planMcpHarnessExposure, };
38
+ export { adviseSkillPromotion, createFileSkillPlaneStore, createInMemorySkillPlaneStore, createSkillWriteProposal, loadSkillHeadsFromSource, loadSkillHeadsFromSources, renderSkillIndexMaterial, skill, } from "../runtimeImplementation/runtime.skillPlane/index.js";
37
39
  export { createMemoryPlane, memoryPlane, };
38
40
  export { capabilities, capability, createProvisionPlan, dependencies, dependencyAuthoring, provisionRuntimeDescriptor, } from "../runtimeImplementation/runtime.provisionPlane/index.js";
39
41
  export { component, createRuntimeComponentRegistry, lookupRuntimeComponent, officialRuntimeComponents, } from "../runtimeImplementation/runtime.componentPlane/index.js";
@@ -288,6 +290,7 @@ export const praxis = Object.freeze({
288
290
  project: defineProject,
289
291
  statePlane,
290
292
  storage,
293
+ skill,
291
294
  memory,
292
295
  basetool,
293
296
  basetools: basetool,
@@ -59,6 +59,7 @@ function segmentStability(kind) {
59
59
  if (kind === "stableSystemCore" ||
60
60
  kind === "declaredRuntimeContext" ||
61
61
  kind === "toolDeclarations" ||
62
+ kind === "skillIndex" ||
62
63
  kind === "projectContext") {
63
64
  return "static";
64
65
  }
@@ -2,9 +2,9 @@ export declare const PROMPT_PACK_INTERNAL_MATERIAL_KINDS: readonly ["system", "u
2
2
  export type PromptPackInternalMaterialKind = (typeof PROMPT_PACK_INTERNAL_MATERIAL_KINDS)[number];
3
3
  export type PromptPackMaterialKind = PromptPackInternalMaterialKind | "tool-summary" | "command-injection";
4
4
  export type PromptPackMaterialSourceCategory = "declared-built-in" | "process-product" | "user-request";
5
- export declare const PROMPT_PACK_SEGMENT_KINDS: readonly ["stableSystemCore", "declaredRuntimeContext", "toolDeclarations", "projectContext", "sessionSummary", "recentConversation", "memoryContext", "retrievedContext", "observations", "userTurn", "assistantScratchpadPlan"];
5
+ export declare const PROMPT_PACK_SEGMENT_KINDS: readonly ["stableSystemCore", "declaredRuntimeContext", "toolDeclarations", "skillIndex", "projectContext", "sessionSummary", "recentConversation", "memoryContext", "retrievedContext", "observations", "userTurn", "assistantScratchpadPlan"];
6
6
  export type PromptPackSegmentKind = (typeof PROMPT_PACK_SEGMENT_KINDS)[number];
7
- export declare const PROMPT_PACK_PROVIDER_VISIBLE_SEGMENT_KINDS: ("stableSystemCore" | "declaredRuntimeContext" | "toolDeclarations" | "projectContext" | "sessionSummary" | "recentConversation" | "memoryContext" | "retrievedContext" | "observations" | "userTurn")[];
7
+ export declare const PROMPT_PACK_PROVIDER_VISIBLE_SEGMENT_KINDS: ("stableSystemCore" | "declaredRuntimeContext" | "toolDeclarations" | "skillIndex" | "projectContext" | "sessionSummary" | "recentConversation" | "memoryContext" | "retrievedContext" | "observations" | "userTurn")[];
8
8
  export declare const BASIC_CORE_PROMPT_MATERIAL_ID: "praxis:basic-core-prompt";
9
9
  export declare const BASIC_CORE_PROMPT_SOURCE: "runtime.basicCorePrompt";
10
10
  export declare const PROMPT_PACK_TOOL_MATERIAL_TYPES: readonly ["policy", "declaration", "result", "call-state"];
@@ -102,8 +102,8 @@ export declare const promptPackDefinerDescriptor: {
102
102
  readonly purpose: "define Praxis internal PromptPack constructs and the protected basic core prompt head";
103
103
  readonly internalMaterialKinds: readonly ["system", "user", "tool", "command", "cmp", "memory", "file", "retrieval", "event", "runtime"];
104
104
  readonly sourceCategories: readonly ["declared-built-in", "process-product", "user-request"];
105
- readonly orderedSegmentKinds: readonly ["stableSystemCore", "declaredRuntimeContext", "toolDeclarations", "projectContext", "sessionSummary", "recentConversation", "memoryContext", "retrievedContext", "observations", "userTurn", "assistantScratchpadPlan"];
106
- readonly providerVisibleSegmentKinds: ("stableSystemCore" | "declaredRuntimeContext" | "toolDeclarations" | "projectContext" | "sessionSummary" | "recentConversation" | "memoryContext" | "retrievedContext" | "observations" | "userTurn")[];
105
+ readonly orderedSegmentKinds: readonly ["stableSystemCore", "declaredRuntimeContext", "toolDeclarations", "skillIndex", "projectContext", "sessionSummary", "recentConversation", "memoryContext", "retrievedContext", "observations", "userTurn", "assistantScratchpadPlan"];
106
+ readonly providerVisibleSegmentKinds: ("stableSystemCore" | "declaredRuntimeContext" | "toolDeclarations" | "skillIndex" | "projectContext" | "sessionSummary" | "recentConversation" | "memoryContext" | "retrievedContext" | "observations" | "userTurn")[];
107
107
  readonly basicCorePromptMaterialId: "praxis:basic-core-prompt";
108
108
  readonly providerPayloadCreated: false;
109
109
  readonly unsafeSideEffects: false;
@@ -26,6 +26,7 @@ export const PROMPT_PACK_SEGMENT_KINDS = [
26
26
  "stableSystemCore",
27
27
  "declaredRuntimeContext",
28
28
  "toolDeclarations",
29
+ "skillIndex",
29
30
  "projectContext",
30
31
  "sessionSummary",
31
32
  "recentConversation",
@@ -13,6 +13,7 @@ import { type RuntimeBaseToolExecutorPolicy, type RuntimeBaseToolExecutorResourc
13
13
  import { type BaseToolDependencyRuntimeMode } from "./runtime.execEngine/baseToolDependencyRuntime.js";
14
14
  import { type BaseToolContextSelection, type BaseToolContextUsageRecord } from "./runtime.execEngine/baseToolContextFolding.js";
15
15
  import { type PromptContextConversationMessage, type PromptContextSessionSummary } from "./runtime.execEngine/promptContextAssembly.js";
16
+ import { type SkillPlaneStore } from "./runtime.skillPlane/index.js";
16
17
  import { type BaseToolPolicyAdjudication } from "./runtime.execEngine/baseToolPolicyAdjudicator.js";
17
18
  import { type BaseToolSandboxPlan } from "./runtime.sandboxPlane/baseToolSandboxPlanner.js";
18
19
  import type { RuntimeAuthResolver, RuntimeAuthResolverRequest } from "./runtime.authPlane/runtimeAuthResolver.js";
@@ -59,6 +60,9 @@ export type PraxisRuntimeKernelOptions = {
59
60
  skillStore?: McpPlusSkillStore;
60
61
  reprofileConsecutiveIndexedCalls?: number;
61
62
  };
63
+ skillPlane?: {
64
+ store?: SkillPlaneStore;
65
+ };
62
66
  baseToolPolicy?: RuntimeBaseToolExecutorPolicy;
63
67
  baseToolResourceLimits?: RuntimeBaseToolExecutorResourceLimits;
64
68
  store?: RuntimeSessionStateEventStore;
@@ -27,6 +27,7 @@ import { evaluateBaseToolRuntimeGovernance } from "./runtime.execEngine/baseTool
27
27
  import { preflightBaseToolDependencies, } from "./runtime.execEngine/baseToolDependencyRuntime.js";
28
28
  import { applyBaseToolContextUsage, createBaseToolContextHeatState, } from "./runtime.execEngine/baseToolContextFolding.js";
29
29
  import { assemblePromptContextMaterials, PRAXIS_BASE_TOOL_CALLING_PROTOCOL, } from "./runtime.execEngine/promptContextAssembly.js";
30
+ import { createFileSkillPlaneStore, loadSkillHeadsFromSources, renderSkillIndexMaterial, skillPlaneModuleFrom, } from "./runtime.skillPlane/index.js";
30
31
  import { invokeMountedBaseTool } from "./runtime.execEngine/baseToolRuntimeMount.js";
31
32
  import { evaluateBaseToolRuntimeReadiness } from "./runtime.execEngine/baseToolSupportCatalog.js";
32
33
  import { adjudicateBaseToolPolicy, } from "./runtime.execEngine/baseToolPolicyAdjudicator.js";
@@ -773,6 +774,31 @@ async function discoverRuntimeMcpDynamicSurface(manifest, executor, mcpPlusRunti
773
774
  toolDeclarationPreludeMaterials: renderMcpPlusNativePrelude(promptPlan),
774
775
  };
775
776
  }
777
+ async function discoverRuntimeSkillIndexMaterials(input) {
778
+ const skillModule = skillPlaneModuleFrom(input.manifest.harness);
779
+ if (skillModule === undefined)
780
+ return [];
781
+ const includeScopes = skillModule.indexPolicy.includeScopes;
782
+ function scopeMatchesIndexPolicy(head) {
783
+ const scopes = includeScopes;
784
+ if (scopes.length === 0)
785
+ return true;
786
+ return head.scope !== undefined && scopes.includes(head.scope);
787
+ }
788
+ const bySkillId = new Map();
789
+ for (const head of await loadSkillHeadsFromSources(skillModule.sources, { workspaceRoot: input.workspaceRoot })) {
790
+ if (scopeMatchesIndexPolicy(head) && !bySkillId.has(head.skillId)) {
791
+ bySkillId.set(head.skillId, head);
792
+ }
793
+ }
794
+ for (const head of await input.store.listHeads({ scopes: skillModule.indexPolicy.includeScopes })) {
795
+ if (!bySkillId.has(head.skillId)) {
796
+ bySkillId.set(head.skillId, head);
797
+ }
798
+ }
799
+ const heads = [...bySkillId.values()].slice(0, skillModule.indexPolicy.maxHeads);
800
+ return heads.length === 0 ? [] : [renderSkillIndexMaterial(heads)];
801
+ }
776
802
  function providerToolMappings(manifest) {
777
803
  return createProviderToolMappings(manifest.harness.tools);
778
804
  }
@@ -2764,6 +2790,7 @@ async function buildPromptPackAndLower(input) {
2764
2790
  sessionSummary: input.sessionSummary,
2765
2791
  conversationWindow: input.conversationWindow,
2766
2792
  toolDeclarationPreludeMaterials: input.toolDeclarationPreludeMaterials,
2793
+ skillIndexMaterials: input.skillIndexMaterials,
2767
2794
  projectContextGovernanceMaterials: input.projectContextGovernanceMaterials?.map((material) => ({
2768
2795
  id: material.id,
2769
2796
  kind: "runtime",
@@ -4134,6 +4161,11 @@ export class PraxisRuntimeKernel {
4134
4161
  const maxToolCalls = manifest.harness.loop.maxToolCalls ?? 4;
4135
4162
  let toolMappings = [];
4136
4163
  let toolDeclarationPreludeMaterials = [];
4164
+ const skillIndexMaterials = await discoverRuntimeSkillIndexMaterials({
4165
+ manifest,
4166
+ workspaceRoot: toolWorkspaceRoot,
4167
+ store: options.skillPlane?.store ?? createFileSkillPlaneStore(path.join(toolWorkspaceRoot, ".rax_workspace", "skills")),
4168
+ });
4137
4169
  async function refreshRuntimeMcpTools(reason) {
4138
4170
  const dynamicSurface = await discoverRuntimeMcpDynamicSurface(runtimeMcpBaseManifest, executor, mcpPlusRuntime);
4139
4171
  manifest = withRuntimeHarnessToolLayer(runtimeMcpBaseManifest, dynamicSurface.tools, reason);
@@ -4217,6 +4249,7 @@ export class PraxisRuntimeKernel {
4217
4249
  sessionSummary: compactSessionSummary,
4218
4250
  conversationWindow: compactConversationWindow,
4219
4251
  toolDeclarationPreludeMaterials,
4252
+ skillIndexMaterials,
4220
4253
  projectContextGovernanceMaterials: preCompactGovernanceProjectContextMaterials,
4221
4254
  toolContextSelection,
4222
4255
  toolContextUsage: toolContextHeatState.usage,
@@ -4462,6 +4495,7 @@ export class PraxisRuntimeKernel {
4462
4495
  sessionSummary: compactSessionSummary,
4463
4496
  conversationWindow: compactConversationWindow,
4464
4497
  toolDeclarationPreludeMaterials,
4498
+ skillIndexMaterials,
4465
4499
  projectContextGovernanceMaterials: preCompactGovernanceProjectContextMaterials,
4466
4500
  toolContextSelection,
4467
4501
  toolContextUsage: toolContextHeatState.usage,
@@ -37,6 +37,7 @@ export type PromptContextAssemblyRequest = {
37
37
  conversationWindow?: readonly PromptContextConversationMessage[];
38
38
  projectContextGovernanceMaterials?: readonly PromptPackMaterialDraft[];
39
39
  toolDeclarationPreludeMaterials?: readonly PromptPackMaterialDraft[];
40
+ skillIndexMaterials?: readonly PromptPackMaterialDraft[];
40
41
  budget?: PromptContextAssemblyBudget;
41
42
  toolContextSelection?: BaseToolContextSelection;
42
43
  toolContextUsage?: readonly BaseToolContextUsageRecord[];
@@ -434,6 +434,21 @@ export function assemblePromptContextMaterials(input) {
434
434
  toolMaterialType: "policy",
435
435
  },
436
436
  }));
437
+ const skillIndexMaterials = (input.skillIndexMaterials ?? []).map((material, index) => ({
438
+ ...material,
439
+ id: material.id ?? `runtime:skill-index:${index + 1}`,
440
+ kind: material.kind,
441
+ source: material.source ?? "runtime.skillPlane.index",
442
+ sourceCategory: material.sourceCategory ?? "declared-built-in",
443
+ priority: material.priority ?? 94 - index,
444
+ trusted: material.trusted ?? true,
445
+ scope: material.scope ?? "runtime.skillPlane.index",
446
+ promptSegmentKind: "skillIndex",
447
+ metadata: {
448
+ ...(material.metadata ?? {}),
449
+ promptSegmentKind: "skillIndex",
450
+ },
451
+ }));
437
452
  const sessionSummaryMaterial = input.sessionSummary === undefined
438
453
  ? []
439
454
  : [{
@@ -462,6 +477,7 @@ export function assemblePromptContextMaterials(input) {
462
477
  ...sessionSummaryMaterial,
463
478
  ...memoryContextMaterials,
464
479
  ...toolDeclarationPreludeMaterials,
480
+ ...skillIndexMaterials,
465
481
  {
466
482
  id: `task:${input.turnIndex}`,
467
483
  kind: "user",
@@ -544,6 +560,7 @@ export function assemblePromptContextMaterials(input) {
544
560
  declaredRuntimeContextMaterial,
545
561
  toolDeclarationsMaterial,
546
562
  ...toolDeclarationPreludeMaterials,
563
+ ...skillIndexMaterials,
547
564
  ...projectContextGovernanceMaterials,
548
565
  ...sessionSummaryMaterial,
549
566
  ...memoryContextMaterials,
@@ -0,0 +1,119 @@
1
+ import type { PromptPackMaterialDraft } from "../../executionEngine/promptPack/promptDefiner.js";
2
+ export type SkillPlaneScope = "agent" | "project" | "workspace" | "user" | "session";
3
+ export type SkillPlanePromotionState = "experience" | "skill" | "candidate-mcp-plus" | "mcp-plus" | "tool";
4
+ export type SkillHead = {
5
+ skillId: string;
6
+ title: string;
7
+ summary: string;
8
+ scope?: SkillPlaneScope;
9
+ whenToUse?: string;
10
+ why?: string;
11
+ keywords?: readonly string[];
12
+ pitfallsPreview?: readonly string[];
13
+ bodyRef?: string;
14
+ promotedFrom?: readonly string[];
15
+ promotionState?: SkillPlanePromotionState;
16
+ };
17
+ export type SkillBody = SkillHead & {
18
+ prerequisites?: readonly string[];
19
+ do?: readonly string[];
20
+ avoid?: readonly string[];
21
+ pitfalls?: readonly string[];
22
+ verification?: readonly string[];
23
+ examples?: readonly string[];
24
+ promotionSignals?: readonly string[];
25
+ updatedAt: string;
26
+ };
27
+ export type SkillSourceSpec = {
28
+ kind: "directory";
29
+ path: string;
30
+ scope?: SkillPlaneScope;
31
+ } | {
32
+ kind: "package";
33
+ packageName: string;
34
+ scope?: SkillPlaneScope;
35
+ } | {
36
+ kind: "inline";
37
+ heads: readonly SkillHead[];
38
+ };
39
+ export type SkillPlaneIndexPolicy = {
40
+ maxHeads: number;
41
+ includeScopes: readonly SkillPlaneScope[];
42
+ };
43
+ export type SkillPlaneBodyLoadPolicy = {
44
+ mode: "on-demand" | "eager" | "disabled";
45
+ maxBodiesPerTurn: number;
46
+ };
47
+ export type SkillPlaneLifecyclePolicy = {
48
+ allowWrite: boolean;
49
+ checkpointWrites: boolean;
50
+ promotion: "off" | "suggest" | "auto";
51
+ };
52
+ export type SkillPlaneModuleSpec = {
53
+ kind: "praxis.skill.module";
54
+ version: "praxis.skill.v1";
55
+ sources: readonly SkillSourceSpec[];
56
+ indexPolicy: SkillPlaneIndexPolicy;
57
+ bodyLoadPolicy: SkillPlaneBodyLoadPolicy;
58
+ lifecycle: SkillPlaneLifecyclePolicy;
59
+ metadata?: Readonly<Record<string, unknown>>;
60
+ };
61
+ export type SkillPlaneListHeadsQuery = {
62
+ scopes?: readonly SkillPlaneScope[];
63
+ };
64
+ export type SkillPlaneStore = {
65
+ listHeads(query?: SkillPlaneListHeadsQuery): Promise<readonly SkillHead[]>;
66
+ readBody(skillId: string): Promise<SkillBody | undefined>;
67
+ write(body: SkillBody): Promise<SkillBody>;
68
+ };
69
+ export type SkillPlaneSourceResolutionInput = {
70
+ workspaceRoot?: string;
71
+ };
72
+ export type SkillWriteProposal = {
73
+ kind: "praxis.skill.writeProposal";
74
+ body: SkillBody;
75
+ reason?: string;
76
+ safeForRuntimeInspection: true;
77
+ };
78
+ export type SkillPromotionAdvice = {
79
+ kind: "praxis.skill.promotionAdvice";
80
+ skillId: string;
81
+ from?: SkillPlanePromotionState;
82
+ target: "candidate-mcp-plus";
83
+ autoGenerateTool: false;
84
+ reason?: string;
85
+ signals?: readonly string[];
86
+ };
87
+ export declare const skill: {
88
+ readonly directory: (directoryPath: string, input?: {
89
+ scope?: SkillPlaneScope;
90
+ }) => SkillSourceSpec;
91
+ readonly package: (packageName: string, input?: {
92
+ scope?: SkillPlaneScope;
93
+ }) => SkillSourceSpec;
94
+ readonly inline: (heads: readonly SkillHead[]) => SkillSourceSpec;
95
+ readonly module: (input?: {
96
+ sources?: readonly SkillSourceSpec[];
97
+ indexPolicy?: Partial<SkillPlaneIndexPolicy>;
98
+ bodyLoadPolicy?: Partial<SkillPlaneBodyLoadPolicy>;
99
+ lifecycle?: Partial<SkillPlaneLifecyclePolicy>;
100
+ metadata?: Readonly<Record<string, unknown>>;
101
+ }) => SkillPlaneModuleSpec;
102
+ };
103
+ export declare function isSkillPlaneModuleSpec(value: unknown): value is SkillPlaneModuleSpec;
104
+ export declare function skillPlaneModuleFrom(input: {
105
+ modules?: Readonly<Record<string, unknown>>;
106
+ }): SkillPlaneModuleSpec | undefined;
107
+ export declare function runtimeRequirementsForSkillModule(module: SkillPlaneModuleSpec | undefined): readonly string[];
108
+ export declare function loadSkillHeadsFromSource(source: SkillSourceSpec, input?: SkillPlaneSourceResolutionInput): Promise<readonly SkillHead[]>;
109
+ export declare function loadSkillHeadsFromSources(sources: readonly SkillSourceSpec[], input?: SkillPlaneSourceResolutionInput): Promise<readonly SkillHead[]>;
110
+ export declare function createInMemorySkillPlaneStore(initialBodies?: readonly SkillBody[]): SkillPlaneStore;
111
+ export declare function createFileSkillPlaneStore(rootDir: string): SkillPlaneStore;
112
+ export declare function renderSkillIndexMaterial(heads: readonly SkillHead[]): PromptPackMaterialDraft;
113
+ export declare function createSkillWriteProposal(body: SkillBody, input?: {
114
+ reason?: string;
115
+ }): SkillWriteProposal;
116
+ export declare function adviseSkillPromotion(skillHead: SkillHead, input?: {
117
+ reason?: string;
118
+ signals?: readonly string[];
119
+ }): SkillPromotionAdvice;
@@ -0,0 +1,274 @@
1
+ /*
2
+ * 文件定位:Runtime Skill Plane / 技能索引与按需正文加载合约。
3
+ * 核心目的:让 Praxis runtime 能声明、索引、读取和写入可复用技能经验,
4
+ * 但不把技能直接降级成工具声明或外部服务配置。
5
+ */
6
+ import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
7
+ import { createHash } from "node:crypto";
8
+ import path from "node:path";
9
+ const DEFAULT_INDEX_POLICY = {
10
+ maxHeads: 40,
11
+ includeScopes: ["agent", "project", "workspace"],
12
+ };
13
+ const DEFAULT_BODY_LOAD_POLICY = {
14
+ mode: "on-demand",
15
+ maxBodiesPerTurn: 3,
16
+ };
17
+ const DEFAULT_LIFECYCLE_POLICY = {
18
+ allowWrite: true,
19
+ checkpointWrites: true,
20
+ promotion: "suggest",
21
+ };
22
+ export const skill = {
23
+ directory(directoryPath, input) {
24
+ return input === undefined
25
+ ? { kind: "directory", path: directoryPath }
26
+ : { kind: "directory", path: directoryPath, scope: input.scope };
27
+ },
28
+ package(packageName, input) {
29
+ return input === undefined
30
+ ? { kind: "package", packageName }
31
+ : { kind: "package", packageName, scope: input.scope };
32
+ },
33
+ inline(heads) {
34
+ return { kind: "inline", heads };
35
+ },
36
+ module(input = {}) {
37
+ return {
38
+ kind: "praxis.skill.module",
39
+ version: "praxis.skill.v1",
40
+ sources: input.sources ?? [],
41
+ indexPolicy: {
42
+ ...DEFAULT_INDEX_POLICY,
43
+ ...input.indexPolicy,
44
+ },
45
+ bodyLoadPolicy: {
46
+ ...DEFAULT_BODY_LOAD_POLICY,
47
+ ...input.bodyLoadPolicy,
48
+ },
49
+ lifecycle: {
50
+ ...DEFAULT_LIFECYCLE_POLICY,
51
+ ...input.lifecycle,
52
+ },
53
+ metadata: input.metadata,
54
+ };
55
+ },
56
+ };
57
+ export function isSkillPlaneModuleSpec(value) {
58
+ if (typeof value !== "object" || value === null || Array.isArray(value))
59
+ return false;
60
+ const record = value;
61
+ return record.kind === "praxis.skill.module" && Array.isArray(record.sources);
62
+ }
63
+ export function skillPlaneModuleFrom(input) {
64
+ const candidate = input.modules?.skill;
65
+ return isSkillPlaneModuleSpec(candidate) ? candidate : undefined;
66
+ }
67
+ export function runtimeRequirementsForSkillModule(module) {
68
+ return module === undefined ? [] : ["runtime.skill"];
69
+ }
70
+ function isSkillHeadLike(value) {
71
+ if (typeof value !== "object" || value === null || Array.isArray(value))
72
+ return false;
73
+ const record = value;
74
+ return typeof record.skillId === "string" && typeof record.title === "string" && typeof record.summary === "string";
75
+ }
76
+ function headsFromUnknown(value) {
77
+ if (Array.isArray(value))
78
+ return value.filter(isSkillHeadLike);
79
+ if (typeof value !== "object" || value === null)
80
+ return [];
81
+ const record = value;
82
+ if (Array.isArray(record.skillHeads))
83
+ return record.skillHeads.filter(isSkillHeadLike);
84
+ if (Array.isArray(record.heads))
85
+ return record.heads.filter(isSkillHeadLike);
86
+ if (Array.isArray(record.skills))
87
+ return record.skills.filter(isSkillHeadLike);
88
+ return isSkillHeadLike(value) ? [value] : [];
89
+ }
90
+ function withSourceScope(heads, scope) {
91
+ if (scope === undefined)
92
+ return heads;
93
+ return heads.map((head) => ({
94
+ ...head,
95
+ scope: head.scope ?? scope,
96
+ }));
97
+ }
98
+ export async function loadSkillHeadsFromSource(source, input = {}) {
99
+ if (source.kind === "inline")
100
+ return source.heads;
101
+ if (source.kind === "package") {
102
+ const module = await import(source.packageName);
103
+ return withSourceScope([
104
+ ...headsFromUnknown(module.skillHeads),
105
+ ...headsFromUnknown(module.heads),
106
+ ...headsFromUnknown(module.skills),
107
+ ...headsFromUnknown(module.default),
108
+ ], source.scope);
109
+ }
110
+ const rootDir = path.isAbsolute(source.path)
111
+ ? source.path
112
+ : path.resolve(input.workspaceRoot ?? process.cwd(), source.path);
113
+ let entries;
114
+ try {
115
+ entries = await readdir(rootDir);
116
+ }
117
+ catch {
118
+ return [];
119
+ }
120
+ const heads = await Promise.all(entries
121
+ .filter((entry) => entry.endsWith(".json"))
122
+ .map((entry) => readJsonFile(path.join(rootDir, entry), undefined).then(headsFromUnknown)));
123
+ return withSourceScope(heads.flat(), source.scope);
124
+ }
125
+ export async function loadSkillHeadsFromSources(sources, input = {}) {
126
+ const heads = await Promise.all(sources.map((source) => loadSkillHeadsFromSource(source, input)));
127
+ return heads.flat();
128
+ }
129
+ function headFromBody(body) {
130
+ return {
131
+ skillId: body.skillId,
132
+ title: body.title,
133
+ summary: body.summary,
134
+ scope: body.scope,
135
+ whenToUse: body.whenToUse,
136
+ why: body.why,
137
+ keywords: body.keywords,
138
+ pitfallsPreview: body.pitfallsPreview,
139
+ bodyRef: body.bodyRef,
140
+ promotedFrom: body.promotedFrom,
141
+ promotionState: body.promotionState,
142
+ };
143
+ }
144
+ function scopeMatches(head, scopes) {
145
+ if (scopes === undefined || scopes.length === 0)
146
+ return true;
147
+ return head.scope !== undefined && scopes.includes(head.scope);
148
+ }
149
+ function sortHeads(heads) {
150
+ return [...heads].sort((left, right) => left.skillId.localeCompare(right.skillId));
151
+ }
152
+ export function createInMemorySkillPlaneStore(initialBodies = []) {
153
+ const bodies = new Map(initialBodies.map((body) => [body.skillId, body]));
154
+ return {
155
+ async listHeads(query) {
156
+ return sortHeads([...bodies.values()].map(headFromBody).filter((head) => scopeMatches(head, query?.scopes)));
157
+ },
158
+ async readBody(skillId) {
159
+ return bodies.get(skillId);
160
+ },
161
+ async write(body) {
162
+ bodies.set(body.skillId, body);
163
+ return body;
164
+ },
165
+ };
166
+ }
167
+ async function readJsonFile(filePath, fallback) {
168
+ try {
169
+ return JSON.parse(await readFile(filePath, "utf8"));
170
+ }
171
+ catch {
172
+ return fallback;
173
+ }
174
+ }
175
+ async function writeJsonFile(filePath, value) {
176
+ await mkdir(path.dirname(filePath), { recursive: true });
177
+ await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
178
+ }
179
+ function skillFilePart(skillId) {
180
+ const sanitized = skillId
181
+ .trim()
182
+ .replace(/[^a-zA-Z0-9._-]+/gu, "-")
183
+ .replace(/^[._-]+|[._-]+$/gu, "")
184
+ .slice(0, 64)
185
+ .toLowerCase() || "skill";
186
+ const stableSuffix = createHash("sha256").update(skillId).digest("hex").slice(0, 16);
187
+ return `${sanitized}-${stableSuffix}.json`;
188
+ }
189
+ export function createFileSkillPlaneStore(rootDir) {
190
+ function bodyPath(skillId) {
191
+ return path.join(rootDir, skillFilePart(skillId));
192
+ }
193
+ async function listBodies() {
194
+ let entries;
195
+ try {
196
+ entries = await readdir(rootDir);
197
+ }
198
+ catch {
199
+ return [];
200
+ }
201
+ const bodies = await Promise.all(entries
202
+ .filter((entry) => entry.endsWith(".json"))
203
+ .map((entry) => readJsonFile(path.join(rootDir, entry), undefined)));
204
+ return bodies.filter((body) => body !== undefined && typeof body.skillId === "string");
205
+ }
206
+ return {
207
+ async listHeads(query) {
208
+ return sortHeads((await listBodies()).map(headFromBody).filter((head) => scopeMatches(head, query?.scopes)));
209
+ },
210
+ async readBody(skillId) {
211
+ return await readJsonFile(bodyPath(skillId), undefined);
212
+ },
213
+ async write(body) {
214
+ await writeJsonFile(bodyPath(body.skillId), body);
215
+ return body;
216
+ },
217
+ };
218
+ }
219
+ function compactLine(label, value) {
220
+ if (value === undefined)
221
+ return undefined;
222
+ const rendered = typeof value === "string"
223
+ ? value.trim()
224
+ : value.map((item) => item.trim()).filter(Boolean).join(", ");
225
+ return rendered.length === 0 ? undefined : `${label}: ${rendered}`;
226
+ }
227
+ export function renderSkillIndexMaterial(heads) {
228
+ const lines = ["# Skill Plane Index"];
229
+ for (const head of sortHeads(heads)) {
230
+ lines.push(`- ${head.skillId}: ${head.title}. ${head.summary}`);
231
+ const detailLines = [
232
+ compactLine(" scope", head.scope),
233
+ compactLine(" when", head.whenToUse),
234
+ compactLine(" why", head.why),
235
+ compactLine(" keywords", head.keywords),
236
+ compactLine(" pitfalls preview", head.pitfallsPreview),
237
+ compactLine(" body ref", head.bodyRef),
238
+ compactLine(" promotion", head.promotionState),
239
+ ].filter((line) => line !== undefined);
240
+ lines.push(...detailLines);
241
+ }
242
+ return {
243
+ id: "runtime:skill-plane:index",
244
+ kind: "runtime",
245
+ source: "runtime.skillPlane.index",
246
+ sourceCategory: "declared-built-in",
247
+ trusted: true,
248
+ promptSegmentKind: "skillIndex",
249
+ metadata: {
250
+ promptSegmentKind: "skillIndex",
251
+ generatedBy: "runtime.skillPlane",
252
+ },
253
+ text: lines.join("\n"),
254
+ };
255
+ }
256
+ export function createSkillWriteProposal(body, input = {}) {
257
+ return {
258
+ kind: "praxis.skill.writeProposal",
259
+ body,
260
+ reason: input.reason,
261
+ safeForRuntimeInspection: true,
262
+ };
263
+ }
264
+ export function adviseSkillPromotion(skillHead, input = {}) {
265
+ return {
266
+ kind: "praxis.skill.promotionAdvice",
267
+ skillId: skillHead.skillId,
268
+ from: skillHead.promotionState,
269
+ target: "candidate-mcp-plus",
270
+ autoGenerateTool: false,
271
+ reason: input.reason,
272
+ signals: input.signals,
273
+ };
274
+ }
@@ -12,6 +12,7 @@ import { createBaseToolSupportCatalog } from "./runtime.execEngine/baseToolSuppo
12
12
  import { canonicalDependencyId, dependencyKindFromId, } from "./runtime.dependencyPlane/index.js";
13
13
  import { capability as capabilityAuthoring, } from "./runtime.provisionPlane/index.js";
14
14
  import { mcpHarnessModuleFrom, runtimeRequirementsForMcpModule, } from "./runtime.mcpPlane/index.js";
15
+ import { runtimeRequirementsForSkillModule, skillPlaneModuleFrom, } from "./runtime.skillPlane/index.js";
15
16
  export class PromptPack {
16
17
  promptPackId;
17
18
  base;
@@ -1272,6 +1273,7 @@ function normalizeHarness(input, authoring, normalizedTools) {
1272
1273
  runtimeRequirements: cleanList([
1273
1274
  ...(input.runtimeRequirements ?? []),
1274
1275
  ...runtimeRequirementsForMcpModule(mcpHarnessModuleFrom({ modules: input.modules })),
1276
+ ...runtimeRequirementsForSkillModule(skillPlaneModuleFrom({ modules: input.modules })),
1275
1277
  ]),
1276
1278
  capabilities: authoring.capabilities,
1277
1279
  dependencies: authoring.dependencies,
@@ -4,6 +4,26 @@ import type { HarnessSpec } from "@praxis-ai/praxis";
4
4
  import type { NormalizedRepoInspectorOptions } from "../config/repoInspectorOptions.js";
5
5
  import { createRepoInspectorToolSet } from "../tools/toolSet.js";
6
6
 
7
+ const repoInspectorSkillModule = praxis.skill.module({
8
+ sources: [
9
+ praxis.skill.inline([{
10
+ skillId: "repo-review.findings-first",
11
+ title: "Findings First Review",
12
+ summary: "Lead with actionable findings and put summaries after risks.",
13
+ scope: "project",
14
+ whenToUse: "Code review and regression-risk tasks",
15
+ pitfallsPreview: ["Do not bury test gaps in a summary."],
16
+ }, {
17
+ skillId: "repo-inspection.anchor-current-target",
18
+ title: "Anchor Current Target",
19
+ summary: "Restate the current repository/path/task before inspecting or editing.",
20
+ scope: "project",
21
+ whenToUse: "Long context or task-switching sessions",
22
+ pitfallsPreview: ["Do not continue a previous repository by inertia."],
23
+ }]),
24
+ ],
25
+ });
26
+
7
27
  export function createRepoInspectorHarness(options: NormalizedRepoInspectorOptions): HarnessSpec {
8
28
  return praxis.harness({
9
29
  modelRef: `model.repoInspector.${options.mode}`,
@@ -30,6 +50,9 @@ export function createRepoInspectorHarness(options: NormalizedRepoInspectorOptio
30
50
  memoryRefs: [
31
51
  "memory.example.fullstack.mpBridge.contract",
32
52
  ],
53
+ modules: {
54
+ skill: repoInspectorSkillModule,
55
+ },
33
56
  tools: praxis.tools(createRepoInspectorToolSet(options)),
34
57
  policy: praxis.policy({
35
58
  allowProviderCall: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxis-ai/praxis",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Praxis agentCore architecture scaffold, tests, and engineering contracts.",