@compforge/harness-common 0.4.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -10
- package/dist/file.d.ts +30 -0
- package/dist/file.js +9 -0
- package/dist/identity.d.ts +7 -0
- package/dist/identity.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/knowledge.d.ts +24 -17
- package/dist/knowledge.js +22 -27
- package/dist/repository.d.ts +17 -2
- package/dist/repository.js +7 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,12 @@ view during initialize, so concurrent consumers share them and dispose before th
|
|
|
27
27
|
Dependency graphs must be acyclic. A failed initialization permits retry only after successful cleanup;
|
|
28
28
|
failed cleanup poisons that key and is reported again when the root manager is disposed.
|
|
29
29
|
|
|
30
|
+
`FileDataSource` is an abstract, runtime-recognizable DataSource for one file path. Its `FileClient.read`
|
|
31
|
+
returns fresh `Uint8Array` bytes with explicit `maxBytes`, `timeoutMs` and optional cancellation.
|
|
32
|
+
An empty file succeeds; an oversized or incomplete read rejects. The source's `path` and concrete
|
|
33
|
+
location metadata let consumers attach provenance. Parsing, configuration precedence and persistence
|
|
34
|
+
belong to consumers. Platform implementations live in `@compforge/harness-toolbox/file`.
|
|
35
|
+
|
|
30
36
|
Service identifies a Component's runtime presence in an Environment. A Component belongs to a Repository
|
|
31
37
|
on a Forge. Product is a separate business identity; consumers own its many-to-many associations
|
|
32
38
|
with Components. Repository discovery and directory ownership remain consumer responsibilities.
|
|
@@ -34,20 +40,26 @@ A Service explicitly declares zero or more Workloads. Consumers extend Service w
|
|
|
34
40
|
capabilities, without duplicating these identities. For example:
|
|
35
41
|
|
|
36
42
|
```typescript
|
|
37
|
-
import
|
|
43
|
+
import {
|
|
44
|
+
repositoryId, conceptToMarkdown, knowledgeToMarkdown, stepToMarkdown, workflowToMarkdown,
|
|
45
|
+
type Service,
|
|
46
|
+
} from "@compforge/harness-common";
|
|
38
47
|
|
|
39
48
|
const service: Service = {
|
|
40
49
|
name: "chat",
|
|
41
50
|
knowledge: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{
|
|
51
|
+
markdown() { return knowledgeToMarkdown(this); },
|
|
52
|
+
concepts: [{ id: "conversation", name: "Conversation", description: "Contains Messages; each Message may have multiple execution Attempts.",
|
|
53
|
+
markdown() { return conceptToMarkdown(this); } }],
|
|
54
|
+
workflows: [{ markdown() { return workflowToMarkdown(this); }, id: "reply", title: "Reply", summary: "Accept and answer a message.", steps: [
|
|
55
|
+
{ id: "execute", title: "Execute", description: "Execute an attempt and persist its response.",
|
|
56
|
+
markdown() { return stepToMarkdown(this); } },
|
|
45
57
|
] }],
|
|
46
58
|
},
|
|
47
59
|
upstream: ["gateway"],
|
|
48
60
|
component: {
|
|
49
61
|
name: "api",
|
|
50
|
-
repository: { forge: { name: "github" }, path: "example/app" },
|
|
62
|
+
repository: { forge: { name: "github" }, path: "example/app", id() { return repositoryId(this); } },
|
|
51
63
|
},
|
|
52
64
|
environment: { name: "test" },
|
|
53
65
|
workloads: [{
|
|
@@ -57,6 +69,10 @@ const service: Service = {
|
|
|
57
69
|
};
|
|
58
70
|
```
|
|
59
71
|
|
|
72
|
+
Repository extends Identity: `id()` returns `forge.name/path`, excluding `forkedFrom`.
|
|
73
|
+
Use `repositoryId(this)` when implementing the method, including when restoring a Repository
|
|
74
|
+
from JSON; methods are not serialized.
|
|
75
|
+
|
|
60
76
|
Service and Product accept an optional description for a short introduction, and structured
|
|
61
77
|
`knowledge` for concepts, workflows, articles and dictionaries. Service knowledge covers its own
|
|
62
78
|
responsibilities, while Product knowledge covers end-to-end flows. Consumers maintain this offline
|
|
@@ -85,8 +101,15 @@ Development: bun install, make lint, make test. Published artifacts are Node-com
|
|
|
85
101
|
|
|
86
102
|
Product and Service accept an optional `knowledge` declaration. `Knowledge` groups
|
|
87
103
|
`Concept`, `Workflow` (with parent-scoped `Step` records), `Article` (with `Section`
|
|
88
|
-
records), and typed `Dictionary<Entry>` collections.
|
|
89
|
-
|
|
104
|
+
records), and typed `Dictionary<Entry>` collections. All eight content interfaces extend
|
|
105
|
+
`Markdown`, whose `markdown(): string` method returns an I/O-free representation.
|
|
106
|
+
Declarations remain ordinary objects; methods can delegate to the shared converters below.
|
|
107
|
+
`KnowledgeSource` describes provenance and does not carry this rendering contract.
|
|
108
|
+
|
|
109
|
+
JSON preserves the content fields, but not methods. Consumers own source validation,
|
|
110
|
+
method restoration, distribution and version selection. Parsing JSON or asserting a type
|
|
111
|
+
does not create a callable Knowledge object; restore methods on each content object before
|
|
112
|
+
exposing it through these interfaces.
|
|
90
113
|
|
|
91
114
|
IDs are unique per kind within the owner, and per child collection within its parent.
|
|
92
115
|
Step `parentId` expresses inclusion; sibling order follows the array even when a parent
|
|
@@ -98,12 +121,49 @@ published definitions independently of a containing distribution's version.
|
|
|
98
121
|
`knowledge.ts` also provides deterministic, I/O-free Markdown projections:
|
|
99
122
|
`knowledgeToMarkdown`, `conceptToMarkdown`, `workflowToMarkdown`, `stepToMarkdown`, `articleToMarkdown`,
|
|
100
123
|
`sectionToMarkdown`, `dictionaryToMarkdown` and `entryToMarkdown`.
|
|
101
|
-
Dictionary entries retain their typed domain fields;
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
Dictionary entries retain their typed domain fields; implement `Entry.markdown()` to
|
|
125
|
+
include these fields. The shared `entryToMarkdown` uses name, description and aliases.
|
|
126
|
+
Generated headings and ordered steps use compact spacing; authored paragraphs and code
|
|
127
|
+
blocks retain their content. Terminal presentation, exact lookup, search, source loading
|
|
128
|
+
and vector indexes belong to consumers.
|
|
104
129
|
|
|
105
130
|
## Upgrade to 0.4
|
|
106
131
|
|
|
107
132
|
Move the removed Product/Service `concepts` and `workflows` string fields into
|
|
108
133
|
`knowledge.concepts` and `knowledge.workflows`. Use Concept records for domain objects
|
|
109
134
|
and Workflow/Step records for business processes. Knowledge remains optional.
|
|
135
|
+
|
|
136
|
+
## Upgrade to 0.5
|
|
137
|
+
|
|
138
|
+
Implement `markdown()` on Knowledge and each contained Concept, Workflow, Step, Article,
|
|
139
|
+
Section, Dictionary and Entry. For example:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { conceptToMarkdown, type Concept } from "@compforge/harness-common";
|
|
143
|
+
|
|
144
|
+
const concept: Concept = {
|
|
145
|
+
id: "carrier",
|
|
146
|
+
name: "Carrier",
|
|
147
|
+
description: "Infrastructure capacity.",
|
|
148
|
+
markdown() { return conceptToMarkdown(this); },
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
console.log(concept.markdown());
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Existing `...ToMarkdown` functions remain available as shared implementations. Each
|
|
155
|
+
parent calls its children's `markdown()` methods: Knowledge groups concepts, workflows,
|
|
156
|
+
articles and dictionaries; Article renders Sections; Dictionary renders Entries; Workflow
|
|
157
|
+
numbers and indents Steps according to `parentId`. Parents preserve child output instead
|
|
158
|
+
of rebuilding it from the child's fields. Helpers never call the receiver's own method,
|
|
159
|
+
so `markdown() { return knowledgeToMarkdown(this); }` does not recurse.
|
|
160
|
+
|
|
161
|
+
Default headings follow the composition tree: Knowledge categories use level 1; Concepts,
|
|
162
|
+
Workflows, Articles and Dictionaries use level 2; Sections and Entries use level 3.
|
|
163
|
+
Steps return a bold title and body, with numbering supplied by Workflow. Standalone output
|
|
164
|
+
uses the same format. Custom methods own their heading choices; parents do not rewrite
|
|
165
|
+
headings or code blocks in child output.
|
|
166
|
+
|
|
167
|
+
Move `KnowledgeMarkdownOptions.renderEntry` or `dictionaryToMarkdown` renderer callbacks
|
|
168
|
+
into each Entry's `markdown()` method. These callback arguments are removed in 0.5; a
|
|
169
|
+
custom Entry now renders consistently when shown alone or through its Dictionary and Knowledge.
|
package/dist/file.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Client } from "./client.js";
|
|
2
|
+
import type { ClientManager } from "./client-manager.js";
|
|
3
|
+
import type { DataSource } from "./datasource.js";
|
|
4
|
+
export interface FileReadOptions {
|
|
5
|
+
/** Maximum complete file size; exceeding it rejects instead of returning a prefix. */
|
|
6
|
+
maxBytes: number;
|
|
7
|
+
/** Includes time waiting for a concurrency slot. */
|
|
8
|
+
timeoutMs: number;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @spec Each read obtains fresh bytes from the source's bound path. Empty files succeed;
|
|
13
|
+
* missing files, incomplete reads and exceeded limits reject.
|
|
14
|
+
* @rule Parsing, configuration precedence and evidence persistence belong to consumers.
|
|
15
|
+
*/
|
|
16
|
+
export interface FileClient extends Client {
|
|
17
|
+
read(options: FileReadOptions): Promise<Uint8Array>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A single file location, discoverable without creating a client or performing I/O.
|
|
21
|
+
* @why A shared runtime type lets consumers recognize file sources without a second kind registry.
|
|
22
|
+
* @rule clientKey identifies access, not cached file contents or a Service-owned alias.
|
|
23
|
+
* @see {@link component://../../../docs/toolbox.md}
|
|
24
|
+
*/
|
|
25
|
+
export declare abstract class FileDataSource<C extends FileClient = FileClient> implements DataSource<C> {
|
|
26
|
+
abstract readonly path: string;
|
|
27
|
+
readonly description?: string;
|
|
28
|
+
abstract readonly clientKey: string;
|
|
29
|
+
abstract createClient(clients: Pick<ClientManager, "get">, signal: AbortSignal): C;
|
|
30
|
+
}
|
package/dist/file.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single file location, discoverable without creating a client or performing I/O.
|
|
3
|
+
* @why A shared runtime type lets consumers recognize file sources without a second kind registry.
|
|
4
|
+
* @rule clientKey identifies access, not cached file contents or a Service-owned alias.
|
|
5
|
+
* @see {@link component://../../../docs/toolbox.md}
|
|
6
|
+
*/
|
|
7
|
+
export class FileDataSource {
|
|
8
|
+
description;
|
|
9
|
+
}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/knowledge.d.ts
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @spec Knowledge objects provide an I/O-free Markdown representation of their content.
|
|
3
|
+
* @rule JSON preserves content only; consumers restore methods when loading declarations.
|
|
4
|
+
*/
|
|
5
|
+
export interface Markdown {
|
|
6
|
+
markdown(): string;
|
|
7
|
+
}
|
|
1
8
|
/** A named domain object and its relationships or constraints. */
|
|
2
|
-
export interface Concept {
|
|
9
|
+
export interface Concept extends Markdown {
|
|
3
10
|
readonly id: string;
|
|
4
11
|
readonly name: string;
|
|
5
12
|
readonly description: string;
|
|
6
13
|
}
|
|
7
14
|
/** A documented business process; steps are descriptions, not executable actions. */
|
|
8
|
-
export interface Workflow {
|
|
15
|
+
export interface Workflow extends Markdown {
|
|
9
16
|
readonly id: string;
|
|
10
17
|
readonly title: string;
|
|
11
18
|
readonly summary: string;
|
|
12
19
|
readonly steps: readonly Step[];
|
|
13
20
|
}
|
|
14
|
-
export interface Step {
|
|
21
|
+
export interface Step extends Markdown {
|
|
15
22
|
readonly id: string;
|
|
16
23
|
/** Inclusion within this Workflow. Array order determines sibling order. */
|
|
17
24
|
readonly parentId?: string;
|
|
@@ -19,20 +26,20 @@ export interface Step {
|
|
|
19
26
|
readonly description: string;
|
|
20
27
|
}
|
|
21
28
|
/** A self-contained explanation of a topic. */
|
|
22
|
-
export interface Article {
|
|
29
|
+
export interface Article extends Markdown {
|
|
23
30
|
readonly id: string;
|
|
24
31
|
readonly title: string;
|
|
25
32
|
readonly summary: string;
|
|
26
33
|
readonly sections: readonly Section[];
|
|
27
34
|
}
|
|
28
|
-
export interface Section {
|
|
35
|
+
export interface Section extends Markdown {
|
|
29
36
|
readonly id: string;
|
|
30
37
|
readonly title: string;
|
|
31
38
|
/** Markdown authored by the knowledge owner. */
|
|
32
39
|
readonly body: string;
|
|
33
40
|
}
|
|
34
41
|
/** Common reading identity; consumers extend entries with their typed domain fields. */
|
|
35
|
-
export interface Entry {
|
|
42
|
+
export interface Entry extends Markdown {
|
|
36
43
|
readonly id: string;
|
|
37
44
|
readonly name: string;
|
|
38
45
|
readonly description: string;
|
|
@@ -45,7 +52,7 @@ export interface KnowledgeSource {
|
|
|
45
52
|
readonly reference?: string;
|
|
46
53
|
}
|
|
47
54
|
/** Entries retain domain fields. Names and codes need not be unique; IDs must be. */
|
|
48
|
-
export interface Dictionary<T extends Entry = Entry> {
|
|
55
|
+
export interface Dictionary<T extends Entry = Entry> extends Markdown {
|
|
49
56
|
readonly id: string;
|
|
50
57
|
readonly title: string;
|
|
51
58
|
readonly summary: string;
|
|
@@ -57,7 +64,7 @@ export interface Dictionary<T extends Entry = Entry> {
|
|
|
57
64
|
* @rule Top-level IDs are unique per kind; child IDs are unique within their containing object.
|
|
58
65
|
* @see {@link component://docs/kernel.md}
|
|
59
66
|
*/
|
|
60
|
-
export interface Knowledge {
|
|
67
|
+
export interface Knowledge extends Markdown {
|
|
61
68
|
readonly concepts?: readonly Concept[];
|
|
62
69
|
readonly workflows?: readonly Workflow[];
|
|
63
70
|
readonly articles?: readonly Article[];
|
|
@@ -73,14 +80,14 @@ export declare function validateKnowledge(knowledge: Knowledge): void;
|
|
|
73
80
|
export declare function conceptToMarkdown(concept: Concept): string;
|
|
74
81
|
export declare function sectionToMarkdown(section: Section): string;
|
|
75
82
|
export declare function articleToMarkdown(article: Article): string;
|
|
76
|
-
export declare function stepToMarkdown(step: Step): string;
|
|
77
83
|
export declare function workflowToMarkdown(workflow: Workflow): string;
|
|
84
|
+
export declare function stepToMarkdown(step: Step): string;
|
|
78
85
|
export declare function entryToMarkdown(entry: Entry): string;
|
|
79
|
-
/**
|
|
80
|
-
export declare function dictionaryToMarkdown<T extends Entry>(dictionary: Dictionary<T
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
export declare function knowledgeToMarkdown(knowledge: Knowledge
|
|
86
|
+
/** Entries own their domain-specific output; the dictionary owns its title, source and order. */
|
|
87
|
+
export declare function dictionaryToMarkdown<T extends Entry>(dictionary: Dictionary<T>): string;
|
|
88
|
+
/**
|
|
89
|
+
* @spec Parents compose child markdown() output; only the child owns its content rendering.
|
|
90
|
+
* @rule Helpers never invoke the receiver's own markdown(), so declarations can safely delegate to them.
|
|
91
|
+
* @case id=knowledge_composition,desc=`Nested objects customize Markdown`,expect=`Root output preserves each child result`
|
|
92
|
+
*/
|
|
93
|
+
export declare function knowledgeToMarkdown(knowledge: Knowledge): string;
|
package/dist/knowledge.js
CHANGED
|
@@ -55,16 +55,16 @@ function paragraphs(...parts) {
|
|
|
55
55
|
return parts.filter(part => part !== undefined && part.length > 0).join("\n\n");
|
|
56
56
|
}
|
|
57
57
|
export function conceptToMarkdown(concept) {
|
|
58
|
-
return
|
|
58
|
+
return `${heading(concept.name, 2)}\n${concept.description}`;
|
|
59
59
|
}
|
|
60
60
|
export function sectionToMarkdown(section) {
|
|
61
|
-
return
|
|
61
|
+
return `${heading(section.title, 3)}\n${section.body}`;
|
|
62
62
|
}
|
|
63
63
|
export function articleToMarkdown(article) {
|
|
64
64
|
requireIds(`article '${article.id}'`, article.sections);
|
|
65
|
-
return paragraphs(heading(article.title,
|
|
65
|
+
return paragraphs(`${heading(article.title, 2)}\n${article.summary}`, ...article.sections.map(section => section.markdown()));
|
|
66
66
|
}
|
|
67
|
-
function
|
|
67
|
+
export function workflowToMarkdown(workflow) {
|
|
68
68
|
validateWorkflow(workflow);
|
|
69
69
|
const children = new Map();
|
|
70
70
|
for (const step of workflow.steps) {
|
|
@@ -76,41 +76,36 @@ function workflowMarkdown(workflow, level) {
|
|
|
76
76
|
return (children.get(parentId) ?? []).map((step, index) => {
|
|
77
77
|
const marker = `${index + 1}. `;
|
|
78
78
|
const childIndent = indent + " ".repeat(marker.length);
|
|
79
|
-
const body = step.
|
|
80
|
-
return
|
|
81
|
-
|
|
79
|
+
const body = step.markdown().split("\n").map((line, lineIndex) => lineIndex === 0 ? `${indent}${marker}${line}` : `${childIndent}${line}`).join("\n");
|
|
80
|
+
return [body, render(step.id, childIndent)]
|
|
81
|
+
.filter(part => part.length > 0).join("\n");
|
|
82
|
+
}).join("\n");
|
|
82
83
|
};
|
|
83
|
-
return paragraphs(heading(workflow.title,
|
|
84
|
+
return paragraphs(`${heading(workflow.title, 2)}\n${workflow.summary}`, render(undefined, ""));
|
|
84
85
|
}
|
|
85
86
|
export function stepToMarkdown(step) {
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
export function workflowToMarkdown(workflow) {
|
|
89
|
-
return workflowMarkdown(workflow, 1);
|
|
87
|
+
// Preserve a block boundary before authored descriptions such as indented code and thematic breaks.
|
|
88
|
+
return paragraphs(`**${step.title}**`, step.description);
|
|
90
89
|
}
|
|
91
90
|
export function entryToMarkdown(entry) {
|
|
92
|
-
return paragraphs(heading(entry.name,
|
|
91
|
+
return paragraphs(`${heading(entry.name, 3)}\n${entry.description}`, entry.aliases?.length ? `Aliases: ${entry.aliases.join(", ")}` : undefined);
|
|
93
92
|
}
|
|
94
|
-
/**
|
|
95
|
-
export function dictionaryToMarkdown(dictionary
|
|
93
|
+
/** Entries own their domain-specific output; the dictionary owns its title, source and order. */
|
|
94
|
+
export function dictionaryToMarkdown(dictionary) {
|
|
96
95
|
requireIds(`dictionary '${dictionary.id}'`, dictionary.entries);
|
|
97
96
|
const source = dictionary.source;
|
|
98
|
-
return paragraphs(heading(dictionary.title,
|
|
97
|
+
return paragraphs(`${heading(dictionary.title, 2)}\n${dictionary.summary}`, source ? `Source: ${source.name}@${source.version}${source.reference ? `\n\n${source.reference}` : ""}` : undefined, ...dictionary.entries.map(entry => entry.markdown()));
|
|
99
98
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
/**
|
|
100
|
+
* @spec Parents compose child markdown() output; only the child owns its content rendering.
|
|
101
|
+
* @rule Helpers never invoke the receiver's own markdown(), so declarations can safely delegate to them.
|
|
102
|
+
* @case id=knowledge_composition,desc=`Nested objects customize Markdown`,expect=`Root output preserves each child result`
|
|
103
|
+
*/
|
|
104
|
+
export function knowledgeToMarkdown(knowledge) {
|
|
105
105
|
validateKnowledge(knowledge);
|
|
106
106
|
const concepts = knowledge.concepts ?? [];
|
|
107
107
|
const workflows = knowledge.workflows ?? [];
|
|
108
108
|
const articles = knowledge.articles ?? [];
|
|
109
109
|
const dictionaries = knowledge.dictionaries ?? [];
|
|
110
|
-
return paragraphs(concepts.length ? paragraphs("
|
|
111
|
-
const source = dictionary.source;
|
|
112
|
-
return paragraphs(heading(dictionary.title, 3), dictionary.summary, source ? `Source: ${source.name}@${source.version}${source.reference ? `\n\n${source.reference}` : ""}` : undefined, ...dictionary.entries.map(entry => options.renderEntry
|
|
113
|
-
? options.renderEntry(dictionary, entry)
|
|
114
|
-
: paragraphs(heading(entry.name, 4), entry.description, entry.aliases?.length ? `Aliases: ${entry.aliases.join(", ")}` : undefined)));
|
|
115
|
-
})) : undefined);
|
|
110
|
+
return paragraphs(concepts.length ? paragraphs("# Concepts", ...concepts.map(concept => concept.markdown())) : undefined, workflows.length ? paragraphs("# Workflows", ...workflows.map(workflow => workflow.markdown())) : undefined, articles.length ? paragraphs("# Articles", ...articles.map(article => article.markdown())) : undefined, dictionaries.length ? paragraphs("# Dictionaries", ...dictionaries.map(dictionary => dictionary.markdown())) : undefined);
|
|
116
111
|
}
|
package/dist/repository.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import type { Forge } from "./forge.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { Identity } from "./identity.js";
|
|
3
|
+
/**
|
|
4
|
+
* A repository identified by its Forge and path within that Forge.
|
|
5
|
+
* @spec forkedFrom is the direct parent path within the same Forge instance, not repository identity.
|
|
6
|
+
* @see {@link component://docs/kernel.md}
|
|
7
|
+
*/
|
|
8
|
+
export interface Repository extends Identity {
|
|
4
9
|
readonly forge: Forge;
|
|
5
10
|
readonly path: string;
|
|
11
|
+
/**
|
|
12
|
+
* Direct parent repository path within this same Forge instance; omission/null is unspecified.
|
|
13
|
+
* Cross-Forge import/mirror provenance belongs in separate metadata.
|
|
14
|
+
*/
|
|
15
|
+
readonly forkedFrom?: string | null;
|
|
6
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Derive the Repository.id() value from identity fields.
|
|
19
|
+
* @spec Repository identity is forge.name/path; fork provenance is excluded.
|
|
20
|
+
*/
|
|
21
|
+
export declare function repositoryId(repository: Pick<Repository, "forge" | "path">): string;
|
package/dist/repository.js
CHANGED