@aid-framework/generator-sdk 0.1.57 → 0.1.59
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/dist/.tsbuildinfo +1 -1
- package/dist/aid-manifest.d.ts +7 -0
- package/dist/aid-manifest.d.ts.map +1 -1
- package/dist/aid-manifest.js +62 -2
- package/dist/aid-manifest.js.map +1 -1
- package/dist/diagnostics.d.ts +4 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +4 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/drift.d.ts +11 -0
- package/dist/drift.d.ts.map +1 -1
- package/dist/drift.js +46 -1
- package/dist/drift.js.map +1 -1
- package/dist/eject.d.ts +69 -0
- package/dist/eject.d.ts.map +1 -0
- package/dist/eject.js +169 -0
- package/dist/eject.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ownership.d.ts +19 -2
- package/dist/ownership.d.ts.map +1 -1
- package/dist/ownership.js +25 -1
- package/dist/ownership.js.map +1 -1
- package/dist/scaffold.d.ts +104 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +248 -0
- package/dist/scaffold.js.map +1 -0
- package/package.json +3 -3
package/dist/eject.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aid eject` (§10): taking ownership of a generated file.
|
|
3
|
+
*
|
|
4
|
+
* Ejection is the developer's answer to the drift rule. When a generated file needs
|
|
5
|
+
* hand-editing, the choice is to keep discarding the edits with `--force`, or to own the
|
|
6
|
+
* file. Owning it means two things, and both are required:
|
|
7
|
+
*
|
|
8
|
+
* 1. **The bytes move to the business tier.** Ownership is decided by *where a path
|
|
9
|
+
* lives* (`ownership.ts`), not by a flag, so flipping ownership is a move from
|
|
10
|
+
* `<generatedDir>/x` to `<businessDir>/x`. A manifest flag alone would contradict
|
|
11
|
+
* the location rule the planner enforces.
|
|
12
|
+
* 2. **The generated path is excluded forever.** The manifest records it in `ejected`,
|
|
13
|
+
* and `planRegeneration` drops it from every plan. Without this the next `gen` would
|
|
14
|
+
* simply recreate the generated file and the edit would be lost again.
|
|
15
|
+
*
|
|
16
|
+
* The write order is deliberate: destination first, source second. An interrupted eject
|
|
17
|
+
* leaves two copies, never zero.
|
|
18
|
+
*
|
|
19
|
+
* Two refusals are not negotiable. Ejecting onto a business file with different bytes
|
|
20
|
+
* would destroy developer-owned content — the one thing the ownership model protects —
|
|
21
|
+
* so it fails and names the file to move aside. Ejecting a path the manifest never
|
|
22
|
+
* recorded has nothing to transfer and is refused rather than manufacturing a business
|
|
23
|
+
* file from an accident.
|
|
24
|
+
*/
|
|
25
|
+
import { manifestRecordFor } from './aid-manifest.js';
|
|
26
|
+
import { sha256Hex, sortByPath } from './determinism.js';
|
|
27
|
+
import { GENERATOR_DIAGNOSTIC_CODES, generatorError, } from './diagnostics.js';
|
|
28
|
+
import { DEFAULT_BUSINESS_DIR, DEFAULT_GENERATED_DIR, normalizeRelativePath, ownerForPath, } from './ownership.js';
|
|
29
|
+
function stripTrailingSlashes(value) {
|
|
30
|
+
let end = value.length;
|
|
31
|
+
while (end > 0 && value[end - 1] === '/')
|
|
32
|
+
end--;
|
|
33
|
+
return value.slice(0, end);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The business-tier home of a generated path: `<generatedDir>/a/b.py` becomes
|
|
37
|
+
* `<businessDir>/a/b.py`. Returns `undefined` for anything that is not a file directly
|
|
38
|
+
* beneath the generated root, so a caller cannot "eject" a directory or a foreign path.
|
|
39
|
+
*/
|
|
40
|
+
export function businessPathFor(path, options = {}) {
|
|
41
|
+
const normalized = normalizeRelativePath(path);
|
|
42
|
+
if (normalized === undefined)
|
|
43
|
+
return undefined;
|
|
44
|
+
const generatedDir = stripTrailingSlashes(options.generatedDir ?? DEFAULT_GENERATED_DIR);
|
|
45
|
+
const businessDir = stripTrailingSlashes(options.businessDir ?? DEFAULT_BUSINESS_DIR);
|
|
46
|
+
if (!normalized.startsWith(`${generatedDir}/`))
|
|
47
|
+
return undefined;
|
|
48
|
+
const rest = normalized.slice(generatedDir.length + 1);
|
|
49
|
+
if (rest === '')
|
|
50
|
+
return undefined;
|
|
51
|
+
return `${businessDir}/${rest}`;
|
|
52
|
+
}
|
|
53
|
+
function refuse(diagnostic) {
|
|
54
|
+
return { ok: false, diagnostics: [diagnostic] };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Moves one generated file to the business tier and records a permanent exclusion.
|
|
58
|
+
*
|
|
59
|
+
* Idempotent by design: ejecting a path that is already developer-owned succeeds with
|
|
60
|
+
* `status: 'already-owned'`, so a script can call it without first asking whether the
|
|
61
|
+
* file was ejected.
|
|
62
|
+
*/
|
|
63
|
+
export function eject(request) {
|
|
64
|
+
const dryRun = request.dryRun ?? false;
|
|
65
|
+
const path = normalizeRelativePath(request.path);
|
|
66
|
+
if (path === undefined) {
|
|
67
|
+
return refuse(generatorError({
|
|
68
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectInvalidPath,
|
|
69
|
+
message: `"${request.path}" is not a repo-relative path, so it cannot name a generated file.`,
|
|
70
|
+
path: request.path,
|
|
71
|
+
hint: 'Pass the path `aid gen` prints, for example `app/generated/prompts/triage.py`.',
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
// Scaffold content is authored once and owned by the developer from then on, so there
|
|
75
|
+
// is nothing to transfer and nothing to look up. Checked before the manifest guard: the
|
|
76
|
+
// answer does not depend on the tree ever having been generated.
|
|
77
|
+
if (ownerForPath(path, request) === 'scaffold') {
|
|
78
|
+
return { ok: true, status: 'already-owned', from: path, dryRun, diagnostics: [] };
|
|
79
|
+
}
|
|
80
|
+
const manifest = request.manifest;
|
|
81
|
+
if (manifest === undefined) {
|
|
82
|
+
return refuse(generatorError({
|
|
83
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectNotGenerated,
|
|
84
|
+
message: 'There is no manifest, so this tree has never been generated and has nothing to eject.',
|
|
85
|
+
hint: 'Run `aid gen` first; ejection transfers a file the generator wrote.',
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
const record = manifestRecordFor(manifest, path);
|
|
89
|
+
if (record === undefined) {
|
|
90
|
+
// A business path the generator never planned is already owned by the developer;
|
|
91
|
+
// asking to eject it is a no-op, not a mistake. The same is true of a generated path
|
|
92
|
+
// already in the ledger: the file has moved, so there is no record left, and the
|
|
93
|
+
// ledger is the only proof the transfer happened. Without this lookup a second eject
|
|
94
|
+
// would report "not generated" for a file this command ejected itself. Scaffold paths
|
|
95
|
+
// are handled above, before the manifest guard.
|
|
96
|
+
if (ownerForPath(path, request) === 'business' || manifest.ejected.includes(path)) {
|
|
97
|
+
return { ok: true, status: 'already-owned', from: path, dryRun, diagnostics: [] };
|
|
98
|
+
}
|
|
99
|
+
return refuse(generatorError({
|
|
100
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectNotGenerated,
|
|
101
|
+
message: `"${path}" is not recorded in the manifest, so there is no generated artifact to take ownership of.`,
|
|
102
|
+
path,
|
|
103
|
+
hint: 'Eject a path the manifest lists as generated; `aid doctor` prints them.',
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
if (record.owner === 'business') {
|
|
107
|
+
return { ok: true, status: 'already-owned', from: record.path, dryRun, diagnostics: [] };
|
|
108
|
+
}
|
|
109
|
+
const to = businessPathFor(record.path, request);
|
|
110
|
+
if (to === undefined) {
|
|
111
|
+
return refuse(generatorError({
|
|
112
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectInvalidPath,
|
|
113
|
+
message: `"${record.path}" has no business-tier counterpart under the configured roots.`,
|
|
114
|
+
path: record.path,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
const content = request.sink.read(record.path);
|
|
118
|
+
if (content === undefined) {
|
|
119
|
+
return refuse(generatorError({
|
|
120
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectMissingFile,
|
|
121
|
+
message: `"${record.path}" is recorded as generated but is missing from the tree.`,
|
|
122
|
+
path: record.path,
|
|
123
|
+
hint: 'Run `aid gen` to restore it, then eject.',
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
const existing = request.sink.read(to);
|
|
127
|
+
if (existing !== undefined && existing !== content) {
|
|
128
|
+
return refuse(generatorError({
|
|
129
|
+
code: GENERATOR_DIAGNOSTIC_CODES.ejectDestinationExists,
|
|
130
|
+
message: `"${to}" already exists and differs from "${record.path}"; ejecting would overwrite developer-owned content.`,
|
|
131
|
+
path: to,
|
|
132
|
+
hint: 'Move or delete that file yourself, then run eject again.',
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
const written = existing === undefined;
|
|
136
|
+
if (!dryRun) {
|
|
137
|
+
if (written)
|
|
138
|
+
request.sink.write(to, content);
|
|
139
|
+
request.sink.remove(record.path);
|
|
140
|
+
}
|
|
141
|
+
const businessRecord = {
|
|
142
|
+
path: to,
|
|
143
|
+
owner: 'business',
|
|
144
|
+
sha256: sha256Hex(content),
|
|
145
|
+
generator: record.generator,
|
|
146
|
+
generatorVersion: record.generatorVersion,
|
|
147
|
+
};
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
status: 'ejected',
|
|
151
|
+
from: record.path,
|
|
152
|
+
to,
|
|
153
|
+
written,
|
|
154
|
+
dryRun,
|
|
155
|
+
manifest: {
|
|
156
|
+
manifestVersion: manifest.manifestVersion,
|
|
157
|
+
generatedBy: manifest.generatedBy,
|
|
158
|
+
files: sortByPath([
|
|
159
|
+
...manifest.files.filter((file) => file.path !== record.path && file.path !== to),
|
|
160
|
+
businessRecord,
|
|
161
|
+
]),
|
|
162
|
+
// Sorted and de-duplicated: two routes to the same exclusion must not produce two
|
|
163
|
+
// entries, and a stable order is what makes the manifest byte-comparable.
|
|
164
|
+
ejected: [...new Set([...manifest.ejected, record.path])].sort(),
|
|
165
|
+
},
|
|
166
|
+
diagnostics: [],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=eject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eject.js","sourceRoot":"","sources":["../src/eject.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,13 +16,17 @@ export type { GeneratorDiagnostic, GeneratorDiagnosticCode } from './diagnostics
|
|
|
16
16
|
export { GENERATOR_DIAGNOSTIC_CODES, generatorError, generatorWarning, withFile, } from './diagnostics.js';
|
|
17
17
|
export type { DriftedFile, RegenerationAction, RegenerationOptions, RegenerationReport, RegenerationResult, RegenerationSink, } from './drift.js';
|
|
18
18
|
export { checkDrift, formatRegenerationSummary, generatedFiles, hasDrift, planRegeneration, regenerate, staleGeneratedFiles, } from './drift.js';
|
|
19
|
+
export type { EjectRequest, EjectResult, EjectStatus, ManagedPathOptions } from './eject.js';
|
|
20
|
+
export { businessPathFor, eject } from './eject.js';
|
|
19
21
|
export type { EmitsAgainst, GeneratorManifest, GeneratorManifestInput, GeneratorOutput, ManifestParseResult, Orchestration, StructuredOutput, TracingBackend, } from './manifest.js';
|
|
20
22
|
export { checkIRSupport, GENERATOR_MANIFEST_VERSION, managedRoots, ORCHESTRATIONS, parseManifest, parseManifestJson, STRUCTURED_OUTPUTS, supportsIR, TRACING_BACKENDS, targetCapabilityDeclarations, validateGeneratorSet, validateManifest, } from './manifest.js';
|
|
21
23
|
export { createMemorySink, createNodeSink } from './node-sink.js';
|
|
22
24
|
export type { FileOwner } from './ownership.js';
|
|
23
|
-
export { DEFAULT_BUSINESS_DIR, DEFAULT_GENERATED_DIR, DEFAULT_MANIFEST_FILENAME, escapesRoot, isAbsolutePath, isBusinessPath, isGeneratedPath, isRelativePath, isReservedPath, normalizeRelativePath, ownerForPath, REJECTION_SUFFIX, rejectionPath, } from './ownership.js';
|
|
25
|
+
export { DEFAULT_BUSINESS_DIR, DEFAULT_GENERATED_DIR, DEFAULT_MANIFEST_FILENAME, escapesRoot, isAbsolutePath, isBusinessPath, isGeneratedPath, isRelativePath, isReservedPath, isScaffoldPath, normalizeRelativePath, ownerForPath, REJECTION_SUFFIX, rejectionPath, SCAFFOLD_PREFIXES, } from './ownership.js';
|
|
24
26
|
export type { GeneratedFile, Generator, GeneratorContext, Plan, PlanValidationOptions, } from './plan.js';
|
|
25
27
|
export { isRecord, validatePlan } from './plan.js';
|
|
28
|
+
export type { CiProfile, EvalProfile, EvalSuite } from './scaffold.js';
|
|
29
|
+
export { ACTION_PINS, CI_WORKFLOW_PATH, cliRangeFor, EVALS_WORKFLOW_PATH, scaffoldCi, scaffoldEvals, } from './scaffold.js';
|
|
26
30
|
export type { Version } from './semver.js';
|
|
27
31
|
export { compareVersions, formatVersion, isValidRange, isValidVersion, parseRange, parseVersion, satisfies, } from './semver.js';
|
|
28
32
|
export { PY_FASTAPI_MANIFEST, PY_FASTAPI_MANIFEST_INPUT, PY_FASTAPI_TARGET, phase0Generators, phase0TargetCapabilities, } from './targets.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EACV,WAAW,EACX,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,gBAAgB,EAChB,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,YAAY,EACZ,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,4BAA4B,EAC5B,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -12,10 +12,12 @@ export { AID_MANIFEST_VERSION, emptyAidManifest, manifestFor, manifestRecordFor,
|
|
|
12
12
|
export { checkDeterminism, compareIds, DETERMINISM_PATTERNS, ensureTrailingNewline, GENERATED_BANNER_MARKER, generatedBanner, normalizeNewlines, normalizeText, scanForNonDeterminism, sha256Hex, sortById, sortByPath, stableId, stableSortBy, } from './determinism.js';
|
|
13
13
|
export { GENERATOR_DIAGNOSTIC_CODES, generatorError, generatorWarning, withFile, } from './diagnostics.js';
|
|
14
14
|
export { checkDrift, formatRegenerationSummary, generatedFiles, hasDrift, planRegeneration, regenerate, staleGeneratedFiles, } from './drift.js';
|
|
15
|
+
export { businessPathFor, eject } from './eject.js';
|
|
15
16
|
export { checkIRSupport, GENERATOR_MANIFEST_VERSION, managedRoots, ORCHESTRATIONS, parseManifest, parseManifestJson, STRUCTURED_OUTPUTS, supportsIR, TRACING_BACKENDS, targetCapabilityDeclarations, validateGeneratorSet, validateManifest, } from './manifest.js';
|
|
16
17
|
export { createMemorySink, createNodeSink } from './node-sink.js';
|
|
17
|
-
export { DEFAULT_BUSINESS_DIR, DEFAULT_GENERATED_DIR, DEFAULT_MANIFEST_FILENAME, escapesRoot, isAbsolutePath, isBusinessPath, isGeneratedPath, isRelativePath, isReservedPath, normalizeRelativePath, ownerForPath, REJECTION_SUFFIX, rejectionPath, } from './ownership.js';
|
|
18
|
+
export { DEFAULT_BUSINESS_DIR, DEFAULT_GENERATED_DIR, DEFAULT_MANIFEST_FILENAME, escapesRoot, isAbsolutePath, isBusinessPath, isGeneratedPath, isRelativePath, isReservedPath, isScaffoldPath, normalizeRelativePath, ownerForPath, REJECTION_SUFFIX, rejectionPath, SCAFFOLD_PREFIXES, } from './ownership.js';
|
|
18
19
|
export { isRecord, validatePlan } from './plan.js';
|
|
20
|
+
export { ACTION_PINS, CI_WORKFLOW_PATH, cliRangeFor, EVALS_WORKFLOW_PATH, scaffoldCi, scaffoldEvals, } from './scaffold.js';
|
|
19
21
|
export { compareVersions, formatVersion, isValidRange, isValidVersion, parseRange, parseVersion, satisfies, } from './semver.js';
|
|
20
22
|
export { PY_FASTAPI_MANIFEST, PY_FASTAPI_MANIFEST_INPUT, PY_FASTAPI_TARGET, phase0Generators, phase0TargetCapabilities, } from './targets.js';
|
|
21
23
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,gBAAgB,EAChB,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,mBAAmB,GACpB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,gBAAgB,EAChB,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAWpD,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,YAAY,EACZ,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,4BAA4B,EAC5B,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAQxB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,cAAc,CAAC"}
|
package/dist/ownership.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ownership and path rules (§8.3, §8.4, §10).
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
4
|
+
* The tier split is the whole reason regeneration is safe: `generated/` is
|
|
5
5
|
* generator-owned and never hand-edited, `business/` is developer-owned and written
|
|
6
6
|
* once, and the ownership of a path is decided by *where it lives*, not by what a
|
|
7
7
|
* generator happens to say about it. Every path in a plan is normalized through this
|
|
8
8
|
* module, so a generator cannot escape its own root or claim a business path as
|
|
9
9
|
* generated (or the reverse).
|
|
10
|
+
*
|
|
11
|
+
* `scaffold` is the third tier: generator-authored content that lives *outside* the
|
|
12
|
+
* managed roots, which today means the repository's own CI workflows. It is written
|
|
13
|
+
* once and then belongs to the developer, so it is never recorded in the manifest --
|
|
14
|
+
* there is no hash to compare against, and claiming one would make every edit a drift
|
|
15
|
+
* conflict. The allowlist exists so that "outside the managed roots" does not become
|
|
16
|
+
* "anywhere": a generator may only reach paths it is explicitly permitted to own.
|
|
17
|
+
*/
|
|
18
|
+
export type FileOwner = 'generated' | 'business' | 'scaffold';
|
|
19
|
+
/**
|
|
20
|
+
* The only path prefixes a generator may scaffold. A prefix, not a glob, so the check
|
|
21
|
+
* stays a string comparison and a generator cannot smuggle a nested escape past it.
|
|
10
22
|
*/
|
|
11
|
-
export
|
|
23
|
+
export declare const SCAFFOLD_PREFIXES: readonly ['.github/workflows/'];
|
|
12
24
|
export declare const DEFAULT_GENERATED_DIR = "generated";
|
|
13
25
|
export declare const DEFAULT_BUSINESS_DIR = "business";
|
|
14
26
|
/** The ownership manifest. Generator bookkeeping, so it is never a planned artifact. */
|
|
@@ -35,6 +47,11 @@ export declare function ownerForPath(path: string, options?: {
|
|
|
35
47
|
generatedDir?: string;
|
|
36
48
|
businessDir?: string;
|
|
37
49
|
}): FileOwner | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* True for a path inside the scaffold allowlist. Requires a file name after the
|
|
52
|
+
* prefix: `.github/workflows/` itself is the directory, not a workflow.
|
|
53
|
+
*/
|
|
54
|
+
export declare function isScaffoldPath(path: string): boolean;
|
|
38
55
|
export declare function isGeneratedPath(path: string, options?: {
|
|
39
56
|
generatedDir?: string;
|
|
40
57
|
businessDir?: string;
|
package/dist/ownership.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ownership.d.ts","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ownership.d.ts","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,YAAI,oBAAoB,CAAU,CAAC;AAEjE,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUtE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAUD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5D,SAAS,GAAG,SAAS,CAWvB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMpD;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5D,OAAO,CAET;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5D,OAAO,CAET;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAI9E"}
|
package/dist/ownership.js
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ownership and path rules (§8.3, §8.4, §10).
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
4
|
+
* The tier split is the whole reason regeneration is safe: `generated/` is
|
|
5
5
|
* generator-owned and never hand-edited, `business/` is developer-owned and written
|
|
6
6
|
* once, and the ownership of a path is decided by *where it lives*, not by what a
|
|
7
7
|
* generator happens to say about it. Every path in a plan is normalized through this
|
|
8
8
|
* module, so a generator cannot escape its own root or claim a business path as
|
|
9
9
|
* generated (or the reverse).
|
|
10
|
+
*
|
|
11
|
+
* `scaffold` is the third tier: generator-authored content that lives *outside* the
|
|
12
|
+
* managed roots, which today means the repository's own CI workflows. It is written
|
|
13
|
+
* once and then belongs to the developer, so it is never recorded in the manifest --
|
|
14
|
+
* there is no hash to compare against, and claiming one would make every edit a drift
|
|
15
|
+
* conflict. The allowlist exists so that "outside the managed roots" does not become
|
|
16
|
+
* "anywhere": a generator may only reach paths it is explicitly permitted to own.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The only path prefixes a generator may scaffold. A prefix, not a glob, so the check
|
|
20
|
+
* stays a string comparison and a generator cannot smuggle a nested escape past it.
|
|
10
21
|
*/
|
|
22
|
+
export const SCAFFOLD_PREFIXES = ['.github/workflows/'];
|
|
11
23
|
export const DEFAULT_GENERATED_DIR = 'generated';
|
|
12
24
|
export const DEFAULT_BUSINESS_DIR = 'business';
|
|
13
25
|
/** The ownership manifest. Generator bookkeeping, so it is never a planned artifact. */
|
|
@@ -68,8 +80,20 @@ export function ownerForPath(path, options = {}) {
|
|
|
68
80
|
return 'generated';
|
|
69
81
|
if (normalized === businessDir || normalized.startsWith(`${businessDir}/`))
|
|
70
82
|
return 'business';
|
|
83
|
+
if (isScaffoldPath(normalized))
|
|
84
|
+
return 'scaffold';
|
|
71
85
|
return undefined;
|
|
72
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* True for a path inside the scaffold allowlist. Requires a file name after the
|
|
89
|
+
* prefix: `.github/workflows/` itself is the directory, not a workflow.
|
|
90
|
+
*/
|
|
91
|
+
export function isScaffoldPath(path) {
|
|
92
|
+
const normalized = normalizeRelativePath(path);
|
|
93
|
+
if (normalized === undefined)
|
|
94
|
+
return false;
|
|
95
|
+
return SCAFFOLD_PREFIXES.some((prefix) => normalized.startsWith(prefix) && normalized.length > prefix.length);
|
|
96
|
+
}
|
|
73
97
|
export function isGeneratedPath(path, options = {}) {
|
|
74
98
|
return ownerForPath(path, options) === 'generated';
|
|
75
99
|
}
|
package/dist/ownership.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ownership.js","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ownership.js","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold content: generator-authored files that live outside the managed roots (§6a).
|
|
3
|
+
*
|
|
4
|
+
* Today that is the repository's own CI. It is planned like any other file, but it is
|
|
5
|
+
* written once and then belongs to the developer: `aid gen` never overwrites it, never
|
|
6
|
+
* records it in the manifest, and `aid eject` reports it as already owned. That split is
|
|
7
|
+
* what makes a generated workflow usable -- CI has to be edited for a runner, a
|
|
8
|
+
* credential, or a second toolchain, and every one of those edits would otherwise be a
|
|
9
|
+
* drift conflict against a file the developer is supposed to own.
|
|
10
|
+
*
|
|
11
|
+
* The emitted workflow deliberately contains **no** `apply` step and no cloud keys: it
|
|
12
|
+
* gates the repository and stops there. Deployment stays a human action, per §12.6.
|
|
13
|
+
*/
|
|
14
|
+
import type { GeneratedFile } from './plan.js';
|
|
15
|
+
/** The repository CI: the spec gates, then lint/build/test for the app tier. */
|
|
16
|
+
export declare const CI_WORKFLOW_PATH = ".github/workflows/ci.yml";
|
|
17
|
+
/**
|
|
18
|
+
* The eval gate. A separate workflow because it needs a model credential and therefore
|
|
19
|
+
* cannot be a required check on a fork pull request: it runs on `workflow_dispatch` and
|
|
20
|
+
* nightly, and reports a skip -- not a pass -- when the credential is absent.
|
|
21
|
+
*/
|
|
22
|
+
export declare const EVALS_WORKFLOW_PATH = ".github/workflows/evals.yml";
|
|
23
|
+
/**
|
|
24
|
+
* Action pins. A tag is mutable; a SHA is not, and a generated workflow that runs
|
|
25
|
+
* `@v4` is one force-push away from running different code than it did last week.
|
|
26
|
+
* These are the commits the `v4`/`v5` tags resolved to when this was written.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ACTION_PINS: {
|
|
29
|
+
readonly checkout: 'actions/checkout@11d5960a326750d5838078e36cf38b85af677262';
|
|
30
|
+
readonly setupNode: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020';
|
|
31
|
+
readonly setupPython: 'actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065';
|
|
32
|
+
};
|
|
33
|
+
export interface CiProfile {
|
|
34
|
+
/** The target name, used in the workflow's title so a reader knows what generated it. */
|
|
35
|
+
readonly target: string;
|
|
36
|
+
/** Spec path relative to the repository root. */
|
|
37
|
+
readonly specPath: string;
|
|
38
|
+
/**
|
|
39
|
+
* The file that proves the app tier has dependencies to install.
|
|
40
|
+
* When it is absent the build job is *skipped*, not green: the repository has a spec
|
|
41
|
+
* but no application yet, and a check that passes because it never ran is the failure
|
|
42
|
+
* mode §6a exists to prevent.
|
|
43
|
+
*/
|
|
44
|
+
readonly dependencyManifest: string;
|
|
45
|
+
/** Steps that put the language toolchain on the runner, as prepared YAML lines. */
|
|
46
|
+
readonly toolchain: readonly string[];
|
|
47
|
+
/** Shell lines that install the app's dependencies. */
|
|
48
|
+
readonly install: readonly string[];
|
|
49
|
+
/** Shell lines for lint/format. */
|
|
50
|
+
readonly lint: readonly string[];
|
|
51
|
+
/** Shell line for the type check or build. */
|
|
52
|
+
readonly build: string;
|
|
53
|
+
/** Shell line for the unit tests. */
|
|
54
|
+
readonly test: string;
|
|
55
|
+
}
|
|
56
|
+
/** One generated eval module and the command that runs it from the project root. */
|
|
57
|
+
export interface EvalSuite {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly command: string;
|
|
60
|
+
}
|
|
61
|
+
export interface EvalProfile {
|
|
62
|
+
/** The target name, used in the workflow's title so a reader knows what generated it. */
|
|
63
|
+
readonly target: string;
|
|
64
|
+
/** Spec path relative to the repository root. */
|
|
65
|
+
readonly specPath: string;
|
|
66
|
+
/** Steps that put the language toolchain on the runner, as prepared YAML lines. */
|
|
67
|
+
readonly toolchain: readonly string[];
|
|
68
|
+
/** Shell lines that install the app's dependencies. */
|
|
69
|
+
readonly install: readonly string[];
|
|
70
|
+
/** The CI-gated evals, in declaration order. Never empty when a workflow is emitted. */
|
|
71
|
+
readonly suites: readonly EvalSuite[];
|
|
72
|
+
/**
|
|
73
|
+
* Environment variables the generated gateway reads a model key from. When this is
|
|
74
|
+
* empty every model is a fake, so the gate runs unguarded. When it is not, the gate is
|
|
75
|
+
* skipped with a warning unless every one of them is set: a real model behind a gate
|
|
76
|
+
* cannot be measured without its credential.
|
|
77
|
+
*/
|
|
78
|
+
readonly secrets: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
/** `major.minor` of a semver string, used to pin the CLI a workflow installs. */
|
|
81
|
+
export declare function cliRangeFor(version: string): string;
|
|
82
|
+
/**
|
|
83
|
+
* The CI workflow for a generated project.
|
|
84
|
+
*
|
|
85
|
+
* The spec gates are the framework's own contract and always run. The app job needs the
|
|
86
|
+
* project's dependency manifest, and a job-level `if` cannot call `hashFiles`, so a small
|
|
87
|
+
* `detect` job probes for the file and the app job is skipped -- not green -- without it.
|
|
88
|
+
* The infra job is skipped the same way when `infra/` is absent, and it only compares the
|
|
89
|
+
* committed tree against the spec: `plan`/`apply` need credentials and stay human actions.
|
|
90
|
+
*/
|
|
91
|
+
export declare function scaffoldCi(profile: CiProfile, cliRange: string): GeneratedFile;
|
|
92
|
+
/**
|
|
93
|
+
* The eval gate for a project whose spec declares `gate.ci: true` evals.
|
|
94
|
+
*
|
|
95
|
+
* It never runs on `pull_request`. The generated evals measure a real model: with no
|
|
96
|
+
* credential the gateway falls back to the fake provider, whose output does not satisfy
|
|
97
|
+
* the eval's JSON schema, and the gate fails. Requiring the key on PRs would therefore
|
|
98
|
+
* either leak a secret to forks or turn the gate red for every contributor, so the gate
|
|
99
|
+
* runs on `workflow_dispatch` and nightly instead, and a missing key is an **error**
|
|
100
|
+
* rather than a silent skip: a gate that is green because it never ran is the failure
|
|
101
|
+
* mode this whole tier exists to avoid.
|
|
102
|
+
*/
|
|
103
|
+
export declare function scaffoldEvals(profile: EvalProfile): GeneratedFile;
|
|
104
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,WAAW;aACtB,QAAQ,EAAE,2DAA2D;aACrE,SAAS,EAAE,6DAA6D;aACxE,WAAW,EAAE,+DAA+D;CACpE,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,oFAAoF;AACpF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGnD;AAMD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CA2G9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,CAqFjE"}
|