@aikdna/kdna-studio-cli 0.8.17 → 0.9.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/README.md +15 -18
- package/bin/kdna-studio.js +32 -232
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Distillation-first authoring is domain-first: declare the target domain, owner s
|
|
|
8
8
|
|
|
9
9
|
This package provides the `kdna-studio` command. It creates Studio projects,
|
|
10
10
|
imports evidence, manages judgment cards, records optional review/provenance
|
|
11
|
-
signals, compiles
|
|
11
|
+
signals, compiles project content, and exports canonical `.kdna`
|
|
12
12
|
assets with build reports.
|
|
13
13
|
|
|
14
14
|
It is intentionally separate from `@aikdna/kdna-cli`:
|
|
@@ -37,7 +37,7 @@ kdna-studio target declare my_domain \
|
|
|
37
37
|
--task "longform article review" \
|
|
38
38
|
--include "argument structure,tone,revision" \
|
|
39
39
|
--exclude "life habits,food preference"
|
|
40
|
-
kdna-studio source
|
|
40
|
+
kdna-studio source my_domain
|
|
41
41
|
kdna-studio distill my_domain --candidates candidates.json
|
|
42
42
|
kdna-studio candidate list my_domain
|
|
43
43
|
kdna-studio candidate accept my_domain <candidate-id>
|
|
@@ -51,16 +51,16 @@ kdna-studio card add my_domain axiom \
|
|
|
51
51
|
--field failure_risk="generic advice" \
|
|
52
52
|
--field confidence='high' \
|
|
53
53
|
--field evidence_type='practice'
|
|
54
|
+
# Optional: record review provenance
|
|
54
55
|
kdna-studio card approve my_domain --all --by expert --statement "I confirm this judgment."
|
|
55
56
|
kdna-studio export my_domain --out dist/my_domain.kdna
|
|
56
57
|
```
|
|
57
58
|
|
|
58
59
|
Candidate promotion is scope-gated: only candidates with `status == accepted` and `scope_fit == true` are promoted to cards by default. Use `kdna-studio candidate override <project> <candidate-id>` only when a human intentionally overrides the scope gate.
|
|
59
60
|
|
|
60
|
-
The
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
requirements.
|
|
61
|
+
The Studio CLI exports complete, non-deprecated cards. Human Lock and other
|
|
62
|
+
provenance records are optional review evidence, not creation permission or
|
|
63
|
+
format-validity requirements.
|
|
64
64
|
|
|
65
65
|
After export, use the runtime CLI:
|
|
66
66
|
|
|
@@ -79,14 +79,11 @@ loading existing `.kdna` assets.
|
|
|
79
79
|
If you just installed and want to ship a KDNA asset without an LLM:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
# 1.
|
|
83
|
-
kdna-studio identity init --name "Your Name"
|
|
84
|
-
|
|
85
|
-
# 2. Create a project
|
|
82
|
+
# 1. Create a project
|
|
86
83
|
kdna-studio create my_domain --name @yourscope/my_domain
|
|
87
84
|
|
|
88
|
-
#
|
|
89
|
-
kdna-studio card add
|
|
85
|
+
# 2. Add at least one judgment card
|
|
86
|
+
kdna-studio card add my_domain axiom \
|
|
90
87
|
--field one_sentence='specific evidence outranks broad claims' \
|
|
91
88
|
--field full_statement='Always cite the specific source that supports a judgment; broad claims without evidence are the most common cause of bad agent advice.' \
|
|
92
89
|
--field why='because vague advice fails in production' \
|
|
@@ -96,13 +93,13 @@ kdna-studio card add . axiom \
|
|
|
96
93
|
--field confidence='high' \
|
|
97
94
|
--field evidence_type='practice'
|
|
98
95
|
|
|
99
|
-
#
|
|
100
|
-
kdna-studio card approve
|
|
96
|
+
# 3. Optional: approve and record Human Lock provenance
|
|
97
|
+
kdna-studio card approve my_domain --all --by me --statement "i confirm"
|
|
101
98
|
|
|
102
|
-
#
|
|
103
|
-
kdna-studio export
|
|
99
|
+
# 4. Export the asset
|
|
100
|
+
kdna-studio export my_domain --out my_domain.kdna
|
|
104
101
|
|
|
105
|
-
#
|
|
102
|
+
# 5. Verify with the runtime CLI
|
|
106
103
|
kdna load my_domain.kdna --profile=compact
|
|
107
104
|
```
|
|
108
105
|
|
|
@@ -157,7 +154,7 @@ kdna-studio identity show
|
|
|
157
154
|
## Import from existing KDNA or legacy folders
|
|
158
155
|
|
|
159
156
|
```bash
|
|
160
|
-
# Fork an existing .kdna asset (cards imported as draft
|
|
157
|
+
# Fork an existing canonical .kdna asset (cards are imported as draft)
|
|
161
158
|
kdna-studio create forked --from-kdna ./parent.kdna --name @scope/forked
|
|
162
159
|
|
|
163
160
|
# Migrate a legacy JSON source folder
|
package/bin/kdna-studio.js
CHANGED
|
@@ -410,10 +410,14 @@ function resetImportedIds() { _importedIds.clear(); }
|
|
|
410
410
|
function decodePayload(bytes, manifest = {}) {
|
|
411
411
|
const raw = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
|
|
412
412
|
const encoding = manifest.payload?.encoding || manifest.container?.payload_encoding || null;
|
|
413
|
-
if (encoding
|
|
414
|
-
|
|
413
|
+
if (encoding && encoding !== 'cbor') {
|
|
414
|
+
throw new Error(`unsupported payload encoding "${encoding}"; current .kdna assets require CBOR`);
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
return cbor.decode(raw);
|
|
418
|
+
} catch (error) {
|
|
419
|
+
throw new Error(`payload.kdnab is not valid CBOR: ${error.message}`);
|
|
415
420
|
}
|
|
416
|
-
return cbor.decode(raw);
|
|
417
421
|
}
|
|
418
422
|
|
|
419
423
|
// Runtime path: trust the producer (export-runtime) to have already shaped
|
|
@@ -561,97 +565,11 @@ function cardsFromRuntimePayload(payload) {
|
|
|
561
565
|
return cards;
|
|
562
566
|
}
|
|
563
567
|
|
|
564
|
-
function cardsFromLegacyPayload(payload) {
|
|
565
|
-
resetImportedIds();
|
|
566
|
-
const cards = [];
|
|
567
|
-
const judgment = payload.judgment || {};
|
|
568
|
-
const core = judgment.core || {};
|
|
569
|
-
const patterns = judgment.patterns || {};
|
|
570
|
-
|
|
571
|
-
for (const ax of (Array.isArray(core.axioms) ? core.axioms : [])) {
|
|
572
|
-
pushImportedCard(cards, 'axiom', {
|
|
573
|
-
one_sentence: ax.one_sentence || '',
|
|
574
|
-
full_statement: ax.full_statement || '',
|
|
575
|
-
why: ax.why || '',
|
|
576
|
-
applies_when: ax.applies_when || [],
|
|
577
|
-
does_not_apply_when: ax.does_not_apply_when || [],
|
|
578
|
-
failure_risk: ax.failure_risk || '',
|
|
579
|
-
}, ax.id || null);
|
|
580
|
-
}
|
|
581
|
-
for (const ont of (Array.isArray(core.ontology) ? core.ontology : [])) {
|
|
582
|
-
pushImportedCard(cards, 'ontology', {
|
|
583
|
-
one_sentence: ont.one_sentence || ont.essence || '',
|
|
584
|
-
essence: ont.essence || '',
|
|
585
|
-
boundary: ont.boundary || '',
|
|
586
|
-
trigger_signal: ont.trigger_signal || '',
|
|
587
|
-
}, ont.id || null);
|
|
588
|
-
}
|
|
589
|
-
for (const boundary of (Array.isArray(core.boundaries) ? core.boundaries : [])) {
|
|
590
|
-
pushImportedCard(cards, 'boundary', {
|
|
591
|
-
scope: boundary.scope || '',
|
|
592
|
-
out_of_scope: boundary.out_of_scope || '',
|
|
593
|
-
acceptable_exceptions: boundary.acceptable_exceptions || [],
|
|
594
|
-
}, boundary.id || null);
|
|
595
|
-
}
|
|
596
|
-
for (const risk of (Array.isArray(core.risks) ? core.risks : [])) {
|
|
597
|
-
pushImportedCard(cards, 'risk', risk, risk.id || null);
|
|
598
|
-
}
|
|
599
|
-
// Bug (#63): prior version skipped `core.stances` and
|
|
600
|
-
// `core.frameworks`, so a legacy asset that authored either type
|
|
601
|
-
// round-tripped out as zero cards. The fix adds both loops.
|
|
602
|
-
for (const stance of (Array.isArray(core.stances) ? core.stances : [])) {
|
|
603
|
-
pushImportedCard(cards, 'stance', stance, stance.id || null);
|
|
604
|
-
}
|
|
605
|
-
for (const fw of (Array.isArray(core.frameworks) ? core.frameworks : [])) {
|
|
606
|
-
pushImportedCard(cards, 'framework', fw, fw.id || null);
|
|
607
|
-
}
|
|
608
|
-
for (const term of (Array.isArray(patterns.terminology?.standard_terms) ? patterns.terminology?.standard_terms : [])) {
|
|
609
|
-
pushImportedCard(cards, 'term', term, term.id || null);
|
|
610
|
-
}
|
|
611
|
-
for (const banned of (Array.isArray(patterns.terminology?.banned_terms) ? patterns.terminology?.banned_terms : [])) {
|
|
612
|
-
pushImportedCard(cards, 'banned_term', banned, banned.id || null);
|
|
613
|
-
}
|
|
614
|
-
for (const ms of (Array.isArray(patterns.misunderstandings) ? patterns.misunderstandings : [])) {
|
|
615
|
-
pushImportedCard(cards, 'misunderstanding', {
|
|
616
|
-
wrong: ms.wrong || '',
|
|
617
|
-
correct: ms.correct || '',
|
|
618
|
-
key_distinction: ms.key_distinction || '',
|
|
619
|
-
why: ms.why || '',
|
|
620
|
-
applies_when: ms.applies_when || [],
|
|
621
|
-
does_not_apply_when: ms.does_not_apply_when || [],
|
|
622
|
-
failure_risk: ms.failure_risk || '',
|
|
623
|
-
}, ms.id || null);
|
|
624
|
-
}
|
|
625
|
-
for (const sc of (Array.isArray(patterns.self_check) ? patterns.self_check : [])) {
|
|
626
|
-
const question = typeof sc === 'string' ? sc : sc.question || '';
|
|
627
|
-
pushImportedCard(cards, 'self_check', { question }, sc.id || null);
|
|
628
|
-
}
|
|
629
|
-
for (const aesthetic of (Array.isArray(patterns.aesthetics) ? patterns.aesthetics : [])) {
|
|
630
|
-
pushImportedCard(cards, 'aesthetic', aesthetic, aesthetic.id || null);
|
|
631
|
-
}
|
|
632
|
-
for (const scene of (Array.isArray(judgment.scenarios?.scenes) ? judgment.scenarios?.scenes : [])) {
|
|
633
|
-
pushImportedCard(cards, 'scenario', scene, scene.id || null);
|
|
634
|
-
}
|
|
635
|
-
for (const item of (Array.isArray(judgment.cases?.cases) ? judgment.cases?.cases : [])) {
|
|
636
|
-
pushImportedCard(cards, 'case', item, item.id || null);
|
|
637
|
-
}
|
|
638
|
-
for (const chain of (Array.isArray(judgment.reasoning?.reasoning_chains) ? judgment.reasoning?.reasoning_chains : [])) {
|
|
639
|
-
pushImportedCard(cards, 'reasoning', chain, chain.id || null);
|
|
640
|
-
}
|
|
641
|
-
for (const stage of (Array.isArray(judgment.evolution?.stages) ? judgment.evolution?.stages : [])) {
|
|
642
|
-
pushImportedCard(cards, 'evolution_stage', stage, stage.id || null);
|
|
643
|
-
}
|
|
644
|
-
return cards;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
568
|
function cardsFromPayload(payload) {
|
|
648
569
|
if (!payload || typeof payload !== 'object') return [];
|
|
649
570
|
if (payload.profile === 'judgment-profile-v1' || payload.core || payload.source_cards) {
|
|
650
571
|
return cardsFromRuntimePayload(payload);
|
|
651
572
|
}
|
|
652
|
-
if (payload.kind === 'kdna.payload' || payload.judgment) {
|
|
653
|
-
return cardsFromLegacyPayload(payload);
|
|
654
|
-
}
|
|
655
573
|
return [];
|
|
656
574
|
}
|
|
657
575
|
|
|
@@ -688,7 +606,7 @@ function buildManifest(project, name) {
|
|
|
688
606
|
id: author.id || project.author?.id || undefined,
|
|
689
607
|
},
|
|
690
608
|
compatibility: { min_loader_version: '1.0.0', profile: 'judgment-profile-v1' },
|
|
691
|
-
payload: { path: 'payload.kdnab', encoding: '
|
|
609
|
+
payload: { path: 'payload.kdnab', encoding: 'cbor', encrypted: false },
|
|
692
610
|
summary: source.core_insight || project.release?.description || source.description || '',
|
|
693
611
|
description: source.description || project.release?.description || '',
|
|
694
612
|
language: source.default_language || project.default_language || (Array.isArray(source.languages) ? source.languages[0] : undefined),
|
|
@@ -821,6 +739,14 @@ function importFromKdna(kdnaPath) {
|
|
|
821
739
|
if (stats.size > 50 * 1024 * 1024) {
|
|
822
740
|
fail(`KDNA file too large (${(stats.size / (1024 * 1024)).toFixed(1)} MiB, max 50 MiB): ${absKdna}`);
|
|
823
741
|
}
|
|
742
|
+
let runtimeCore;
|
|
743
|
+
try { runtimeCore = require('@aikdna/kdna-core'); } catch {
|
|
744
|
+
fail('@aikdna/kdna-core is required to validate --from-kdna imports.');
|
|
745
|
+
}
|
|
746
|
+
const validation = runtimeCore.validate(absKdna);
|
|
747
|
+
if (!validation.overall_valid) {
|
|
748
|
+
fail(`Not a current .kdna asset: ${(validation.problems || []).join('; ')}`);
|
|
749
|
+
}
|
|
824
750
|
const zipBuf = fs.readFileSync(absKdna);
|
|
825
751
|
const entries = readZipEntries(zipBuf);
|
|
826
752
|
if (!entries.has('kdna.json')) fail('Not a valid .kdna asset: missing kdna.json');
|
|
@@ -834,122 +760,21 @@ function importFromKdna(kdnaPath) {
|
|
|
834
760
|
parent_asset_digest: manifest.content_digest || manifest.asset_digest || null,
|
|
835
761
|
};
|
|
836
762
|
|
|
837
|
-
//
|
|
838
|
-
//
|
|
839
|
-
// across KDNA_*.json files. Prefer payload.kdnab when present — it
|
|
840
|
-
// covers all 8+ card types (axiom / boundary / risk / aesthetic /
|
|
841
|
-
// ontology / misunderstanding / self_check / scenario / case /
|
|
842
|
-
// reasoning / evolution_stage / stance / framework / term / banned_term)
|
|
843
|
-
// via cardsFromRuntimePayload / cardsFromLegacyPayload.
|
|
763
|
+
// Current assets carry strict-CBOR `payload.kdnab`. Legacy source folders
|
|
764
|
+
// are migrated explicitly with --from-folder; they are not runtime assets.
|
|
844
765
|
const importedCards = [];
|
|
845
|
-
if (entries.has('payload.kdnab')) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
// Source-tree fallback — used when an imported source has no payload.kdnab
|
|
854
|
-
// (i.e. the asset predates the 0.7 split). Bug (#67): prior
|
|
855
|
-
// version only handled axiom / ontology / boundary / misunderstanding
|
|
856
|
-
// / self_check — 5 of the 14 card types — so every other type
|
|
857
|
-
// (risk / stance / framework / term / banned_term / aesthetic /
|
|
858
|
-
// scenario / case / reasoning / evolution_stage) round-tripped
|
|
859
|
-
// out as zero cards. The fix threads every type this CLI can
|
|
860
|
-
// import through, and prefers the same field-shape rules as
|
|
861
|
-
// cardsFromLegacyPayload so the round-trip is symmetric.
|
|
862
|
-
if (entries.has('KDNA_Core.json')) {
|
|
863
|
-
const core = JSON.parse(entries.get('KDNA_Core.json').toString());
|
|
864
|
-
for (const ax of (Array.isArray(core.axioms) ? core.axioms : [])) {
|
|
865
|
-
const fields = {};
|
|
866
|
-
for (const k of ['one_sentence','full_statement','why','applies_when','does_not_apply_when','failure_risk','confidence','evidence_type']) {
|
|
867
|
-
if (k in ax) fields[k] = ax[k];
|
|
868
|
-
}
|
|
869
|
-
importedCards.push(cardApi.createCard('axiom', fields));
|
|
870
|
-
}
|
|
871
|
-
for (const ont of (Array.isArray(core.ontology) ? core.ontology : [])) {
|
|
872
|
-
importedCards.push(cardApi.createCard('ontology', {
|
|
873
|
-
one_sentence: ont.one_sentence || ont.essence || '',
|
|
874
|
-
essence: ont.essence || '', boundary: ont.boundary || '',
|
|
875
|
-
trigger_signal: ont.trigger_signal || '',
|
|
876
|
-
}));
|
|
877
|
-
}
|
|
878
|
-
for (const b of (Array.isArray(core.boundaries) ? core.boundaries : [])) {
|
|
879
|
-
importedCards.push(cardApi.createCard('boundary', {
|
|
880
|
-
scope: b.scope || '', out_of_scope: b.out_of_scope || '',
|
|
881
|
-
acceptable_exceptions: b.acceptable_exceptions || [],
|
|
882
|
-
}));
|
|
883
|
-
}
|
|
884
|
-
// Accept risks as a top-level array (`risks`) or wrapped in `risk_model`
|
|
885
|
-
// (either as `{risks: [...]}` or as an array itself). Uses the same
|
|
886
|
-
// Array.isArray ladder pattern as the safe path at lines 1033-1040.
|
|
887
|
-
let risksSource = core.risks;
|
|
888
|
-
if (!Array.isArray(risksSource)) {
|
|
889
|
-
if (Array.isArray(core.risk_model)) risksSource = core.risk_model;
|
|
890
|
-
else if (Array.isArray(core.risk_model?.risks)) risksSource = core.risk_model.risks;
|
|
891
|
-
else risksSource = [];
|
|
892
|
-
}
|
|
893
|
-
for (const risk of risksSource) {
|
|
894
|
-
importedCards.push(cardApi.createCard('risk', risk.fields || risk));
|
|
895
|
-
}
|
|
896
|
-
for (const stance of (Array.isArray(core.stances) ? core.stances : [])) {
|
|
897
|
-
importedCards.push(cardApi.createCard('stance', stance.fields || stance));
|
|
898
|
-
}
|
|
899
|
-
for (const fw of (Array.isArray(core.frameworks) ? core.frameworks : [])) {
|
|
900
|
-
importedCards.push(cardApi.createCard('framework', fw.fields || fw));
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
if (entries.has('KDNA_Patterns.json')) {
|
|
904
|
-
const pat = JSON.parse(entries.get('KDNA_Patterns.json').toString());
|
|
905
|
-
for (const ms of (Array.isArray(pat.misunderstandings) ? pat.misunderstandings : [])) {
|
|
906
|
-
importedCards.push(cardApi.createCard('misunderstanding', {
|
|
907
|
-
wrong: ms.wrong || '', correct: ms.correct || '',
|
|
908
|
-
key_distinction: ms.key_distinction || '', why: ms.why || '',
|
|
909
|
-
}));
|
|
910
|
-
}
|
|
911
|
-
for (const sc of (Array.isArray(pat.self_check) ? pat.self_check : [])) {
|
|
912
|
-
const q = typeof sc === 'string' ? sc : sc.question || '';
|
|
913
|
-
importedCards.push(cardApi.createCard('self_check', { question: q }));
|
|
914
|
-
}
|
|
915
|
-
for (const aesthetic of (Array.isArray(pat.aesthetics) ? pat.aesthetics : [])) {
|
|
916
|
-
importedCards.push(cardApi.createCard('aesthetic', aesthetic.fields || aesthetic));
|
|
917
|
-
}
|
|
918
|
-
for (const term of (Array.isArray(pat.terminology?.standard_terms) ? pat.terminology?.standard_terms : [])) {
|
|
919
|
-
importedCards.push(cardApi.createCard('term', term));
|
|
920
|
-
}
|
|
921
|
-
for (const banned of (Array.isArray(pat.terminology?.banned_terms) ? pat.terminology?.banned_terms : [])) {
|
|
922
|
-
importedCards.push(cardApi.createCard('banned_term', banned));
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
if (entries.has('KDNA_Scenarios.json')) {
|
|
926
|
-
const scen = JSON.parse(entries.get('KDNA_Scenarios.json').toString());
|
|
927
|
-
for (const s of (Array.isArray(scen.scenes) ? scen.scenes : [])) {
|
|
928
|
-
importedCards.push(cardApi.createCard('scenario', s));
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
if (entries.has('KDNA_Cases.json')) {
|
|
932
|
-
const cases = JSON.parse(entries.get('KDNA_Cases.json').toString());
|
|
933
|
-
for (const c of (Array.isArray(cases.cases) ? cases.cases : [])) {
|
|
934
|
-
importedCards.push(cardApi.createCard('case', c));
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
if (entries.has('KDNA_Reasoning.json')) {
|
|
938
|
-
const reasoning = JSON.parse(entries.get('KDNA_Reasoning.json').toString());
|
|
939
|
-
for (const chain of (Array.isArray(reasoning.reasoning_chains) ? reasoning.reasoning_chains : [])) {
|
|
940
|
-
importedCards.push(cardApi.createCard('reasoning', chain));
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
if (entries.has('KDNA_Evolution.json')) {
|
|
944
|
-
const evolution = JSON.parse(entries.get('KDNA_Evolution.json').toString());
|
|
945
|
-
for (const stage of (Array.isArray(evolution.stages) ? evolution.stages : [])) {
|
|
946
|
-
importedCards.push(cardApi.createCard('evolution_stage', stage));
|
|
947
|
-
}
|
|
948
|
-
}
|
|
766
|
+
if (!entries.has('payload.kdnab')) {
|
|
767
|
+
fail('Not a current .kdna asset: missing payload.kdnab. Use --from-folder for legacy JSON source migration.');
|
|
768
|
+
}
|
|
769
|
+
try {
|
|
770
|
+
const payload = decodePayload(entries.get('payload.kdnab'), manifest);
|
|
771
|
+
importedCards.push(...cardsFromPayload(payload));
|
|
772
|
+
} catch (e) {
|
|
773
|
+
fail(`Could not import cards from payload.kdnab: ${e.message}`);
|
|
949
774
|
}
|
|
950
775
|
|
|
951
776
|
if (importedCards.length === 0) {
|
|
952
|
-
fail(`No cards could be extracted from ${absKdna}
|
|
777
|
+
fail(`No current judgment cards could be extracted from ${absKdna}.`);
|
|
953
778
|
}
|
|
954
779
|
|
|
955
780
|
// Bug #15 / #28 follow-up: surface the source's KDNA_Patterns /
|
|
@@ -958,23 +783,13 @@ function importFromKdna(kdnaPath) {
|
|
|
958
783
|
// compileDomain via exportRuntimeAsset, which preserves
|
|
959
784
|
// changelog / version_notes / reasoning_chains / banned_terms
|
|
960
785
|
// through the round-trip.
|
|
961
|
-
const sourcePatterns = entries.has('KDNA_Patterns.json')
|
|
962
|
-
? JSON.parse(entries.get('KDNA_Patterns.json').toString())
|
|
963
|
-
: null;
|
|
964
|
-
const sourceReasoning = entries.has('KDNA_Reasoning.json')
|
|
965
|
-
? JSON.parse(entries.get('KDNA_Reasoning.json').toString())
|
|
966
|
-
: null;
|
|
967
|
-
const sourceEvolution = entries.has('KDNA_Evolution.json')
|
|
968
|
-
? JSON.parse(entries.get('KDNA_Evolution.json').toString())
|
|
969
|
-
: null;
|
|
970
|
-
|
|
971
786
|
return {
|
|
972
787
|
lineage,
|
|
973
788
|
cards: importedCards,
|
|
974
789
|
source_manifest: manifest,
|
|
975
|
-
source_patterns:
|
|
976
|
-
source_reasoning:
|
|
977
|
-
source_evolution:
|
|
790
|
+
source_patterns: null,
|
|
791
|
+
source_reasoning: null,
|
|
792
|
+
source_evolution: null,
|
|
978
793
|
};
|
|
979
794
|
}
|
|
980
795
|
|
|
@@ -1992,17 +1807,7 @@ function exportProject(project, name, outPath, opts = {}) {
|
|
|
1992
1807
|
);
|
|
1993
1808
|
}
|
|
1994
1809
|
}
|
|
1995
|
-
const
|
|
1996
|
-
if (gate.blocked) {
|
|
1997
|
-
if (opts.allowIncomplete) {
|
|
1998
|
-
console.warn('Human Lock Gate bypassed (--allow-incomplete):');
|
|
1999
|
-
for (const issue of gate.issues) console.warn(` - ${issue.cardId}: ${issue.reason}`);
|
|
2000
|
-
} else {
|
|
2001
|
-
const reasons = gate.issues.map((i) => `${i.cardId}: ${i.reason}`).join('\n - ');
|
|
2002
|
-
fail(`Human Lock Gate blocked export:\n - ${reasons}\nUse --allow-incomplete to bypass.`, EXIT.HUMAN_LOCK_REQUIRED);
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
const lockedCards = (project.cards || []).filter(c => c.locked);
|
|
1810
|
+
const exportedCards = (project.cards || []).filter(c => c.status !== 'deprecated');
|
|
2006
1811
|
const runtimeDir = trackTempDir(fs.mkdtempSync(path.join(os.tmpdir(), 'kdna-runtime-')));
|
|
2007
1812
|
try {
|
|
2008
1813
|
const manifestDefaults = buildManifest(project, name);
|
|
@@ -2021,7 +1826,7 @@ function exportProject(project, name, outPath, opts = {}) {
|
|
|
2021
1826
|
const vr = core.validate(outPath);
|
|
2022
1827
|
if (!vr.overall_valid) fail('runtime export validation failed: ' + (vr.problems || []).join('; '));
|
|
2023
1828
|
console.log('Exported: ' + outPath);
|
|
2024
|
-
console.log(' Name: ' + name + ' Cards: ' +
|
|
1829
|
+
console.log(' Name: ' + name + ' Cards: ' + exportedCards.length + ' Validated: runtime contract passed');
|
|
2025
1830
|
} finally {
|
|
2026
1831
|
try { fs.rmSync(runtimeDir, { recursive: true }); } catch { /* cleanup */ }
|
|
2027
1832
|
}
|
|
@@ -2029,11 +1834,6 @@ function exportProject(project, name, outPath, opts = {}) {
|
|
|
2029
1834
|
|
|
2030
1835
|
function compileProject(projectInput) {
|
|
2031
1836
|
const { project } = readProject(projectInput);
|
|
2032
|
-
const gate = projectApi.checkHumanLockGate(project);
|
|
2033
|
-
if (gate.blocked) {
|
|
2034
|
-
const reasons = gate.issues.map((i) => `${i.cardId}: ${i.reason}`).join('\n - ');
|
|
2035
|
-
fail(`Human Lock Gate blocked compile:\n - ${reasons}`, EXIT.HUMAN_LOCK_REQUIRED);
|
|
2036
|
-
}
|
|
2037
1837
|
return { project, result: compileApi.compileDomain(project) };
|
|
2038
1838
|
}
|
|
2039
1839
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikdna/kdna-studio-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Official KDNA Studio command-line authoring entry for creating, reviewing, compiling, and exporting .kdna judgment assets through the KDNA toolchain.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@aikdna/kdna-core": "0.
|
|
45
|
-
"@aikdna/kdna-studio-core": "1.
|
|
44
|
+
"@aikdna/kdna-core": "0.16.0",
|
|
45
|
+
"@aikdna/kdna-studio-core": "1.8.0",
|
|
46
46
|
"ajv": "^8.20.0",
|
|
47
47
|
"ajv-formats": "^3.0.1",
|
|
48
48
|
"cbor-x": "^1.6.4"
|