open-wiki-spec 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +14 -12
- package/bin/open-wiki-spec.js +0 -0
- package/dist/cli/commands/apply.d.ts.map +1 -1
- package/dist/cli/commands/apply.js +26 -5
- package/dist/cli/commands/apply.js.map +1 -1
- package/dist/cli/commands/archive.d.ts +1 -0
- package/dist/cli/commands/archive.d.ts.map +1 -1
- package/dist/cli/commands/archive.js +12 -4
- package/dist/cli/commands/archive.js.map +1 -1
- package/dist/cli/commands/continue.d.ts.map +1 -1
- package/dist/cli/commands/continue.js +8 -4
- package/dist/cli/commands/continue.js.map +1 -1
- package/dist/cli/commands/error-handler.d.ts +6 -0
- package/dist/cli/commands/error-handler.d.ts.map +1 -0
- package/dist/cli/commands/error-handler.js +15 -0
- package/dist/cli/commands/error-handler.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/list.js +3 -3
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +5 -1
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/commands/propose.d.ts.map +1 -1
- package/dist/cli/commands/propose.js +20 -3
- package/dist/cli/commands/propose.js.map +1 -1
- package/dist/cli/commands/query.d.ts.map +1 -1
- package/dist/cli/commands/query.js +25 -20
- package/dist/cli/commands/query.js.map +1 -1
- package/dist/cli/commands/status.d.ts +7 -2
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +123 -53
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/verify.d.ts +3 -0
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +6 -8
- package/dist/cli/commands/verify.js.map +1 -1
- package/dist/cli/index.js +3 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/init-engine.d.ts.map +1 -1
- package/dist/cli/init/init-engine.js +65 -0
- package/dist/cli/init/init-engine.js.map +1 -1
- package/dist/cli/init/meta-files.d.ts.map +1 -1
- package/dist/cli/init/meta-files.js +8 -12
- package/dist/cli/init/meta-files.js.map +1 -1
- package/dist/cli/init/skill-generator.d.ts.map +1 -1
- package/dist/cli/init/skill-generator.js +78 -19
- package/dist/cli/init/skill-generator.js.map +1 -1
- package/dist/cli/init/types.d.ts +3 -0
- package/dist/cli/init/types.d.ts.map +1 -1
- package/dist/core/embedding/cache.d.ts +28 -0
- package/dist/core/embedding/cache.d.ts.map +1 -0
- package/dist/core/embedding/cache.js +53 -0
- package/dist/core/embedding/cache.js.map +1 -0
- package/dist/core/embedding/embedder.d.ts +26 -0
- package/dist/core/embedding/embedder.d.ts.map +1 -0
- package/dist/core/embedding/embedder.js +51 -0
- package/dist/core/embedding/embedder.js.map +1 -0
- package/dist/core/embedding/index.d.ts +5 -0
- package/dist/core/embedding/index.d.ts.map +1 -0
- package/dist/core/embedding/index.js +5 -0
- package/dist/core/embedding/index.js.map +1 -0
- package/dist/core/embedding/semantic-recall.d.ts +18 -0
- package/dist/core/embedding/semantic-recall.d.ts.map +1 -0
- package/dist/core/embedding/semantic-recall.js +37 -0
- package/dist/core/embedding/semantic-recall.js.map +1 -0
- package/dist/core/embedding/similarity.d.ts +5 -0
- package/dist/core/embedding/similarity.d.ts.map +1 -0
- package/dist/core/embedding/similarity.js +21 -0
- package/dist/core/embedding/similarity.js.map +1 -0
- package/dist/core/index/build.d.ts.map +1 -1
- package/dist/core/index/build.js +38 -3
- package/dist/core/index/build.js.map +1 -1
- package/dist/core/index/resolve.d.ts +2 -1
- package/dist/core/index/resolve.d.ts.map +1 -1
- package/dist/core/index/resolve.js +17 -4
- package/dist/core/index/resolve.js.map +1 -1
- package/dist/core/index/scan.js +1 -1
- package/dist/core/index/scan.js.map +1 -1
- package/dist/core/index/validate.d.ts +2 -1
- package/dist/core/index/validate.d.ts.map +1 -1
- package/dist/core/index/validate.js +23 -2
- package/dist/core/index/validate.js.map +1 -1
- package/dist/core/migrate/change-converter.js +5 -5
- package/dist/core/migrate/change-converter.js.map +1 -1
- package/dist/core/migrate/migrate.js +1 -1
- package/dist/core/migrate/migrate.js.map +1 -1
- package/dist/core/migrate/spec-converter.js +1 -2
- package/dist/core/migrate/spec-converter.js.map +1 -1
- package/dist/core/parser/wikilink-parser.d.ts.map +1 -1
- package/dist/core/parser/wikilink-parser.js +13 -1
- package/dist/core/parser/wikilink-parser.js.map +1 -1
- package/dist/core/retrieval/constants.d.ts +4 -1
- package/dist/core/retrieval/constants.d.ts.map +1 -1
- package/dist/core/retrieval/constants.js +3 -0
- package/dist/core/retrieval/constants.js.map +1 -1
- package/dist/core/retrieval/retrieve.d.ts +6 -0
- package/dist/core/retrieval/retrieve.d.ts.map +1 -1
- package/dist/core/retrieval/retrieve.js +17 -4
- package/dist/core/retrieval/retrieve.js.map +1 -1
- package/dist/core/retrieval/scoring.d.ts +3 -2
- package/dist/core/retrieval/scoring.d.ts.map +1 -1
- package/dist/core/retrieval/scoring.js +42 -3
- package/dist/core/retrieval/scoring.js.map +1 -1
- package/dist/core/schema/base.schema.js +1 -1
- package/dist/core/schema/base.schema.js.map +1 -1
- package/dist/core/schema/requirement.d.ts +2 -2
- package/dist/core/workflow/apply/apply.d.ts.map +1 -1
- package/dist/core/workflow/apply/apply.js +265 -15
- package/dist/core/workflow/apply/apply.js.map +1 -1
- package/dist/core/workflow/apply/feature-updater.d.ts +9 -5
- package/dist/core/workflow/apply/feature-updater.d.ts.map +1 -1
- package/dist/core/workflow/apply/feature-updater.js +130 -8
- package/dist/core/workflow/apply/feature-updater.js.map +1 -1
- package/dist/core/workflow/apply/types.d.ts +5 -0
- package/dist/core/workflow/apply/types.d.ts.map +1 -1
- package/dist/core/workflow/continue/continue.d.ts +1 -0
- package/dist/core/workflow/continue/continue.d.ts.map +1 -1
- package/dist/core/workflow/continue/continue.js +94 -34
- package/dist/core/workflow/continue/continue.js.map +1 -1
- package/dist/core/workflow/continue/types.d.ts +1 -1
- package/dist/core/workflow/continue/types.d.ts.map +1 -1
- package/dist/core/workflow/propose/note-creator.d.ts +2 -0
- package/dist/core/workflow/propose/note-creator.d.ts.map +1 -1
- package/dist/core/workflow/propose/note-creator.js +33 -10
- package/dist/core/workflow/propose/note-creator.js.map +1 -1
- package/dist/core/workflow/propose/propose.d.ts.map +1 -1
- package/dist/core/workflow/propose/propose.js +131 -14
- package/dist/core/workflow/propose/propose.js.map +1 -1
- package/dist/core/workflow/propose/query-normalizer.d.ts +7 -1
- package/dist/core/workflow/propose/query-normalizer.d.ts.map +1 -1
- package/dist/core/workflow/propose/query-normalizer.js +52 -2
- package/dist/core/workflow/propose/query-normalizer.js.map +1 -1
- package/dist/core/workflow/propose/types.d.ts +7 -3
- package/dist/core/workflow/propose/types.d.ts.map +1 -1
- package/dist/core/workflow/query/query-note-creator.js +1 -1
- package/dist/core/workflow/query/query-note-creator.js.map +1 -1
- package/dist/core/workflow/query/query-search.d.ts +3 -1
- package/dist/core/workflow/query/query-search.d.ts.map +1 -1
- package/dist/core/workflow/query/query-search.js +6 -2
- package/dist/core/workflow/query/query-search.js.map +1 -1
- package/dist/core/workflow/verify/completeness.d.ts +2 -2
- package/dist/core/workflow/verify/completeness.d.ts.map +1 -1
- package/dist/core/workflow/verify/completeness.js +101 -5
- package/dist/core/workflow/verify/completeness.js.map +1 -1
- package/dist/core/workflow/verify/correctness.d.ts +6 -0
- package/dist/core/workflow/verify/correctness.d.ts.map +1 -1
- package/dist/core/workflow/verify/correctness.js +35 -0
- package/dist/core/workflow/verify/correctness.js.map +1 -1
- package/dist/core/workflow/verify/index.d.ts +2 -2
- package/dist/core/workflow/verify/index.d.ts.map +1 -1
- package/dist/core/workflow/verify/index.js +2 -2
- package/dist/core/workflow/verify/index.js.map +1 -1
- package/dist/core/workflow/verify/vault-integrity.d.ts +11 -0
- package/dist/core/workflow/verify/vault-integrity.d.ts.map +1 -1
- package/dist/core/workflow/verify/vault-integrity.js +47 -2
- package/dist/core/workflow/verify/vault-integrity.js.map +1 -1
- package/dist/core/workflow/verify/verify.d.ts.map +1 -1
- package/dist/core/workflow/verify/verify.js +6 -2
- package/dist/core/workflow/verify/verify.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/types/index-record.d.ts +2 -1
- package/dist/types/index-record.d.ts.map +1 -1
- package/dist/types/retrieval.d.ts +2 -0
- package/dist/types/retrieval.d.ts.map +1 -1
- package/dist/utils/path-safety.d.ts +8 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +15 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/package.json +4 -3
|
@@ -55,23 +55,19 @@ This file is the entry point for navigating the vault.
|
|
|
55
55
|
|
|
56
56
|
## Note Types
|
|
57
57
|
|
|
58
|
+
This file is a manual entry point. Use \`ows list\` for the current vault contents.
|
|
59
|
+
|
|
58
60
|
### Features
|
|
59
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
60
61
|
|
|
61
62
|
### Systems
|
|
62
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
63
63
|
|
|
64
64
|
### Active Changes
|
|
65
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
66
65
|
|
|
67
66
|
### Decisions
|
|
68
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
69
67
|
|
|
70
68
|
### Sources
|
|
71
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
72
69
|
|
|
73
70
|
### Queries
|
|
74
|
-
<!-- Auto-populated by ows or manually maintained -->
|
|
75
71
|
`;
|
|
76
72
|
fs.writeFileSync(path.join(wikiPath, '00-meta', 'index.md'), content);
|
|
77
73
|
}
|
|
@@ -107,7 +103,7 @@ type: meta
|
|
|
107
103
|
## Frontmatter Rules
|
|
108
104
|
|
|
109
105
|
- \`id\` is immutable after creation. Never change it.
|
|
110
|
-
- \`status\`
|
|
106
|
+
- \`status\` should follow the allowed lifecycle transitions.
|
|
111
107
|
- Wikilinks in frontmatter use the format: \`"[[Note Title]]"\`.
|
|
112
108
|
|
|
113
109
|
## Wikilink Conventions
|
|
@@ -118,23 +114,23 @@ type: meta
|
|
|
118
114
|
|
|
119
115
|
## Section Conventions
|
|
120
116
|
|
|
121
|
-
- Each note type has
|
|
117
|
+
- Each note type has recommended sections (see [[schema]]).
|
|
122
118
|
- Additional sections can be added freely.
|
|
123
|
-
- Section names
|
|
119
|
+
- Section names should match the expected names exactly (case-sensitive).
|
|
124
120
|
|
|
125
121
|
## Requirement Conventions
|
|
126
122
|
|
|
127
123
|
- Requirements live inside Feature notes under \`## Requirements\`.
|
|
128
124
|
- Each requirement: \`### Requirement: <name>\` with \`<name>\` unique within the Feature.
|
|
129
|
-
- Normative statement
|
|
130
|
-
- Each requirement
|
|
125
|
+
- Normative statement should contain \`SHALL\` or \`MUST\`.
|
|
126
|
+
- Each requirement should have at least one \`#### Scenario:\` with \`WHEN\`/\`THEN\` format.
|
|
131
127
|
|
|
132
128
|
## Delta Summary Conventions
|
|
133
129
|
|
|
134
130
|
- Delta Summary lives inside Change notes under \`## Delta Summary\`.
|
|
135
131
|
- Operations: \`ADDED\`, \`MODIFIED\`, \`REMOVED\`, \`RENAMED\`.
|
|
136
132
|
- Apply order: RENAMED -> REMOVED -> MODIFIED -> ADDED.
|
|
137
|
-
- MODIFIED/REMOVED/RENAMED entries include \`[base: <content_hash>]\`.
|
|
133
|
+
- MODIFIED/REMOVED/RENAMED entries should include \`[base: <content_hash>]\`.
|
|
138
134
|
`;
|
|
139
135
|
fs.writeFileSync(path.join(wikiPath, '00-meta', 'conventions.md'), content);
|
|
140
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-files.js","sourceRoot":"","sources":["../../../src/cli/init/meta-files.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,cAAc,GAAG,eAAe,CAAC;AAEvC,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,OAAO,GAAG;;mBAEC,cAAc;mBACd,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;;;;;;;IAOrC,cAAc;;;;;;;;;;;;;;;;;;;;CAoBjB,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"meta-files.js","sourceRoot":"","sources":["../../../src/cli/init/meta-files.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,cAAc,GAAG,eAAe,CAAC;AAEvC,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,OAAO,GAAG;;mBAEC,cAAc;mBACd,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;;;;;;;IAOrC,cAAc;;;;;;;;;;;;;;;;;;;;CAoBjB,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG;;;;;;;;;;IAUd,IAAI;CACP,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CjB,CAAC;IACA,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,SAAiB,EACjB,MAAc,EACd,QAAgB,KAAK;IAErB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,KAAK,IAAI,MAAM,SAAS,MAAM,MAAM,MAAM,KAAK,IAAI,CAAC;IAClE,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-generator.d.ts","sourceRoot":"","sources":["../../../src/cli/init/skill-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"skill-generator.d.ts","sourceRoot":"","sources":["../../../src/cli/init/skill-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA0wB3D,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAQnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAahE"}
|
|
@@ -19,7 +19,22 @@ export const WORKFLOW_SKILLS = {
|
|
|
19
19
|
|
|
20
20
|
**IMPORTANT**: Do NOT proceed without understanding what the user wants.
|
|
21
21
|
|
|
22
|
-
2. **
|
|
22
|
+
2. **If input is long natural language, refine it first**
|
|
23
|
+
|
|
24
|
+
Extract the core from the user's input:
|
|
25
|
+
- **intent**: add / modify / remove / query
|
|
26
|
+
- **keywords**: 3-5 essential keywords (prioritize technical terms, feature names, system names)
|
|
27
|
+
- **summary**: 1-sentence summary
|
|
28
|
+
|
|
29
|
+
Example: "우리 앱에서 워치랑 연동해서 수영 기록을 자동으로 가져오는데 HealthKit에서 데이터를 못 가져오는 케이스가 있어서 그걸 Sentry로 추적하고 싶거든"
|
|
30
|
+
→ summary: "HealthKit 워치 동기화 실패 Sentry 추적"
|
|
31
|
+
→ keywords: "워치 동기화,HealthKit,Sentry,에러 추적"
|
|
32
|
+
|
|
33
|
+
3. **Run preflight retrieval (dry-run first)**
|
|
34
|
+
\`\`\`bash
|
|
35
|
+
ows propose "<summary>" --keywords "<keyword1>,<keyword2>,..." --dry-run --json
|
|
36
|
+
\`\`\`
|
|
37
|
+
If the user's input is already concise, skip \`--keywords\` and use the input directly:
|
|
23
38
|
\`\`\`bash
|
|
24
39
|
ows propose "<user's description>" --dry-run --json
|
|
25
40
|
\`\`\`
|
|
@@ -30,7 +45,7 @@ export const WORKFLOW_SKILLS = {
|
|
|
30
45
|
- \`classification.primary_candidate\`: the top matching note
|
|
31
46
|
- \`sequencing_warnings\`: any parallel work conflicts
|
|
32
47
|
|
|
33
|
-
|
|
48
|
+
4. **Act based on classification**
|
|
34
49
|
|
|
35
50
|
---
|
|
36
51
|
|
|
@@ -47,24 +62,27 @@ export const WORKFLOW_SKILLS = {
|
|
|
47
62
|
|
|
48
63
|
---
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
5. **Execute the propose (if confirmed)**
|
|
66
|
+
|
|
67
|
+
**IMPORTANT**: Use the same \`--keywords\` from the dry-run step to ensure consistent retrieval results.
|
|
51
68
|
|
|
52
69
|
For \`new_feature\` or \`existing_feature\` classification, run directly:
|
|
53
70
|
\`\`\`bash
|
|
54
|
-
ows propose "<
|
|
71
|
+
ows propose "<summary>" --keywords "<keyword1>,<keyword2>,..." --json
|
|
55
72
|
\`\`\`
|
|
56
73
|
|
|
57
|
-
For \`needs_confirmation\` (after user chooses), use \`--force-classification\`
|
|
74
|
+
For \`needs_confirmation\` (after user chooses), use \`--force-classification\` AND \`--force-target\`:
|
|
58
75
|
\`\`\`bash
|
|
59
76
|
# User chose to create new Feature + Change:
|
|
60
|
-
ows propose "<
|
|
61
|
-
# User chose an existing Feature:
|
|
62
|
-
ows propose "<
|
|
63
|
-
# User chose to continue an existing Change:
|
|
64
|
-
ows
|
|
77
|
+
ows propose "<summary>" --force-classification new_feature --json
|
|
78
|
+
# User chose an existing Feature (use the candidate id from dry-run):
|
|
79
|
+
ows propose "<summary>" --force-classification existing_feature --force-target "<candidate-id>" --json
|
|
80
|
+
# User chose to continue an existing Change (hand off to continue):
|
|
81
|
+
/ows-continue <candidate-change-id>
|
|
65
82
|
\`\`\`
|
|
83
|
+
**IMPORTANT**: When user picks \`existing_feature\` or \`existing_change\`, always include \`--force-target <id>\` with the candidate's actual id from the dry-run results. Without it, the engine uses the top candidate which may not be what the user chose.
|
|
66
84
|
|
|
67
|
-
|
|
85
|
+
6. **Show results**
|
|
68
86
|
|
|
69
87
|
Display:
|
|
70
88
|
- Classification decision and reasoning
|
|
@@ -79,6 +97,14 @@ After completing, summarize:
|
|
|
79
97
|
- Why (classification reasoning from retrieval)
|
|
80
98
|
- What to do next
|
|
81
99
|
|
|
100
|
+
**Retrieval Quality**
|
|
101
|
+
|
|
102
|
+
The propose workflow automatically enriches the query with system_terms by matching feature/entity terms against System note titles and aliases in the vault index. This means:
|
|
103
|
+
- System-related queries like "auth login" will auto-detect System notes titled "Authentication" and use them for scoring
|
|
104
|
+
- Partial title matches are supported: a search for "auth" will match "Feature: Auth Login" (partial match, +20 points)
|
|
105
|
+
- Title prefix stripping: "auth login" matches "Feature: Auth Login" (prefix-stripped match, +30 points)
|
|
106
|
+
- Derived aliases are auto-generated from note titles and IDs, improving alias-based matching even when no explicit aliases are set
|
|
107
|
+
|
|
82
108
|
**Guardrails**
|
|
83
109
|
- Always show dry-run results before creating anything
|
|
84
110
|
- If classification is \`needs_confirmation\`, NEVER auto-decide — always ask the user
|
|
@@ -90,15 +116,18 @@ After completing, summarize:
|
|
|
90
116
|
description: 'Continue work on an existing Change.',
|
|
91
117
|
instructions: `Continue working on an existing Change by filling sections or advancing status.
|
|
92
118
|
|
|
93
|
-
**Input**: Optionally specify a change ID after \`/ows-continue\` (e.g., \`/ows-continue change-add-auth\`). If omitted,
|
|
119
|
+
**Input**: Optionally specify a change ID after \`/ows-continue\` (e.g., \`/ows-continue change-add-auth\`). If omitted and only one active change exists, it is auto-selected. If multiple active changes exist, the CLI returns a list and the agent must ask the user to choose.
|
|
94
120
|
|
|
95
121
|
**Steps**
|
|
96
122
|
|
|
97
|
-
1. **If no change ID provided
|
|
123
|
+
1. **If no change ID provided**
|
|
98
124
|
|
|
99
|
-
Run \`ows
|
|
125
|
+
Run \`ows continue --json\`. The CLI will:
|
|
126
|
+
- **If 1 active change**: auto-select it and proceed.
|
|
127
|
+
- **If 2+ active changes**: return an error with the list of active changes. Show them and let the user pick, then re-run with the chosen ID.
|
|
128
|
+
- **If 0 active changes**: return an error. Suggest \`/ows-propose\` to create one.
|
|
100
129
|
|
|
101
|
-
**IMPORTANT**:
|
|
130
|
+
**IMPORTANT**: When the CLI returns multiple active changes, NEVER auto-select. Always ask the user.
|
|
102
131
|
|
|
103
132
|
2. **Check current status**
|
|
104
133
|
\`\`\`bash
|
|
@@ -144,9 +173,20 @@ After each invocation, show:
|
|
|
144
173
|
- Section/task progress
|
|
145
174
|
- What to do next
|
|
146
175
|
|
|
176
|
+
**Context Enrichment**
|
|
177
|
+
|
|
178
|
+
The continue result includes a \`context\` object with real content from linked notes (truncated at 500 chars per section):
|
|
179
|
+
- \`context.features[]\`: Purpose, Current Behavior, Requirements sections from linked Feature notes
|
|
180
|
+
- \`context.decisions[]\`: Summary, Context, Decision sections from linked Decision notes
|
|
181
|
+
- \`context.systems[]\`: Purpose, Boundaries sections from linked System notes
|
|
182
|
+
- \`context.sources[]\`: Summary, Content sections from linked Source notes
|
|
183
|
+
|
|
184
|
+
Use this context to inform section writing (especially Why and Delta Summary).
|
|
185
|
+
|
|
147
186
|
**Guardrails**
|
|
148
187
|
- Perform ONE section fill or ONE status transition per invocation
|
|
149
188
|
- Always read the Change note before modifying it
|
|
189
|
+
- Use the \`context\` from the continue result to inform your writing — do not ignore linked note content
|
|
150
190
|
- If context is unclear, ask the user before writing
|
|
151
191
|
- Show status after every change
|
|
152
192
|
- The continue workflow owns proposed->planned and planned->in_progress transitions ONLY
|
|
@@ -206,7 +246,11 @@ After each invocation, show:
|
|
|
206
246
|
- **Phase 1** (validate & compute): Parse Delta Summary, stale-check all entries, pre-validate operations. No files written.
|
|
207
247
|
- **Phase 2** (write): Only if Phase 1 passes. Apply operations in **atomic order**: RENAMED -> REMOVED -> MODIFIED -> ADDED.
|
|
208
248
|
|
|
209
|
-
|
|
249
|
+
The apply engine programmatically modifies Feature notes:
|
|
250
|
+
- **RENAMED**: Automatically renames the requirement in the Feature note. Fully automated.
|
|
251
|
+
- **REMOVED**: Automatically removes the requirement from the Feature note. Fully automated.
|
|
252
|
+
- **MODIFIED**: Inserts a \`<!-- MODIFIED by change: <changeId> -->\` marker after the requirement heading. The agent must then update the requirement text.
|
|
253
|
+
- **ADDED**: Inserts a \`<!-- ADDED by change: <changeId>. Fill in normative statement (SHALL/MUST) and scenarios (WHEN/THEN). -->\` marker in the Requirements section. The agent must then write the new requirement content.
|
|
210
254
|
|
|
211
255
|
5. **Show final state**
|
|
212
256
|
\`\`\`bash
|
|
@@ -591,6 +635,7 @@ The change has been archived. Decision history is preserved.
|
|
|
591
635
|
**Available flags**:
|
|
592
636
|
- \`--json\`: Output structured JSON result
|
|
593
637
|
- \`--force\`: Force re-initialization, recreating meta files even if they exist
|
|
638
|
+
- \`--skip-seed\`: Skip creating seed notes (source and system placeholders)
|
|
594
639
|
|
|
595
640
|
**Steps**
|
|
596
641
|
|
|
@@ -601,6 +646,8 @@ The change has been archived. Decision history is preserved.
|
|
|
601
646
|
ows init <path> --json
|
|
602
647
|
# force re-init:
|
|
603
648
|
ows init --force --json
|
|
649
|
+
# skip seed notes:
|
|
650
|
+
ows init --skip-seed --json
|
|
604
651
|
\`\`\`
|
|
605
652
|
|
|
606
653
|
2. **Parse the result**
|
|
@@ -610,6 +657,7 @@ The change has been archived. Decision history is preserved.
|
|
|
610
657
|
- \`wikiPath\`: path to the created wiki directory
|
|
611
658
|
- \`directoriesCreated\`: list of directories created
|
|
612
659
|
- \`metaFilesCreated\`: list of meta files created (log.md, index, etc.)
|
|
660
|
+
- \`seedFilesCreated\`: list of seed notes created (Source and System placeholders)
|
|
613
661
|
- \`skillFilesGenerated\`: list of Claude Code skill files generated
|
|
614
662
|
- \`warnings\`: any warnings during initialization
|
|
615
663
|
|
|
@@ -622,11 +670,13 @@ The change has been archived. Decision history is preserved.
|
|
|
622
670
|
Created new vault at: <wikiPath>
|
|
623
671
|
- N directories created
|
|
624
672
|
- N meta files created
|
|
673
|
+
- N seed notes created
|
|
625
674
|
- N skill files generated
|
|
626
675
|
|
|
627
676
|
Next steps:
|
|
628
|
-
|
|
629
|
-
|
|
677
|
+
1. Edit \`wiki/01-sources/seed-context.md\` to describe your project (stack, constraints, goals)
|
|
678
|
+
2. Edit \`wiki/02-systems/default-system.md\` to define your primary system boundary
|
|
679
|
+
3. Run \`/ows-propose\` to create your first Change
|
|
630
680
|
\`\`\`
|
|
631
681
|
|
|
632
682
|
**If extend** (existing directory):
|
|
@@ -637,12 +687,21 @@ The change has been archived. Decision history is preserved.
|
|
|
637
687
|
- N new directories added
|
|
638
688
|
- N meta files updated
|
|
639
689
|
|
|
640
|
-
Your existing notes are preserved.
|
|
690
|
+
Your existing notes are preserved. Seed notes are not overwritten.
|
|
641
691
|
\`\`\`
|
|
642
692
|
|
|
693
|
+
**Seed Notes**
|
|
694
|
+
|
|
695
|
+
On fresh init, two seed notes are created:
|
|
696
|
+
- \`wiki/01-sources/seed-context.md\` — A placeholder Source note for the user to fill with project context (tech stack, goals, constraints)
|
|
697
|
+
- \`wiki/02-systems/default-system.md\` — A default System note for the user to define their primary system boundary
|
|
698
|
+
|
|
699
|
+
In extend mode, existing seed notes are never overwritten. Use \`--skip-seed\` to skip seed creation entirely.
|
|
700
|
+
|
|
643
701
|
**Guardrails**
|
|
644
702
|
- If the vault already exists and --force is not used, the init will extend rather than overwrite
|
|
645
703
|
- Never destroy existing vault content
|
|
704
|
+
- Encourage the user to edit seed-context.md after init — it improves retrieval quality
|
|
646
705
|
- Show warnings if any files were skipped`,
|
|
647
706
|
},
|
|
648
707
|
migrate: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-generator.js","sourceRoot":"","sources":["../../../src/cli/init/skill-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,CAAC,MAAM,eAAe,GAAoC;IAC9D,OAAO,EAAE;QACP,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,4CAA4C;QACzD,YAAY,EAAE
|
|
1
|
+
{"version":3,"file":"skill-generator.js","sourceRoot":"","sources":["../../../src/cli/init/skill-generator.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/init/types.d.ts
CHANGED
|
@@ -10,12 +10,15 @@ export interface InitOptions {
|
|
|
10
10
|
nonInteractive?: boolean;
|
|
11
11
|
/** Output as JSON */
|
|
12
12
|
json?: boolean;
|
|
13
|
+
/** Skip seed note generation */
|
|
14
|
+
skipSeed?: boolean;
|
|
13
15
|
}
|
|
14
16
|
export interface InitResult {
|
|
15
17
|
mode: 'fresh' | 'extend';
|
|
16
18
|
wikiPath: string;
|
|
17
19
|
directoriesCreated: string[];
|
|
18
20
|
metaFilesCreated: string[];
|
|
21
|
+
seedFilesCreated: string[];
|
|
19
22
|
skillFilesGenerated: string[];
|
|
20
23
|
warnings: string[];
|
|
21
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/init/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qBAAqB;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/init/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qBAAqB;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface EmbeddingCacheEntry {
|
|
2
|
+
vector: number[];
|
|
3
|
+
content_hash: string;
|
|
4
|
+
}
|
|
5
|
+
export interface EmbeddingCache {
|
|
6
|
+
model: string;
|
|
7
|
+
entries: Record<string, EmbeddingCacheEntry>;
|
|
8
|
+
}
|
|
9
|
+
export declare function createEmptyCache(model: string): EmbeddingCache;
|
|
10
|
+
/**
|
|
11
|
+
* Load embedding cache from disk.
|
|
12
|
+
* Returns null if file doesn't exist, is corrupted, or model mismatches.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadEmbeddingCache(filePath: string, expectedModel?: string): EmbeddingCache | null;
|
|
15
|
+
/**
|
|
16
|
+
* Save embedding cache to disk atomically (write-to-temp-then-rename).
|
|
17
|
+
* Prevents corruption from interrupted or concurrent writes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function saveEmbeddingCache(filePath: string, cache: EmbeddingCache): void;
|
|
20
|
+
/**
|
|
21
|
+
* Get cached vector if content_hash matches.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCachedVector(cache: EmbeddingCache, id: string, currentHash: string): number[] | null;
|
|
24
|
+
/**
|
|
25
|
+
* Store a vector in the cache.
|
|
26
|
+
*/
|
|
27
|
+
export declare function setCachedVector(cache: EmbeddingCache, id: string, vector: number[], contentHash: string): void;
|
|
28
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/core/embedding/cache.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC9C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAE9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,cAAc,GAAG,IAAI,CAWvB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAMhF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,GAAG,IAAI,CAIjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EAAE,EAChB,WAAW,EAAE,MAAM,GAClB,IAAI,CAEN"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as crypto from 'node:crypto';
|
|
4
|
+
export function createEmptyCache(model) {
|
|
5
|
+
return { model, entries: {} };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Load embedding cache from disk.
|
|
9
|
+
* Returns null if file doesn't exist, is corrupted, or model mismatches.
|
|
10
|
+
*/
|
|
11
|
+
export function loadEmbeddingCache(filePath, expectedModel) {
|
|
12
|
+
try {
|
|
13
|
+
if (!fs.existsSync(filePath))
|
|
14
|
+
return null;
|
|
15
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
16
|
+
const data = JSON.parse(raw);
|
|
17
|
+
if (!data.model || !data.entries || typeof data.entries !== 'object')
|
|
18
|
+
return null;
|
|
19
|
+
if (expectedModel && data.model !== expectedModel)
|
|
20
|
+
return null;
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Save embedding cache to disk atomically (write-to-temp-then-rename).
|
|
29
|
+
* Prevents corruption from interrupted or concurrent writes.
|
|
30
|
+
*/
|
|
31
|
+
export function saveEmbeddingCache(filePath, cache) {
|
|
32
|
+
const dir = path.dirname(filePath);
|
|
33
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
34
|
+
const tmpPath = path.join(dir, `.embeddings-${crypto.randomBytes(4).toString('hex')}.tmp`);
|
|
35
|
+
fs.writeFileSync(tmpPath, JSON.stringify(cache), 'utf-8');
|
|
36
|
+
fs.renameSync(tmpPath, filePath);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get cached vector if content_hash matches.
|
|
40
|
+
*/
|
|
41
|
+
export function getCachedVector(cache, id, currentHash) {
|
|
42
|
+
const entry = cache.entries[id];
|
|
43
|
+
if (!entry || entry.content_hash !== currentHash)
|
|
44
|
+
return null;
|
|
45
|
+
return entry.vector;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Store a vector in the cache.
|
|
49
|
+
*/
|
|
50
|
+
export function setCachedVector(cache, id, vector, contentHash) {
|
|
51
|
+
cache.entries[id] = { vector, content_hash: contentHash };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/core/embedding/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAYtC,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,aAAsB;IAEtB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAClF,IAAI,aAAa,IAAI,IAAI,CAAC,KAAK,KAAK,aAAa;YAAE,OAAO,IAAI,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,KAAqB;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3F,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1D,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAqB,EACrB,EAAU,EACV,WAAmB;IAEnB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,YAAY,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9D,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAqB,EACrB,EAAU,EACV,MAAgB,EAChB,WAAmB;IAEnB,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding model wrapper with graceful degradation.
|
|
3
|
+
* Uses @huggingface/transformers when available, otherwise returns null vectors.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_MODEL = "Xenova/multilingual-e5-small";
|
|
6
|
+
export type EmbedPipeline = (text: string) => Promise<number[]>;
|
|
7
|
+
export interface Embedder {
|
|
8
|
+
available: boolean;
|
|
9
|
+
embed: (text: string) => Promise<number[] | null>;
|
|
10
|
+
embedBatch: (texts: string[]) => Promise<(number[] | null)[]>;
|
|
11
|
+
}
|
|
12
|
+
export interface CreateEmbedderOptions {
|
|
13
|
+
/** If false, skip model loading (for testing). */
|
|
14
|
+
loadModel?: boolean;
|
|
15
|
+
/** Inject a mock pipeline (for testing). */
|
|
16
|
+
pipeline?: EmbedPipeline;
|
|
17
|
+
/** Model name override. */
|
|
18
|
+
model?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create an embedder instance.
|
|
22
|
+
* When @huggingface/transformers is not installed or loadModel is false,
|
|
23
|
+
* returns a no-op embedder (available: false).
|
|
24
|
+
*/
|
|
25
|
+
export declare function createEmbedder(options?: CreateEmbedderOptions): Promise<Embedder>;
|
|
26
|
+
//# sourceMappingURL=embedder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../../../src/core/embedding/embedder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,aAAa,iCAAiC,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAEhE,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,qBAAqB;IACpC,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,QAAQ,CAAC,CAsCnB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding model wrapper with graceful degradation.
|
|
3
|
+
* Uses @huggingface/transformers when available, otherwise returns null vectors.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_MODEL = 'Xenova/multilingual-e5-small';
|
|
6
|
+
/**
|
|
7
|
+
* Create an embedder instance.
|
|
8
|
+
* When @huggingface/transformers is not installed or loadModel is false,
|
|
9
|
+
* returns a no-op embedder (available: false).
|
|
10
|
+
*/
|
|
11
|
+
export async function createEmbedder(options = {}) {
|
|
12
|
+
const { loadModel = true, pipeline: injectedPipeline, model = DEFAULT_MODEL } = options;
|
|
13
|
+
// If a mock pipeline is injected, use it directly
|
|
14
|
+
if (injectedPipeline) {
|
|
15
|
+
return {
|
|
16
|
+
available: true,
|
|
17
|
+
embed: async (text) => injectedPipeline(text),
|
|
18
|
+
embedBatch: async (texts) => Promise.all(texts.map((t) => injectedPipeline(t))),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (!loadModel) {
|
|
22
|
+
return createNullEmbedder();
|
|
23
|
+
}
|
|
24
|
+
// Try to load @huggingface/transformers dynamically
|
|
25
|
+
try {
|
|
26
|
+
const { pipeline } = await import('@huggingface/transformers');
|
|
27
|
+
const extractor = await pipeline('feature-extraction', model, {
|
|
28
|
+
dtype: 'q8',
|
|
29
|
+
});
|
|
30
|
+
const embedFn = async (text) => {
|
|
31
|
+
const output = await extractor(text, { pooling: 'mean', normalize: true });
|
|
32
|
+
return Array.from(output.data);
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
available: true,
|
|
36
|
+
embed: async (text) => embedFn(text),
|
|
37
|
+
embedBatch: async (texts) => Promise.all(texts.map((t) => embedFn(t))),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return createNullEmbedder();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function createNullEmbedder() {
|
|
45
|
+
return {
|
|
46
|
+
available: false,
|
|
47
|
+
embed: async () => null,
|
|
48
|
+
embedBatch: async (texts) => texts.map(() => null),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=embedder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.js","sourceRoot":"","sources":["../../../src/core/embedding/embedder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,8BAA8B,CAAC;AAmB5D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAiC,EAAE;IAEnC,MAAM,EAAE,SAAS,GAAG,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IAExF,kDAAkD;IAClD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACrD,UAAU,EAAE,KAAK,EAAE,KAAe,EAAE,EAAE,CACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;SACrD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IAED,oDAAoD;IACpD,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,oBAAoB,EAAE,KAAK,EAAE;YAC5D,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,MAAM,OAAO,GAAkB,KAAK,EAAE,IAAY,EAAE,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3E,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAoB,CAAC,CAAC;QACjD,CAAC,CAAC;QAEF,OAAO;YACL,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;YAC5C,UAAU,EAAE,KAAK,EAAE,KAAe,EAAE,EAAE,CACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;SAC5C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,kBAAkB,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO;QACL,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;QACvB,UAAU,EAAE,KAAK,EAAE,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { cosineSimilarity } from './similarity.js';
|
|
2
|
+
export { loadEmbeddingCache, saveEmbeddingCache, getCachedVector, setCachedVector, createEmptyCache, type EmbeddingCache, type EmbeddingCacheEntry, } from './cache.js';
|
|
3
|
+
export { createEmbedder, DEFAULT_MODEL, type Embedder, type EmbedPipeline, type CreateEmbedderOptions, } from './embedder.js';
|
|
4
|
+
export { computeSemanticRecall, type SemanticRecallResult, type SemanticRecallOptions, } from './semantic-recall.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/embedding/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { cosineSimilarity } from './similarity.js';
|
|
2
|
+
export { loadEmbeddingCache, saveEmbeddingCache, getCachedVector, setCachedVector, createEmptyCache, } from './cache.js';
|
|
3
|
+
export { createEmbedder, DEFAULT_MODEL, } from './embedder.js';
|
|
4
|
+
export { computeSemanticRecall, } from './semantic-recall.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/embedding/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,gBAAgB,GAGjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,aAAa,GAId,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,GAGtB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EmbeddingCache } from './cache.js';
|
|
2
|
+
import type { Embedder } from './embedder.js';
|
|
3
|
+
export interface SemanticRecallOptions {
|
|
4
|
+
/** Max number of candidates to return. Default: 20 */
|
|
5
|
+
topK?: number;
|
|
6
|
+
/** Minimum cosine similarity to include. Default: 0.5 */
|
|
7
|
+
minScore?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface SemanticRecallResult {
|
|
10
|
+
/** Cosine similarities per note ID (keys = candidate IDs). */
|
|
11
|
+
scores: ReadonlyMap<string, number>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Find semantically similar notes by comparing query embedding against cached note embeddings.
|
|
15
|
+
* Returns topK candidates above minScore, sorted by similarity descending.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeSemanticRecall(querySummary: string, cache: EmbeddingCache, embedder: Embedder, options?: SemanticRecallOptions): Promise<SemanticRecallResult>;
|
|
18
|
+
//# sourceMappingURL=semantic-recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-recall.d.ts","sourceRoot":"","sources":["../../../src/core/embedding/semantic-recall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAiC/B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cosineSimilarity } from './similarity.js';
|
|
2
|
+
/**
|
|
3
|
+
* Find semantically similar notes by comparing query embedding against cached note embeddings.
|
|
4
|
+
* Returns topK candidates above minScore, sorted by similarity descending.
|
|
5
|
+
*/
|
|
6
|
+
export async function computeSemanticRecall(querySummary, cache, embedder, options) {
|
|
7
|
+
const topK = options?.topK ?? 20;
|
|
8
|
+
const minScore = options?.minScore ?? 0.5;
|
|
9
|
+
const emptyResult = { scores: new Map() };
|
|
10
|
+
if (!embedder.available)
|
|
11
|
+
return emptyResult;
|
|
12
|
+
const queryVector = await embedder.embed(querySummary);
|
|
13
|
+
if (!queryVector)
|
|
14
|
+
return emptyResult;
|
|
15
|
+
const entries = Object.entries(cache.entries);
|
|
16
|
+
if (entries.length === 0)
|
|
17
|
+
return emptyResult;
|
|
18
|
+
// Compute similarities for all cached entries
|
|
19
|
+
const scored = [];
|
|
20
|
+
for (const [id, entry] of entries) {
|
|
21
|
+
if (!entry.vector || entry.vector.length !== queryVector.length)
|
|
22
|
+
continue;
|
|
23
|
+
const sim = cosineSimilarity(queryVector, entry.vector);
|
|
24
|
+
if (sim >= minScore) {
|
|
25
|
+
scored.push({ id, score: sim });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Sort by score descending, take topK
|
|
29
|
+
scored.sort((a, b) => b.score - a.score);
|
|
30
|
+
const topResults = scored.slice(0, topK);
|
|
31
|
+
const scores = new Map();
|
|
32
|
+
for (const { id, score } of topResults) {
|
|
33
|
+
scores.set(id, score);
|
|
34
|
+
}
|
|
35
|
+
return { scores };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=semantic-recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-recall.js","sourceRoot":"","sources":["../../../src/core/embedding/semantic-recall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAcnD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,YAAoB,EACpB,KAAqB,EACrB,QAAkB,EAClB,OAA+B;IAE/B,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,GAAG,CAAC;IAC1C,MAAM,WAAW,GAAyB,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAEhE,IAAI,CAAC,QAAQ,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IAE5C,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC;IAErC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAE7C,8CAA8C;IAC9C,MAAM,MAAM,GAAyC,EAAE,CAAC;IACxD,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;YAAE,SAAS;QAC1E,MAAM,GAAG,GAAG,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEzC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,UAAU,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../../src/core/embedding/similarity.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAmBjE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute cosine similarity between two vectors.
|
|
3
|
+
*/
|
|
4
|
+
export function cosineSimilarity(a, b) {
|
|
5
|
+
if (a.length !== b.length) {
|
|
6
|
+
throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);
|
|
7
|
+
}
|
|
8
|
+
let dot = 0;
|
|
9
|
+
let normA = 0;
|
|
10
|
+
let normB = 0;
|
|
11
|
+
for (let i = 0; i < a.length; i++) {
|
|
12
|
+
dot += a[i] * b[i];
|
|
13
|
+
normA += a[i] * a[i];
|
|
14
|
+
normB += b[i] * b[i];
|
|
15
|
+
}
|
|
16
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
17
|
+
if (denom === 0)
|
|
18
|
+
return 0;
|
|
19
|
+
return dot / denom;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=similarity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../../src/core/embedding/similarity.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAE1B,OAAO,GAAG,GAAG,KAAK,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/core/index/build.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,UAAU,EAAgB,MAAM,6BAA6B,CAAC;AAczF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/core/index/build.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,UAAU,EAAgB,MAAM,6BAA6B,CAAC;AAczF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CAyEhF"}
|