@cstack-protocol/pingala 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/CSD.md +39 -0
- package/.agent/MANIFEST.md +4 -0
- package/.agent/MANIFEST.md.template +4 -0
- package/.agent/agent-contractor.md +45 -0
- package/.agent/architecture/consent-model-fsm.md +77 -0
- package/.agent/architecture/governor-maturity-fsm.md +101 -0
- package/.agent/architecture/governor-validation-fsm.md +106 -0
- package/.agent/architecture/humanized-audit-fsm.md +76 -0
- package/.agent/architecture/pingala-csi-fsm.md +81 -0
- package/.agent/architecture.md +34 -0
- package/.agent/behavior.md +29 -0
- package/.agent/compute.md +32 -0
- package/.agent/consent-prompts.md +41 -0
- package/.agent/governance.yaml +5 -0
- package/.agent/identity.md +29 -0
- package/.agent/knowledge-lattice.json +96 -0
- package/.agent/knowledge-lattice.md +53 -0
- package/.agent/lattice-viz.html +157 -0
- package/.agent/mission.md +37 -0
- package/.agent/pairing-protocol.md +89 -0
- package/.agent/pairing.csp +108 -0
- package/.agent/personas/reflective-operator.md +67 -0
- package/.agent/personas/research.md +62 -0
- package/.agent/pingala.md +47 -0
- package/.agent/roadmap.md +56 -0
- package/.agent/scripts/lattice-extract.py +100 -0
- package/.agent/scripts/sync-agents.sh +82 -0
- package/.agent/scripts/vault-ingest.py +80 -0
- package/.agent/seo-strategy.md +71 -0
- package/.agent/skills/agent-orchestrator/SKILL.md +22 -0
- package/.agent/skills/agent-orchestrator/scripts/sync-agents.sh +61 -0
- package/.agent/skills/knowledge-lattice/SKILL.md +23 -0
- package/.agent/skills/knowledge-lattice/scripts/lattice-extract.py +107 -0
- package/.agent/skills/resource-vault/SKILL.md +30 -0
- package/.agent/skills/resource-vault/scripts/vault-ingest.py +80 -0
- package/.agent/skills/sites-integrity/SKILL.md +28 -0
- package/.agent/skills/stack-auditor/SKILL.md +25 -0
- package/.agent/sources.md +20 -0
- package/.agent/stack-auditor.md +47 -0
- package/.agent/standards.md +36 -0
- package/.agent/strategy.md +65 -0
- package/.agent/vault-schema.md +53 -0
- package/.agent/voice.md +27 -0
- package/.agent/workflows/sync-agents.md +14 -0
- package/.env.example +5 -0
- package/.env.production +3 -0
- package/DISTRIBUTION-PLAN.md +33 -0
- package/HOSTED_SETUP.md +54 -0
- package/LANDING_PAGE_DESIGN.md +46 -0
- package/MANUAL_VERCEL_STEPS.md +39 -0
- package/PRODUCT-ROADMAP.md +241 -0
- package/PROVISIONING_GUIDE.md +39 -0
- package/README.md +38 -0
- package/ROADMAP.md +21 -0
- package/SYNC-ENGINE-SPEC.md +257 -0
- package/build/core/531-protocol.d.ts +26 -0
- package/build/core/531-protocol.js +87 -0
- package/build/core/531-protocol.js.map +1 -0
- package/build/core/531-rule.d.ts +26 -0
- package/build/core/531-rule.js +106 -0
- package/build/core/531-rule.js.map +1 -0
- package/build/core/auth.d.ts +1 -0
- package/build/core/auth.js +24 -0
- package/build/core/auth.js.map +1 -0
- package/build/core/consent-manager.d.ts +17 -0
- package/build/core/consent-manager.js +104 -0
- package/build/core/consent-manager.js.map +1 -0
- package/build/core/csp.d.ts +12 -0
- package/build/core/csp.js +20 -0
- package/build/core/csp.js.map +1 -0
- package/build/core/engagement-analyzer.d.ts +42 -0
- package/build/core/engagement-analyzer.js +71 -0
- package/build/core/engagement-analyzer.js.map +1 -0
- package/build/core/governor.d.ts +106 -0
- package/build/core/governor.js +405 -0
- package/build/core/governor.js.map +1 -0
- package/build/core/life-area-mapper.d.ts +39 -0
- package/build/core/life-area-mapper.js +73 -0
- package/build/core/life-area-mapper.js.map +1 -0
- package/build/core/methodology.d.ts +39 -0
- package/build/core/methodology.js +164 -0
- package/build/core/methodology.js.map +1 -0
- package/build/core/pingala.d.ts +31 -0
- package/build/core/pingala.js +56 -0
- package/build/core/pingala.js.map +1 -0
- package/build/core/sdk-adapter.d.ts +6 -0
- package/build/core/sdk-adapter.js +33 -0
- package/build/core/sdk-adapter.js.map +1 -0
- package/build/cs-agent-core/sdk/index.d.ts +6 -0
- package/build/cs-agent-core/sdk/index.js +18 -0
- package/build/cs-agent-core/sdk/index.js.map +1 -0
- package/build/cs-agent-core/sdk/patterns/index.d.ts +3 -0
- package/build/cs-agent-core/sdk/patterns/index.js +37 -0
- package/build/cs-agent-core/sdk/patterns/index.js.map +1 -0
- package/build/cs-agent-core/sdk/patterns/registry.d.ts +4 -0
- package/build/cs-agent-core/sdk/patterns/registry.js +80 -0
- package/build/cs-agent-core/sdk/patterns/registry.js.map +1 -0
- package/build/cs-agent-core/sdk/telemetry/buffer.d.ts +9 -0
- package/build/cs-agent-core/sdk/telemetry/buffer.js +47 -0
- package/build/cs-agent-core/sdk/telemetry/buffer.js.map +1 -0
- package/build/cs-agent-core/sdk/telemetry/scrubber.d.ts +3 -0
- package/build/cs-agent-core/sdk/telemetry/scrubber.js +13 -0
- package/build/cs-agent-core/sdk/telemetry/scrubber.js.map +1 -0
- package/build/cs-agent-core/sdk/telemetry/types.d.ts +50 -0
- package/build/cs-agent-core/sdk/telemetry/types.js +2 -0
- package/build/cs-agent-core/sdk/telemetry/types.js.map +1 -0
- package/build/cs-agent-core/sdk/types/decision.d.ts +18 -0
- package/build/cs-agent-core/sdk/types/decision.js +2 -0
- package/build/cs-agent-core/sdk/types/decision.js.map +1 -0
- package/build/cs-agent-core/sdk/types/index.d.ts +4 -0
- package/build/cs-agent-core/sdk/types/index.js +5 -0
- package/build/cs-agent-core/sdk/types/index.js.map +1 -0
- package/build/cs-agent-core/sdk/types/pattern.d.ts +17 -0
- package/build/cs-agent-core/sdk/types/pattern.js +2 -0
- package/build/cs-agent-core/sdk/types/pattern.js.map +1 -0
- package/build/cs-agent-core/sdk/types/stack.d.ts +8 -0
- package/build/cs-agent-core/sdk/types/stack.js +2 -0
- package/build/cs-agent-core/sdk/types/stack.js.map +1 -0
- package/build/cs-agent-core/sdk/types/tool.d.ts +9 -0
- package/build/cs-agent-core/sdk/types/tool.js +2 -0
- package/build/cs-agent-core/sdk/types/tool.js.map +1 -0
- package/build/cs-agent-core/sdk/validator/csi.d.ts +2 -0
- package/build/cs-agent-core/sdk/validator/csi.js +24 -0
- package/build/cs-agent-core/sdk/validator/csi.js.map +1 -0
- package/build/cs-agent-core/sdk/validator/index.d.ts +2 -0
- package/build/cs-agent-core/sdk/validator/index.js +3 -0
- package/build/cs-agent-core/sdk/validator/index.js.map +1 -0
- package/build/cs-agent-core/sdk/validator/rules/geometry.d.ts +11 -0
- package/build/cs-agent-core/sdk/validator/rules/geometry.js +22 -0
- package/build/cs-agent-core/sdk/validator/rules/geometry.js.map +1 -0
- package/build/cs-agent-core/sdk/validator/validate.d.ts +2 -0
- package/build/cs-agent-core/sdk/validator/validate.js +46 -0
- package/build/cs-agent-core/sdk/validator/validate.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +444 -0
- package/build/index.js.map +1 -0
- package/build/pingala-mcp/src/core/531-rule.d.ts +26 -0
- package/build/pingala-mcp/src/core/531-rule.js +96 -0
- package/build/pingala-mcp/src/core/531-rule.js.map +1 -0
- package/build/pingala-mcp/src/core/auth.d.ts +1 -0
- package/build/pingala-mcp/src/core/auth.js +15 -0
- package/build/pingala-mcp/src/core/auth.js.map +1 -0
- package/build/pingala-mcp/src/core/consent-manager.d.ts +17 -0
- package/build/pingala-mcp/src/core/consent-manager.js +104 -0
- package/build/pingala-mcp/src/core/consent-manager.js.map +1 -0
- package/build/pingala-mcp/src/core/csp.d.ts +12 -0
- package/build/pingala-mcp/src/core/csp.js +20 -0
- package/build/pingala-mcp/src/core/csp.js.map +1 -0
- package/build/pingala-mcp/src/core/engagement-analyzer.d.ts +42 -0
- package/build/pingala-mcp/src/core/engagement-analyzer.js +71 -0
- package/build/pingala-mcp/src/core/engagement-analyzer.js.map +1 -0
- package/build/pingala-mcp/src/core/governor.d.ts +104 -0
- package/build/pingala-mcp/src/core/governor.js +359 -0
- package/build/pingala-mcp/src/core/governor.js.map +1 -0
- package/build/pingala-mcp/src/core/life-area-mapper.d.ts +39 -0
- package/build/pingala-mcp/src/core/life-area-mapper.js +73 -0
- package/build/pingala-mcp/src/core/life-area-mapper.js.map +1 -0
- package/build/pingala-mcp/src/core/methodology.d.ts +39 -0
- package/build/pingala-mcp/src/core/methodology.js +164 -0
- package/build/pingala-mcp/src/core/methodology.js.map +1 -0
- package/build/pingala-mcp/src/core/pingala.d.ts +25 -0
- package/build/pingala-mcp/src/core/pingala.js +56 -0
- package/build/pingala-mcp/src/core/pingala.js.map +1 -0
- package/build/pingala-mcp/src/core/sdk-adapter.d.ts +6 -0
- package/build/pingala-mcp/src/core/sdk-adapter.js +33 -0
- package/build/pingala-mcp/src/core/sdk-adapter.js.map +1 -0
- package/build/pingala-mcp/src/index.d.ts +1 -0
- package/build/pingala-mcp/src/index.js +221 -0
- package/build/pingala-mcp/src/index.js.map +1 -0
- package/build/pingala-mcp/src/test-l3.d.ts +1 -0
- package/build/pingala-mcp/src/test-l3.js +35 -0
- package/build/pingala-mcp/src/test-l3.js.map +1 -0
- package/build/pingala-mcp/src/tools/audit-workspace.d.ts +16 -0
- package/build/pingala-mcp/src/tools/audit-workspace.js +39 -0
- package/build/pingala-mcp/src/tools/audit-workspace.js.map +1 -0
- package/build/pingala-mcp/src/tools/calculate-csi.d.ts +24 -0
- package/build/pingala-mcp/src/tools/calculate-csi.js +29 -0
- package/build/pingala-mcp/src/tools/calculate-csi.js.map +1 -0
- package/build/pingala-mcp/src/tools/cs-audit.d.ts +54 -0
- package/build/pingala-mcp/src/tools/cs-audit.js +310 -0
- package/build/pingala-mcp/src/tools/cs-audit.js.map +1 -0
- package/build/pingala-mcp/src/tools/get-governance-context.d.ts +11 -0
- package/build/pingala-mcp/src/tools/get-governance-context.js +16 -0
- package/build/pingala-mcp/src/tools/get-governance-context.js.map +1 -0
- package/build/pingala-mcp/src/tools/validate-stack-change.d.ts +41 -0
- package/build/pingala-mcp/src/tools/validate-stack-change.js +35 -0
- package/build/pingala-mcp/src/tools/validate-stack-change.js.map +1 -0
- package/build/sdk/index.d.ts +6 -0
- package/build/sdk/index.js +18 -0
- package/build/sdk/index.js.map +1 -0
- package/build/sdk/patterns/index.d.ts +3 -0
- package/build/sdk/patterns/index.js +37 -0
- package/build/sdk/patterns/index.js.map +1 -0
- package/build/sdk/patterns/registry.d.ts +4 -0
- package/build/sdk/patterns/registry.js +80 -0
- package/build/sdk/patterns/registry.js.map +1 -0
- package/build/sdk/telemetry/buffer.d.ts +9 -0
- package/build/sdk/telemetry/buffer.js +47 -0
- package/build/sdk/telemetry/buffer.js.map +1 -0
- package/build/sdk/telemetry/scrubber.d.ts +3 -0
- package/build/sdk/telemetry/scrubber.js +13 -0
- package/build/sdk/telemetry/scrubber.js.map +1 -0
- package/build/sdk/telemetry/types.d.ts +50 -0
- package/build/sdk/telemetry/types.js +2 -0
- package/build/sdk/telemetry/types.js.map +1 -0
- package/build/sdk/types/decision.d.ts +18 -0
- package/build/sdk/types/decision.js +2 -0
- package/build/sdk/types/decision.js.map +1 -0
- package/build/sdk/types/index.d.ts +4 -0
- package/build/sdk/types/index.js +5 -0
- package/build/sdk/types/index.js.map +1 -0
- package/build/sdk/types/pattern.d.ts +17 -0
- package/build/sdk/types/pattern.js +2 -0
- package/build/sdk/types/pattern.js.map +1 -0
- package/build/sdk/types/stack.d.ts +8 -0
- package/build/sdk/types/stack.js +2 -0
- package/build/sdk/types/stack.js.map +1 -0
- package/build/sdk/types/tool.d.ts +9 -0
- package/build/sdk/types/tool.js +2 -0
- package/build/sdk/types/tool.js.map +1 -0
- package/build/sdk/validator/csi.d.ts +2 -0
- package/build/sdk/validator/csi.js +24 -0
- package/build/sdk/validator/csi.js.map +1 -0
- package/build/sdk/validator/index.d.ts +2 -0
- package/build/sdk/validator/index.js +3 -0
- package/build/sdk/validator/index.js.map +1 -0
- package/build/sdk/validator/rules/geometry.d.ts +11 -0
- package/build/sdk/validator/rules/geometry.js +22 -0
- package/build/sdk/validator/rules/geometry.js.map +1 -0
- package/build/sdk/validator/validate.d.ts +2 -0
- package/build/sdk/validator/validate.js +46 -0
- package/build/sdk/validator/validate.js.map +1 -0
- package/build/src/core/531-rule.d.ts +26 -0
- package/build/src/core/531-rule.js +96 -0
- package/build/src/core/531-rule.js.map +1 -0
- package/build/src/core/auth.d.ts +1 -0
- package/build/src/core/auth.js +15 -0
- package/build/src/core/auth.js.map +1 -0
- package/build/src/core/consent-manager.d.ts +17 -0
- package/build/src/core/consent-manager.js +104 -0
- package/build/src/core/consent-manager.js.map +1 -0
- package/build/src/core/csp.d.ts +12 -0
- package/build/src/core/csp.js +20 -0
- package/build/src/core/csp.js.map +1 -0
- package/build/src/core/engagement-analyzer.d.ts +42 -0
- package/build/src/core/engagement-analyzer.js +71 -0
- package/build/src/core/engagement-analyzer.js.map +1 -0
- package/build/src/core/governor.d.ts +104 -0
- package/build/src/core/governor.js +371 -0
- package/build/src/core/governor.js.map +1 -0
- package/build/src/core/life-area-mapper.d.ts +39 -0
- package/build/src/core/life-area-mapper.js +73 -0
- package/build/src/core/life-area-mapper.js.map +1 -0
- package/build/src/core/methodology.d.ts +39 -0
- package/build/src/core/methodology.js +164 -0
- package/build/src/core/methodology.js.map +1 -0
- package/build/src/core/pingala.d.ts +25 -0
- package/build/src/core/pingala.js +56 -0
- package/build/src/core/pingala.js.map +1 -0
- package/build/src/core/sdk-adapter.d.ts +8 -0
- package/build/src/core/sdk-adapter.js +34 -0
- package/build/src/core/sdk-adapter.js.map +1 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +333 -0
- package/build/src/index.js.map +1 -0
- package/build/src/test-l3.d.ts +1 -0
- package/build/src/test-l3.js +35 -0
- package/build/src/test-l3.js.map +1 -0
- package/build/src/tools/audit-workspace.d.ts +16 -0
- package/build/src/tools/audit-workspace.js +39 -0
- package/build/src/tools/audit-workspace.js.map +1 -0
- package/build/src/tools/calculate-csi.d.ts +24 -0
- package/build/src/tools/calculate-csi.js +29 -0
- package/build/src/tools/calculate-csi.js.map +1 -0
- package/build/src/tools/cs-audit.d.ts +54 -0
- package/build/src/tools/cs-audit.js +310 -0
- package/build/src/tools/cs-audit.js.map +1 -0
- package/build/src/tools/get-governance-context.d.ts +11 -0
- package/build/src/tools/get-governance-context.js +16 -0
- package/build/src/tools/get-governance-context.js.map +1 -0
- package/build/src/tools/validate-stack-change.d.ts +41 -0
- package/build/src/tools/validate-stack-change.js +35 -0
- package/build/src/tools/validate-stack-change.js.map +1 -0
- package/build/test-l3.d.ts +1 -0
- package/build/test-l3.js +35 -0
- package/build/test-l3.js.map +1 -0
- package/build/tools/analyze-stack.d.ts +40 -0
- package/build/tools/analyze-stack.js +121 -0
- package/build/tools/analyze-stack.js.map +1 -0
- package/build/tools/audit-workspace.d.ts +16 -0
- package/build/tools/audit-workspace.js +39 -0
- package/build/tools/audit-workspace.js.map +1 -0
- package/build/tools/calculate-csi.d.ts +26 -0
- package/build/tools/calculate-csi.js +30 -0
- package/build/tools/calculate-csi.js.map +1 -0
- package/build/tools/cs-audit.d.ts +43 -0
- package/build/tools/cs-audit.js +330 -0
- package/build/tools/cs-audit.js.map +1 -0
- package/build/tools/get-governance-context.d.ts +11 -0
- package/build/tools/get-governance-context.js +61 -0
- package/build/tools/get-governance-context.js.map +1 -0
- package/build/tools/validate-stack-change.d.ts +41 -0
- package/build/tools/validate-stack-change.js +54 -0
- package/build/tools/validate-stack-change.js.map +1 -0
- package/package.json +34 -0
- package/scripts/cloud-bridge.js +62 -0
- package/scripts/generate-token.js +13 -0
- package/src/core/531-rule.ts +148 -0
- package/src/core/auth.ts +42 -0
- package/src/core/consent-manager.ts +134 -0
- package/src/core/csp.ts +40 -0
- package/src/core/engagement-analyzer.ts +122 -0
- package/src/core/governor.ts +522 -0
- package/src/core/life-area-mapper.ts +138 -0
- package/src/core/methodology.ts +256 -0
- package/src/core/pingala.ts +77 -0
- package/src/core/sdk-adapter.ts +52 -0
- package/src/index.ts +562 -0
- package/src/test-l3.ts +45 -0
- package/src/tools/analyze-stack.ts +153 -0
- package/src/tools/audit-workspace.ts +50 -0
- package/src/tools/calculate-csi.ts +38 -0
- package/src/tools/cs-audit.ts +384 -0
- package/src/tools/get-governance-context.ts +69 -0
- package/src/tools/validate-stack-change.ts +71 -0
- package/src/types.d.ts +2 -0
- package/tsconfig.json +40 -0
- package/vercel.json +15 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { Rule531, type ToolInstance } from "./531-rule.js";
|
|
6
|
+
|
|
7
|
+
export interface MaturityState {
|
|
8
|
+
level: number;
|
|
9
|
+
level_name: string;
|
|
10
|
+
stability_days: number;
|
|
11
|
+
last_changed_at: string; // ISO date
|
|
12
|
+
readonly?: boolean; // If true, state cannot be persisted (e.g. cloud/stateless mode)
|
|
13
|
+
definition?: string;
|
|
14
|
+
primary_action?: string;
|
|
15
|
+
telemetry?: {
|
|
16
|
+
attention_depth: number; // 0-100
|
|
17
|
+
dependency_exposure: number; // 0-100
|
|
18
|
+
last_updated: string;
|
|
19
|
+
};
|
|
20
|
+
decision_stats?: {
|
|
21
|
+
total_validations: number;
|
|
22
|
+
justified_validations: number;
|
|
23
|
+
};
|
|
24
|
+
csi_baseline?: number;
|
|
25
|
+
csi_latest?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ProposedChange {
|
|
29
|
+
type: 'add_tool' | 'remove_tool' | 'change_role' | 'change_anchor' | 'audit';
|
|
30
|
+
tool_name: string;
|
|
31
|
+
proposed_role?: 'Anchor' | 'Active' | 'Supporting';
|
|
32
|
+
functionId?: string; // Horizon 1.5: Functional Slot/Room ID
|
|
33
|
+
contexts?: string[]; // Horizon 1.5: System contexts
|
|
34
|
+
isAdapter?: boolean; // Horizon 1.5: Bridge Coefficient flag
|
|
35
|
+
replaces_existing?: boolean;
|
|
36
|
+
replaced_tool?: string;
|
|
37
|
+
justification?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface GovernanceContext {
|
|
41
|
+
current_stack: {
|
|
42
|
+
anchor: ToolInstance | null;
|
|
43
|
+
active: ToolInstance[];
|
|
44
|
+
supporting: ToolInstance[];
|
|
45
|
+
};
|
|
46
|
+
functional_nodes: {
|
|
47
|
+
id: string;
|
|
48
|
+
role: string;
|
|
49
|
+
tools: string[];
|
|
50
|
+
}[];
|
|
51
|
+
maturity_level: number;
|
|
52
|
+
maturity_name: string;
|
|
53
|
+
stability_days: number;
|
|
54
|
+
csi_latest: number;
|
|
55
|
+
allowed_actions: string[];
|
|
56
|
+
blocked_actions: string[];
|
|
57
|
+
progression: {
|
|
58
|
+
can_level_up: boolean;
|
|
59
|
+
next_level: number | null;
|
|
60
|
+
days_remaining: number;
|
|
61
|
+
csi_delta: number;
|
|
62
|
+
is_l2_eligible: boolean;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class Governor {
|
|
67
|
+
private static dataDir: string = (() => {
|
|
68
|
+
if (process.env.CSTACK_DATA_DIR) return process.env.CSTACK_DATA_DIR;
|
|
69
|
+
if (process.env.VERCEL) return "/tmp";
|
|
70
|
+
return path.join(os.homedir(), ".cstack-data");
|
|
71
|
+
})();
|
|
72
|
+
|
|
73
|
+
private static getFilePath(filename: string): string {
|
|
74
|
+
try {
|
|
75
|
+
if (!fs.existsSync(this.dataDir)) {
|
|
76
|
+
fs.mkdirSync(this.dataDir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(`[Governor] Warning: Could not create data directory ${this.dataDir}. Using /tmp fallback.`);
|
|
80
|
+
this.dataDir = "/tmp";
|
|
81
|
+
}
|
|
82
|
+
return path.join(this.dataDir, filename);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private static DEFAULT_STACK: ToolInstance[] = [
|
|
86
|
+
{ name: "Pingala", role: "Anchor", functionId: "Core-Governance", category: "Core" },
|
|
87
|
+
{ name: "Claude", role: "Active", functionId: "Interaction-Edge", category: "AI" },
|
|
88
|
+
{ name: "Vercel", role: "Active", functionId: "Cloud-Compute", category: "Infrastructure" },
|
|
89
|
+
{ name: "Cursor", role: "Active", functionId: "Development-Lattice", category: "IDE" },
|
|
90
|
+
{ name: "Express", role: "Supporting", functionId: "Transport-Node", category: "Web" },
|
|
91
|
+
{ name: "MCP-SDK", role: "Supporting", functionId: "Protocol-Core", category: "Library" },
|
|
92
|
+
{ name: "Zod", role: "Supporting", functionId: "Schema-Guardian", category: "Validation" },
|
|
93
|
+
{ name: "TypeScript", role: "Supporting", functionId: "Logic-Lattice", category: "Logic" },
|
|
94
|
+
{ name: "Git", role: "Supporting", functionId: "Source-History", category: "VCS" }
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
static getStack(): ToolInstance[] {
|
|
98
|
+
const filePath = this.getFilePath("stack-map.json");
|
|
99
|
+
// If we are in fallback /tmp, check if we have persistence
|
|
100
|
+
if (this.dataDir === "/tmp" && !process.env.VERCEL) {
|
|
101
|
+
// Local fallback without permissions = readonly default
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (fs.existsSync(filePath)) {
|
|
105
|
+
try {
|
|
106
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
107
|
+
return data.tools || this.DEFAULT_STACK;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
console.error("[Governor] Error reading stack-map.json:", e);
|
|
110
|
+
return this.DEFAULT_STACK;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return this.DEFAULT_STACK;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static saveStack(tools: ToolInstance[]): void {
|
|
117
|
+
const state = this.getMaturityState();
|
|
118
|
+
if (state.readonly) return; // Skip persistence in stateless mode
|
|
119
|
+
|
|
120
|
+
const filePath = this.getFilePath("stack-map.json");
|
|
121
|
+
try {
|
|
122
|
+
fs.writeFileSync(filePath, JSON.stringify({ tools }, null, 2));
|
|
123
|
+
|
|
124
|
+
// Update stability
|
|
125
|
+
state.last_changed_at = new Date().toISOString();
|
|
126
|
+
this.saveMaturityState(state);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.error("[Governor] Warning: Could not save stack-map.json", e);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static getMaturityState(): MaturityState {
|
|
133
|
+
const filePath = this.getFilePath("maturity-state.json");
|
|
134
|
+
const defaultState: MaturityState = {
|
|
135
|
+
level: 1,
|
|
136
|
+
level_name: "Fragmented",
|
|
137
|
+
stability_days: 0,
|
|
138
|
+
last_changed_at: new Date().toISOString(),
|
|
139
|
+
readonly: this.dataDir === "/tmp" && process.env.NODE_ENV === "production"
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (fs.existsSync(filePath)) {
|
|
143
|
+
try {
|
|
144
|
+
const state = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
145
|
+
|
|
146
|
+
// Calculate actual stability days
|
|
147
|
+
const lastChanged = new Date(state.last_changed_at);
|
|
148
|
+
const now = new Date();
|
|
149
|
+
const diffTime = Math.abs(now.getTime() - lastChanged.getTime());
|
|
150
|
+
state.stability_days = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
151
|
+
|
|
152
|
+
return state;
|
|
153
|
+
} catch (e) {
|
|
154
|
+
console.error("[Governor] Error reading maturity-state.json:", e);
|
|
155
|
+
return defaultState;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return defaultState;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static saveMaturityState(state: MaturityState): void {
|
|
162
|
+
if (state.readonly) return; // Skip persistence in stateless mode
|
|
163
|
+
|
|
164
|
+
const filePath = this.getFilePath("maturity-state.json");
|
|
165
|
+
try {
|
|
166
|
+
fs.writeFileSync(filePath, JSON.stringify(state, null, 2));
|
|
167
|
+
} catch (e) {
|
|
168
|
+
console.error("[Governor] Warning: Could not save maturity state", e);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static recordTelemetry(data: { attention_depth?: number; dependency_exposure?: number }): void {
|
|
173
|
+
const state = this.getMaturityState();
|
|
174
|
+
if (state.readonly) return;
|
|
175
|
+
|
|
176
|
+
state.telemetry = {
|
|
177
|
+
attention_depth: data.attention_depth ?? state.telemetry?.attention_depth ?? 50,
|
|
178
|
+
dependency_exposure: data.dependency_exposure ?? state.telemetry?.dependency_exposure ?? 50,
|
|
179
|
+
last_updated: new Date().toISOString()
|
|
180
|
+
};
|
|
181
|
+
this.saveMaturityState(state);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
static recordValidation(justified: boolean): void {
|
|
185
|
+
const state = this.getMaturityState();
|
|
186
|
+
if (state.readonly) return;
|
|
187
|
+
|
|
188
|
+
if (!state.decision_stats) {
|
|
189
|
+
state.decision_stats = { total_validations: 0, justified_validations: 0 };
|
|
190
|
+
}
|
|
191
|
+
state.decision_stats.total_validations++;
|
|
192
|
+
if (justified) state.decision_stats.justified_validations++;
|
|
193
|
+
this.saveMaturityState(state);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
static updateCsi(score: number): void {
|
|
197
|
+
const state = this.getMaturityState();
|
|
198
|
+
if (state.readonly) return;
|
|
199
|
+
|
|
200
|
+
if (state.csi_baseline === undefined) {
|
|
201
|
+
state.csi_baseline = score;
|
|
202
|
+
}
|
|
203
|
+
state.csi_latest = score;
|
|
204
|
+
this.saveMaturityState(state);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
static getDecisionProvenanceScore(): number {
|
|
208
|
+
const state = this.getMaturityState();
|
|
209
|
+
if (!state.decision_stats || state.decision_stats.total_validations === 0) return 50;
|
|
210
|
+
return Math.round((state.decision_stats.justified_validations / state.decision_stats.total_validations) * 100);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static getStackDriftScore(): { score: number; signals: string[]; summary: string } {
|
|
214
|
+
const tools = this.getStack();
|
|
215
|
+
const state = this.getMaturityState();
|
|
216
|
+
const validation = Rule531.validate({ tools });
|
|
217
|
+
|
|
218
|
+
let score = validation.score;
|
|
219
|
+
const signals = [...validation.violations];
|
|
220
|
+
|
|
221
|
+
// Temporal deductions
|
|
222
|
+
const lastChanged = new Date(state.last_changed_at);
|
|
223
|
+
const now = new Date();
|
|
224
|
+
const diffDays = Math.floor(Math.abs(now.getTime() - lastChanged.getTime()) / (1000 * 60 * 60 * 24));
|
|
225
|
+
|
|
226
|
+
if (diffDays > 0) {
|
|
227
|
+
const temporalPenalty = Math.min(20, diffDays * 5);
|
|
228
|
+
score -= temporalPenalty;
|
|
229
|
+
if (temporalPenalty > 0) {
|
|
230
|
+
signals.push(`Attention Erosion: ${diffDays} days since last protocol synthesis (-${temporalPenalty} points)`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Anchor check (specifically for drift signal)
|
|
235
|
+
if (!tools.some(t => t.role === 'Anchor')) {
|
|
236
|
+
// Rule531 might already have this in recommendations, but let's ensure it impacts score/signals
|
|
237
|
+
if (!signals.some(s => s.includes("Anchor"))) {
|
|
238
|
+
score -= 10;
|
|
239
|
+
signals.push("Anchor Void: No center of truth established (-10 points)");
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
score = Math.max(0, score);
|
|
244
|
+
|
|
245
|
+
let summary = "Maintaining Crystalline Geometry.";
|
|
246
|
+
if (score < 85) summary = "Minor drift detected. Review Supporting nodes.";
|
|
247
|
+
if (score < 70) summary = "Significant architectural erosion. Audit required.";
|
|
248
|
+
if (score < 50) summary = "Systemic collapse risk. Execute rapid reversal.";
|
|
249
|
+
|
|
250
|
+
return { score, signals, summary };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
static validateStackChange(change: ProposedChange, stackOverride?: ToolInstance[]) {
|
|
254
|
+
const currentStack = stackOverride || this.getStack();
|
|
255
|
+
const state = this.getMaturityState();
|
|
256
|
+
|
|
257
|
+
// Rule 1: 5:3:1 Enforcement
|
|
258
|
+
const validation = this.check531Rules(currentStack, change);
|
|
259
|
+
if (!validation.allowed) return validation;
|
|
260
|
+
|
|
261
|
+
// Rule 3: Maturity Gates
|
|
262
|
+
const gate = this.enforceMaturityGates(state, change);
|
|
263
|
+
if (!gate.allowed) return gate;
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
allowed: true,
|
|
267
|
+
reason: "Compliant with the Conscious Stack Protocol (CSP) and Maturity Gates",
|
|
268
|
+
impact: {
|
|
269
|
+
stability_reset: true,
|
|
270
|
+
new_stability_days: 0
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private static check531Rules(currentStack: ToolInstance[], change: ProposedChange) {
|
|
276
|
+
const getRoleNodeCount = (tools: ToolInstance[], role: string) => {
|
|
277
|
+
const roleTools = tools.filter(t => t.role === role);
|
|
278
|
+
// In Fractal logic, a core role is only counted if it represents a UNIQUE slot
|
|
279
|
+
// UNLESS it's an anchor of a sub-stack that is being promoted to a higher stack.
|
|
280
|
+
const slots = new Set(roleTools.filter(t => t.functionId).map(t => t.functionId));
|
|
281
|
+
const unclassifiedCount = roleTools.filter(t => !t.functionId).length;
|
|
282
|
+
return slots.size + unclassifiedCount;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const counts = {
|
|
286
|
+
anchor: getRoleNodeCount(currentStack, 'Anchor'),
|
|
287
|
+
active: getRoleNodeCount(currentStack, 'Active'),
|
|
288
|
+
supporting: getRoleNodeCount(currentStack, 'Supporting')
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
if (change.type === 'add_tool' || change.type === 'change_role') {
|
|
292
|
+
const role = change.proposed_role;
|
|
293
|
+
const targetFunctionId = change.functionId;
|
|
294
|
+
|
|
295
|
+
// Check if this tool is being added to an EXISTING functional node (Fractal Slot)
|
|
296
|
+
const existingNodeTools = targetFunctionId ? currentStack.filter(t => t.functionId === targetFunctionId) : [];
|
|
297
|
+
const isSubstack = existingNodeTools.length > 0;
|
|
298
|
+
|
|
299
|
+
if (isSubstack) {
|
|
300
|
+
// FRACTAL RULE: If adding to a sub-stack, check if we are creating a Sub-stack Anchor conflict
|
|
301
|
+
if (role === 'Anchor' && existingNodeTools.some(t => t.role === 'Anchor')) {
|
|
302
|
+
const currentSubAnchor = existingNodeTools.find(t => t.role === 'Anchor');
|
|
303
|
+
return {
|
|
304
|
+
allowed: false,
|
|
305
|
+
reason: `Fractal Violation: Sub-stack '${targetFunctionId}' already has an Anchor (${currentSubAnchor?.name}). Only one tool can be the 'Visible' gateway for this slot.`,
|
|
306
|
+
alternatives: [
|
|
307
|
+
`Demote ${change.tool_name} to Supporting within the ${targetFunctionId} sub-stack`,
|
|
308
|
+
`Replace ${currentSubAnchor?.name} as the primary gateway for this slot`
|
|
309
|
+
]
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// If the sub-stack currently HAS NO anchor, and we are adding a non-anchor, warn but allow (will trigger audit violation)
|
|
314
|
+
return { allowed: true };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// CORE STACK LIMITS (Slot-based)
|
|
318
|
+
if (role === 'Anchor') {
|
|
319
|
+
if (counts.anchor >= 1 && !change.replaces_existing) {
|
|
320
|
+
const currentAnchor = currentStack.find(t => t.role === 'Anchor');
|
|
321
|
+
return {
|
|
322
|
+
allowed: false,
|
|
323
|
+
reason: `Protocol violation: Only 1 Anchor Node permitted in the Core Stack. Current anchor: ${currentAnchor?.name}`,
|
|
324
|
+
alternatives: [
|
|
325
|
+
`Cluster ${change.tool_name} into the existing Anchor slot (building a sub-stack)`,
|
|
326
|
+
`Replace ${currentAnchor?.name} with ${change.tool_name}`,
|
|
327
|
+
`Assign ${change.tool_name} as Active instead`
|
|
328
|
+
]
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
} else if (role === 'Active') {
|
|
332
|
+
if (counts.active >= 3 && !change.replaces_existing) {
|
|
333
|
+
return {
|
|
334
|
+
allowed: false,
|
|
335
|
+
reason: `Protocol violation: Max 3 Active Slots permitted. Your Core Stack is congested.`,
|
|
336
|
+
alternatives: [
|
|
337
|
+
`Cluster ${change.tool_name} into an existing Active slot (e.g., as a supporting tool in a sub-stack)`,
|
|
338
|
+
"Archive least-used Active node",
|
|
339
|
+
`Move ${change.tool_name} to Supporting tier`
|
|
340
|
+
]
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
} else if (role === 'Supporting') {
|
|
344
|
+
if (counts.supporting >= 5 && !change.replaces_existing) {
|
|
345
|
+
return {
|
|
346
|
+
allowed: false,
|
|
347
|
+
reason: `Protocol violation: Max 5 Supporting Slots permitted in the Core Stack.`,
|
|
348
|
+
alternatives: [
|
|
349
|
+
`Nest ${change.tool_name} inside an existing Supporting sub-stack`,
|
|
350
|
+
"Archive least-used Supporting node",
|
|
351
|
+
"Promote this to Active if critical (requires archiving an Active slot)"
|
|
352
|
+
]
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return { allowed: true };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private static enforceMaturityGates(state: MaturityState, change: ProposedChange) {
|
|
362
|
+
const GATES: Record<number, any> = {
|
|
363
|
+
1: {
|
|
364
|
+
level_name: "Fragmented",
|
|
365
|
+
min_stability_days: 7, // Stability required to REACH Level 2
|
|
366
|
+
allowed_changes: ["remove_tool", "audit", "emergency_subtract"],
|
|
367
|
+
blocked_changes: ["add_tool", "change_anchor"],
|
|
368
|
+
definition: "Tools and processes are random, chaotic, and uncoordinated.",
|
|
369
|
+
primary_action: "Audit & Eliminate. Reduce tool count by 30%.",
|
|
370
|
+
message: "Level 1: Focus on subtraction and stabilization only"
|
|
371
|
+
},
|
|
372
|
+
2: {
|
|
373
|
+
level_name: "Siloed",
|
|
374
|
+
min_stability_days: 14, // Stability required to REACH Level 3
|
|
375
|
+
allowed_changes: ["remove_tool", "audit", "change_role"],
|
|
376
|
+
blocked_changes: ["add_tool", "change_anchor"],
|
|
377
|
+
definition: "Structure exists, but systems operate in isolation.",
|
|
378
|
+
primary_action: "Standardize. Create specific 'Anchors' for each workflow.",
|
|
379
|
+
message: "Level 2: Maintain 14 days stability before additions"
|
|
380
|
+
},
|
|
381
|
+
3: {
|
|
382
|
+
level_name: "Integrated",
|
|
383
|
+
min_stability_days: 30, // Stability required to REACH Level 4
|
|
384
|
+
allowed_changes: ["remove_tool", "audit", "add_tool", "change_role"],
|
|
385
|
+
blocked_changes: ["change_anchor"],
|
|
386
|
+
definition: "Data flows between systems; reduced friction.",
|
|
387
|
+
primary_action: "Automate. Use APIs to connect Edges.",
|
|
388
|
+
message: "Level 3: Can adjust Active/Supporting after 30 days stability"
|
|
389
|
+
},
|
|
390
|
+
4: {
|
|
391
|
+
level_name: "Aligned",
|
|
392
|
+
min_stability_days: 90, // Stability required to REACH Level 5
|
|
393
|
+
allowed_changes: ["remove_tool", "audit", "add_tool", "change_role", "change_anchor"],
|
|
394
|
+
blocked_changes: [],
|
|
395
|
+
definition: "Stack reflects values, strategy, and purpose.",
|
|
396
|
+
primary_action: "Refine. Align rituals with tool usage.",
|
|
397
|
+
message: "Level 4: All changes permitted with 90+ days stability"
|
|
398
|
+
},
|
|
399
|
+
5: {
|
|
400
|
+
level_name: "Resonant",
|
|
401
|
+
min_stability_days: 180,
|
|
402
|
+
allowed_changes: ["all"],
|
|
403
|
+
blocked_changes: [],
|
|
404
|
+
definition: "Tech amplifies unique human value and signal.",
|
|
405
|
+
primary_action: "Transcend. The stack becomes invisible.",
|
|
406
|
+
message: "Level 5: Mature stack, trust your judgment"
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const gate = GATES[state.level];
|
|
411
|
+
|
|
412
|
+
// Update state with metadata if missing
|
|
413
|
+
if (!state.level_name || state.level_name !== gate.level_name) {
|
|
414
|
+
state.level_name = gate.level_name;
|
|
415
|
+
state.definition = gate.definition;
|
|
416
|
+
state.primary_action = gate.primary_action;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Action check (Subtraction is ALWAYS allowed regardless of stability)
|
|
420
|
+
if (change.type === 'remove_tool' || change.type === 'audit') {
|
|
421
|
+
return { allowed: true };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Stability check for ADDITIONS/CHANGES
|
|
425
|
+
// Rules are based on the NEXT gate. If we are L2, we are subject to the L2 "maintenance" rules.
|
|
426
|
+
const currentStability = state.stability_days;
|
|
427
|
+
|
|
428
|
+
// Block additions if current level stability requirement isn't met or action is generally blocked
|
|
429
|
+
if (gate.blocked_changes.includes(change.type)) {
|
|
430
|
+
return {
|
|
431
|
+
allowed: false,
|
|
432
|
+
reason: `${gate.message}. Action '${change.type}' is unauthorized at the ${gate.level_name} stage.`,
|
|
433
|
+
gate_requirements: gate
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Special rule: Stability threshold for any "positive" change (adding/moving)
|
|
438
|
+
const isExpansion = change.type === 'add_tool' || change.type === 'change_role' || change.type === 'change_anchor';
|
|
439
|
+
const prevGateStability = state.level > 1 ? GATES[state.level - 1].min_stability_days : 0;
|
|
440
|
+
|
|
441
|
+
if (currentStability < prevGateStability && isExpansion) {
|
|
442
|
+
return {
|
|
443
|
+
allowed: false,
|
|
444
|
+
reason: `Stability gate: Reach ${prevGateStability} days of stability in the ${gate.level_name} stage before expanding. Current: ${currentStability} days.`,
|
|
445
|
+
gate_requirements: {
|
|
446
|
+
required_days: prevGateStability,
|
|
447
|
+
current_days: currentStability
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return { allowed: true };
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static getGovernanceContext(): GovernanceContext {
|
|
456
|
+
const tools = this.getStack();
|
|
457
|
+
const state = this.getMaturityState();
|
|
458
|
+
|
|
459
|
+
// Group into Functional Nodes for the context
|
|
460
|
+
const nodeMap: Record<string, { role: string, tools: string[] }> = {};
|
|
461
|
+
const unclassified: any[] = [];
|
|
462
|
+
|
|
463
|
+
tools.forEach(t => {
|
|
464
|
+
if (t.functionId) {
|
|
465
|
+
if (!nodeMap[t.functionId]) nodeMap[t.functionId] = { role: t.role, tools: [] };
|
|
466
|
+
nodeMap[t.functionId].tools.push(t.name);
|
|
467
|
+
} else {
|
|
468
|
+
unclassified.push({ id: t.name, role: t.role, tools: [t.name] });
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const functionalNodes = [
|
|
473
|
+
...Object.entries(nodeMap).map(([id, data]) => ({ id, ...data })),
|
|
474
|
+
...unclassified
|
|
475
|
+
];
|
|
476
|
+
|
|
477
|
+
// Determine allowed/blocked actions for UI/Context
|
|
478
|
+
const allActions: Array<'add_tool' | 'remove_tool' | 'change_role' | 'change_anchor'> = ["add_tool", "remove_tool", "change_role", "change_anchor"];
|
|
479
|
+
const blocked = allActions.filter(a => {
|
|
480
|
+
const res = this.validateStackChange({ type: a, tool_name: '' });
|
|
481
|
+
return !res.allowed;
|
|
482
|
+
});
|
|
483
|
+
const allowed = allActions.filter(a => !blocked.includes(a));
|
|
484
|
+
|
|
485
|
+
// Progression check
|
|
486
|
+
const nextLevel = state.level < 5 ? state.level + 1 : null;
|
|
487
|
+
const canLevelUp = nextLevel && state.stability_days >= this.getNextGateRequiredDays(state.level);
|
|
488
|
+
const csiDelta = (state.csi_latest || 0) - (state.csi_baseline || state.csi_latest || 0);
|
|
489
|
+
|
|
490
|
+
return {
|
|
491
|
+
current_stack: {
|
|
492
|
+
anchor: tools.find(t => t.role === 'Anchor') || null,
|
|
493
|
+
active: tools.filter(t => t.role === 'Active'),
|
|
494
|
+
supporting: tools.filter(t => t.role === 'Supporting')
|
|
495
|
+
},
|
|
496
|
+
functional_nodes: functionalNodes,
|
|
497
|
+
maturity_level: state.level,
|
|
498
|
+
maturity_name: state.level_name || "Unknown",
|
|
499
|
+
stability_days: state.stability_days,
|
|
500
|
+
csi_latest: state.csi_latest || 0,
|
|
501
|
+
allowed_actions: allowed,
|
|
502
|
+
blocked_actions: blocked, progression: {
|
|
503
|
+
can_level_up: !!canLevelUp,
|
|
504
|
+
next_level: nextLevel,
|
|
505
|
+
days_remaining: Math.max(0, this.getNextGateRequiredDays(state.level) - state.stability_days),
|
|
506
|
+
csi_delta: csiDelta,
|
|
507
|
+
is_l2_eligible: csiDelta >= 10
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
private static getNextGateRequiredDays(level: number): number {
|
|
513
|
+
const GATES_DAYS: Record<number, number> = {
|
|
514
|
+
1: 7,
|
|
515
|
+
2: 14,
|
|
516
|
+
3: 30,
|
|
517
|
+
4: 90,
|
|
518
|
+
5: 180
|
|
519
|
+
};
|
|
520
|
+
return GATES_DAYS[level] || 0;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { ToolInstance } from "./531-rule.js";
|
|
2
|
+
import { MethodologyLoader, BaguaCategory, InnerDiamondCategory } from "./methodology.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* LifeAreaAnalysis: The result of mapping a stack to life areas.
|
|
6
|
+
*/
|
|
7
|
+
export interface LifeAreaAnalysis {
|
|
8
|
+
areas: {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
tools: string[];
|
|
12
|
+
description: string;
|
|
13
|
+
}[];
|
|
14
|
+
gaps: string[];
|
|
15
|
+
overIndexed: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* InnerDiamondAnalysis: The result of mapping a stack to deep identity patterns (L3).
|
|
20
|
+
*/
|
|
21
|
+
export interface InnerDiamondAnalysis {
|
|
22
|
+
reflections: {
|
|
23
|
+
id: string;
|
|
24
|
+
label: string;
|
|
25
|
+
observation: string;
|
|
26
|
+
prompt: string;
|
|
27
|
+
}[];
|
|
28
|
+
forecast: {
|
|
29
|
+
sovereignty_score: number;
|
|
30
|
+
primary_risk: string;
|
|
31
|
+
evolution_path: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* LifeAreaMapper: Interface for mapping tools to life areas/domains.
|
|
37
|
+
*/
|
|
38
|
+
export interface LifeAreaMapper {
|
|
39
|
+
mapToolsToAreas(tools: ToolInstance[], practitionerMode?: boolean): LifeAreaAnalysis;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* BaguaMapper: The default implementation using the 9-room Bagua system.
|
|
44
|
+
*/
|
|
45
|
+
export class BaguaMapper implements LifeAreaMapper {
|
|
46
|
+
private categories: BaguaCategory[];
|
|
47
|
+
|
|
48
|
+
constructor() {
|
|
49
|
+
this.categories = MethodologyLoader.loadBaguaCategories();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Maps tools to Bagua rooms and returns sanitized labels.
|
|
54
|
+
*/
|
|
55
|
+
mapToolsToAreas(tools: ToolInstance[], practitionerMode: boolean = false): LifeAreaAnalysis {
|
|
56
|
+
const mapping = this.categories.map(cat => ({
|
|
57
|
+
id: cat.name, // Internal ID (e.g., Li, Kun)
|
|
58
|
+
label: practitionerMode ? cat.name : (cat.userFacingLabel || cat.description),
|
|
59
|
+
tools: tools.filter(t => t.functionId === cat.name).map(t => t.name),
|
|
60
|
+
description: cat.description
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
const gaps = mapping.filter(m => m.tools.length === 0).map(m => m.label);
|
|
64
|
+
const overIndexed = mapping.filter(m => m.tools.length > 2).map(m => m.label);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
areas: mapping,
|
|
68
|
+
gaps,
|
|
69
|
+
overIndexed
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* DiamondMapper: L3 Identity and Purpose mapping.
|
|
76
|
+
*/
|
|
77
|
+
export class DiamondMapper {
|
|
78
|
+
private categories: InnerDiamondCategory[];
|
|
79
|
+
|
|
80
|
+
constructor() {
|
|
81
|
+
this.categories = MethodologyLoader.loadInnerDiamondCategories();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Generates L3 reflection points based on the tool stack.
|
|
86
|
+
*/
|
|
87
|
+
mapToDiamond(tools: ToolInstance[], practitionerMode: boolean = false): InnerDiamondAnalysis {
|
|
88
|
+
// Logic for L3 is more qualitative and pattern-based
|
|
89
|
+
const prompts = MethodologyLoader.loadConsentPrompts(); // Not exactly what we need, but we can have specific prompts
|
|
90
|
+
|
|
91
|
+
const reflections = this.categories.map(cat => ({
|
|
92
|
+
id: cat.name,
|
|
93
|
+
label: practitionerMode ? cat.name : (cat.userFacingLabel || cat.name),
|
|
94
|
+
observation: this.getObservationForCategory(cat.name, tools),
|
|
95
|
+
prompt: this.getPromptForCategory(cat.name, tools)
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
// Calculate a proxy sovereignty score based on variety of functions and tool count
|
|
99
|
+
const uniqueFunctions = new Set(tools.map(t => t.functionId).filter(Boolean)).size;
|
|
100
|
+
const sovScore = Math.min(100, Math.round((uniqueFunctions / 9) * 100));
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
reflections,
|
|
104
|
+
forecast: {
|
|
105
|
+
sovereignty_score: sovScore,
|
|
106
|
+
primary_risk: tools.length > 9 ? "Conscious Fragmentation" : "Dependency Lock-in",
|
|
107
|
+
evolution_path: "Move from 'tool-centric' to 'process-centric' autonomy."
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private getObservationForCategory(cat: string, tools: ToolInstance[]): string {
|
|
113
|
+
switch (cat) {
|
|
114
|
+
case 'Identity':
|
|
115
|
+
return tools.length > 0 ? `Your choices in ${tools[0].name} suggest a focus on efficiency.` : "No clear identity pattern detected.";
|
|
116
|
+
case 'Purpose':
|
|
117
|
+
const anchors = tools.filter(t => t.role === 'Anchor');
|
|
118
|
+
return anchors.length > 0 ? `Your Anchor (${anchors[0].name}) is the seat of your daily purpose.` : "Your purpose lacks a central digital anchor.";
|
|
119
|
+
case 'Sovereignty':
|
|
120
|
+
return `You are currently balancing ${tools.length} nodes of external dependencies.`;
|
|
121
|
+
default:
|
|
122
|
+
return "Reflecting on pattern...";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private getPromptForCategory(cat: string, tools: ToolInstance[]): string {
|
|
127
|
+
switch (cat) {
|
|
128
|
+
case 'Identity':
|
|
129
|
+
return "Who would you be if this stack was reset tomorrow?";
|
|
130
|
+
case 'Purpose':
|
|
131
|
+
return "Does this stack serve your mission, or does it define it?";
|
|
132
|
+
case 'Sovereignty':
|
|
133
|
+
return "Where are you choosing not to see a dependency?";
|
|
134
|
+
default:
|
|
135
|
+
return "What is ready to evolve?";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|