@open-agent-toolkit/cli 0.3.9 → 0.3.11
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 +2 -1
- package/assets/bundle-metadata.json +1 -1
- package/assets/config/dispatch-matrix-recommendation.json +6 -6
- package/assets/docs/cli-utilities/configuration.md +12 -8
- package/assets/docs/cli-utilities/meta.json +13 -0
- package/assets/docs/cli-utilities/tool-packs.md +8 -2
- package/assets/docs/cli-utilities/workflow-gates.md +14 -1
- package/assets/docs/contributing/code.md +8 -2
- package/assets/docs/contributing/documentation.md +7 -1
- package/assets/docs/contributing/meta.json +15 -0
- package/assets/docs/contributing/updating-model-guidance.md +34 -6
- package/assets/docs/contributing/verifying-cursor-pins.md +38 -9
- package/assets/docs/docs-tooling/add-docs-to-a-repo.md +14 -5
- package/assets/docs/docs-tooling/commands.md +26 -8
- package/assets/docs/docs-tooling/meta.json +4 -0
- package/assets/docs/docs-tooling/workflows.md +2 -2
- package/assets/docs/guide/meta.json +4 -0
- package/assets/docs/meta.json +14 -0
- package/assets/docs/provider-sync/instruction-sync.md +8 -0
- package/assets/docs/provider-sync/meta.json +11 -0
- package/assets/docs/provider-sync/providers.md +4 -4
- package/assets/docs/provider-sync/scope-and-surface.md +3 -4
- package/assets/docs/reference/cli-reference.md +5 -2
- package/assets/docs/reference/docs-index-contract.md +22 -6
- package/assets/docs/reference/file-locations.md +7 -2
- package/assets/docs/reference/index.md +1 -1
- package/assets/docs/reference/meta.json +10 -0
- package/assets/docs/reference/troubleshooting.md +41 -6
- package/assets/docs/workflows/ideas/meta.json +4 -0
- package/assets/docs/workflows/meta.json +4 -0
- package/assets/docs/workflows/projects/cursor-cloud.md +8 -3
- package/assets/docs/workflows/projects/dispatch-ceiling.md +21 -14
- package/assets/docs/workflows/projects/evidence-layers.md +6 -8
- package/assets/docs/workflows/projects/implementation-execution.md +34 -5
- package/assets/docs/workflows/projects/lifecycle.md +7 -1
- package/assets/docs/workflows/projects/meta.json +25 -0
- package/assets/docs/workflows/projects/orchestration-model.md +5 -6
- package/assets/docs/workflows/skills/meta.json +10 -0
- package/assets/docs/workflows/skills/recon.md +28 -3
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-cursor-cloud-projects/SKILL.md +30 -16
- package/assets/skills/oat-dispatch-subagents/SKILL.md +4 -12
- package/assets/skills/oat-dispatch-subagents/references/managed-claude-example.json +1 -1
- package/assets/skills/oat-dispatch-subagents/references/provider-codex.md +51 -0
- package/assets/skills/oat-dispatch-subagents/references/provider-cursor.md +5 -2
- package/assets/skills/oat-dispatch-subagents/references/record-schema.md +8 -7
- package/assets/skills/oat-docs-analyze/SKILL.md +28 -3
- package/assets/skills/oat-docs-apply/SKILL.md +3 -3
- package/assets/skills/oat-docs-authoring/SKILL.md +1 -1
- package/assets/skills/oat-docs-authoring/references/oat-fumadocs-contract.md +5 -2
- package/assets/skills/oat-docs-bootstrap/SKILL.md +4 -3
- package/assets/skills/oat-docs-bootstrap/assets/AGENTS.md.template +3 -3
- package/assets/skills/oat-pjm-decision/SKILL.md +3 -2
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +4 -4
- package/assets/skills/oat-project-complete/SKILL.md +47 -2
- package/assets/skills/oat-project-design/SKILL.md +10 -6
- package/assets/skills/oat-project-discover/SKILL.md +3 -3
- package/assets/skills/oat-project-dispatch-subagents/SKILL.md +3 -10
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +135 -3
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +8 -10
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +1 -1
- package/assets/skills/oat-project-import-plan/SKILL.md +3 -3
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-new/SKILL.md +3 -3
- package/assets/skills/oat-project-next/SKILL.md +50 -7
- package/assets/skills/oat-project-plan/SKILL.md +4 -4
- package/assets/skills/oat-project-plan-writing/SKILL.md +4 -4
- package/assets/skills/oat-project-pr-final/SKILL.md +11 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +2 -2
- package/assets/skills/oat-project-quick-start/SKILL.md +12 -8
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-retro/SKILL.md +6 -3
- package/assets/skills/oat-project-review-provide/SKILL.md +2 -2
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +2 -2
- package/assets/skills/oat-project-spec/SKILL.md +3 -3
- package/assets/skills/oat-project-summary/SKILL.md +22 -3
- package/assets/skills/oat-repo-improve/SKILL.md +2 -2
- package/assets/skills/recon/SKILL.md +24 -3
- package/assets/skills/recon/references/packet-contract.md +36 -6
- package/assets/skills/recon/references/profiles.md +3 -0
- package/assets/skills/recon/references/worker-contract.md +16 -3
- package/assets/skills/recon/scripts/create-review-brief.mjs +17 -86
- package/assets/skills/recon/scripts/lib/contracts.mjs +158 -41
- package/assets/skills/recon/scripts/lib/review-binding.mjs +123 -0
- package/assets/skills/recon/scripts/lib/routing.mjs +5 -2
- package/assets/skills/recon/scripts/reconcile-ledger.mjs +18 -7
- package/assets/skills/recon/scripts/render-packet.mjs +93 -1
- package/assets/skills/recon/scripts/validate-packet.mjs +119 -88
- package/assets/skills/subagent-orchestration/SKILL.md +1 -1
- package/assets/skills/subagent-orchestration/references/evidence-and-refresh.md +20 -8
- package/assets/skills/subagent-orchestration/references/provider-claude.md +25 -12
- package/assets/skills/subagent-orchestration/references/provider-codex.md +27 -18
- package/assets/skills/subagent-orchestration/references/provider-cursor.md +40 -10
- package/assets/templates/state.md +1 -0
- package/dist/commands/backlog/new.d.ts +2 -2
- package/dist/commands/backlog/new.d.ts.map +1 -1
- package/dist/commands/backlog/new.js +2 -2
- package/dist/commands/decision/new.d.ts +2 -2
- package/dist/commands/decision/new.d.ts.map +1 -1
- package/dist/commands/decision/new.js +2 -2
- package/dist/commands/docs/nav/contents.d.ts +9 -0
- package/dist/commands/docs/nav/contents.d.ts.map +1 -1
- package/dist/commands/docs/nav/contents.js +7 -2
- package/dist/commands/docs/nav/fumadocs.d.ts +51 -0
- package/dist/commands/docs/nav/fumadocs.d.ts.map +1 -0
- package/dist/commands/docs/nav/fumadocs.js +301 -0
- package/dist/commands/docs/nav/sync.d.ts +31 -1
- package/dist/commands/docs/nav/sync.d.ts.map +1 -1
- package/dist/commands/docs/nav/sync.js +163 -6
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/instructions/instructions.utils.d.ts +19 -0
- package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.js +89 -17
- package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
- package/dist/commands/instructions/sync/sync.js +49 -2
- package/dist/commands/pjm/init.d.ts.map +1 -1
- package/dist/commands/pjm/init.js +2 -2
- package/dist/commands/project/closeout-check/closeout-invariant.d.ts +97 -0
- package/dist/commands/project/closeout-check/closeout-invariant.d.ts.map +1 -0
- package/dist/commands/project/closeout-check/closeout-invariant.js +301 -0
- package/dist/commands/project/closeout-check/index.d.ts +38 -0
- package/dist/commands/project/closeout-check/index.d.ts.map +1 -0
- package/dist/commands/project/closeout-check/index.js +117 -0
- package/dist/commands/project/complete-state/index.d.ts +4 -0
- package/dist/commands/project/complete-state/index.d.ts.map +1 -1
- package/dist/commands/project/complete-state/index.js +11 -13
- package/dist/commands/project/dispatch/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch/index.js +6 -30
- package/dist/commands/project/dispatch/record.d.ts +9 -18
- package/dist/commands/project/dispatch/record.d.ts.map +1 -1
- package/dist/commands/project/dispatch/record.js +15 -212
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/project/new/scaffold.d.ts +0 -1
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +19 -20
- package/dist/commands/project/promote/promote.d.ts +2 -2
- package/dist/commands/project/promote/promote.d.ts.map +1 -1
- package/dist/commands/project/promote/promote.js +13 -11
- package/dist/commands/shared/frontmatter.d.ts +21 -0
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +70 -4
- package/dist/commands/shared/template-source.d.ts +29 -0
- package/dist/commands/shared/template-source.d.ts.map +1 -0
- package/dist/commands/{pjm → shared}/template-source.js +24 -7
- package/dist/commands/state/generate.js +2 -2
- package/dist/commands/template/index.d.ts +10 -0
- package/dist/commands/template/index.d.ts.map +1 -0
- package/dist/commands/template/index.js +87 -0
- package/dist/commands/template/resolve.d.ts +31 -0
- package/dist/commands/template/resolve.d.ts.map +1 -0
- package/dist/commands/template/resolve.js +86 -0
- package/dist/fs/io.d.ts +0 -41
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +2 -414
- package/dist/providers/claude/dispatch-envelope.d.ts.map +1 -1
- package/dist/providers/claude/dispatch-envelope.js +1 -0
- package/dist/providers/claude/targets.d.ts +1 -0
- package/dist/providers/claude/targets.d.ts.map +1 -1
- package/dist/providers/claude/targets.js +3 -1
- package/dist/providers/codex/codec/shared.d.ts +3 -0
- package/dist/providers/codex/codec/shared.d.ts.map +1 -1
- package/dist/providers/codex/codec/shared.js +4 -0
- package/dist/providers/cursor/codec/catalog.d.ts +2 -2
- package/dist/providers/cursor/codec/catalog.d.ts.map +1 -1
- package/dist/providers/cursor/codec/catalog.js +45 -0
- package/dist/providers/cursor/codec/mapping-validation.d.ts +4 -0
- package/dist/providers/cursor/codec/mapping-validation.d.ts.map +1 -0
- package/dist/providers/cursor/codec/mapping-validation.js +25 -0
- package/dist/providers/cursor/codec/materialize.d.ts.map +1 -1
- package/dist/providers/cursor/codec/materialize.js +2 -11
- package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/cursor/codec/sync-extension.js +2 -11
- package/dist/providers/identity/absolute-paths.d.ts +4 -13
- package/dist/providers/identity/absolute-paths.d.ts.map +1 -1
- package/dist/providers/identity/absolute-paths.js +4 -17
- package/dist/providers/identity/generic-dispatch-record.d.ts +1 -1
- package/dist/providers/identity/generic-dispatch-record.js +2 -2
- package/dist/providers/identity/oat-dispatch-record.d.ts +4 -357
- package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -1
- package/dist/providers/identity/oat-dispatch-record.js +4 -236
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +12 -4
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +32 -6
- package/package.json +2 -2
- package/dist/commands/pjm/template-source.d.ts +0 -14
- package/dist/commands/pjm/template-source.d.ts.map +0 -1
|
@@ -1,43 +1,11 @@
|
|
|
1
|
-
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { publishContainedJsonRevision, redactedFsError, withContainedWriterLock, } from '../../../fs/io.js';
|
|
4
1
|
import { acceptClaudeLaunchEnvelope, buildClaudeDispatchRecord, collectClaudeLaunchViolations, collectClaudeRecordBaseViolations, ManagedClaudeDispatchValidationError, zodIssueViolations, } from '../../../providers/claude/dispatch-envelope.js';
|
|
5
|
-
import {
|
|
2
|
+
import { redactAbsolutePaths } from '../../../providers/identity/absolute-paths.js';
|
|
6
3
|
import { CLAUDE_OBSERVATION_SOURCE } from '../../../providers/identity/claude-runtime-observation.js';
|
|
7
4
|
import { CODEX_OBSERVATION_SOURCE } from '../../../providers/identity/codex-runtime-observation.js';
|
|
8
|
-
import {
|
|
9
|
-
import { augmentDispatchRecord, compareObservedRuntimeMetadata, comparedObservationAxes, configuredInvocationForObservation,
|
|
5
|
+
import { assertNoSensitiveDispatchContent, collectSensitiveDispatchContent, parseGenericDispatchRecord, redactSensitiveValues, } from '../../../providers/identity/generic-dispatch-record.js';
|
|
6
|
+
import { augmentDispatchRecord, compareObservedRuntimeMetadata, comparedObservationAxes, configuredInvocationForObservation, parseRuntimeObservation, safeParseOatDispatchEvidenceEvent, } from '../../../providers/identity/oat-dispatch-record.js';
|
|
10
7
|
import { observationFromFacts, parseRuntimeObservationEnvelope, projectRuntimeObservation, providerSupportsRuntimeObservation, } from '../../../providers/identity/runtime-observation.js';
|
|
11
8
|
import { ZodError } from 'zod';
|
|
12
|
-
const REQUEST_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
|
|
13
|
-
const DISPATCH_LOCK_NAME = '.dispatch-lock';
|
|
14
|
-
/**
|
|
15
|
-
* The journal is append-only. Revision 1 keeps the plain `<request-id>.json`
|
|
16
|
-
* name; every later revision is published create-only under
|
|
17
|
-
* `<request-id>@<NNNN>.json`. Publishing revision N+1 exclusively is the
|
|
18
|
-
* compare-and-swap: a caller that lost the race observes `EEXIST` instead of
|
|
19
|
-
* replacing the winner, and no publication can ever clobber an existing file.
|
|
20
|
-
* `@` is outside the request-ID character class, so the split is unambiguous.
|
|
21
|
-
*/
|
|
22
|
-
const REVISION_SEPARATOR = '@';
|
|
23
|
-
const REVISION_SUFFIX_PATTERN = /^(.*)@(\d{4})$/;
|
|
24
|
-
const MAX_REVISION = 9999;
|
|
25
|
-
function revisionFileName(requestId, revision) {
|
|
26
|
-
return revision === 1
|
|
27
|
-
? `${requestId}.json`
|
|
28
|
-
: `${requestId}${REVISION_SEPARATOR}${String(revision).padStart(4, '0')}.json`;
|
|
29
|
-
}
|
|
30
|
-
function parseJournalEntry(fileName) {
|
|
31
|
-
if (!fileName.endsWith('.json'))
|
|
32
|
-
return null;
|
|
33
|
-
const stem = fileName.slice(0, -'.json'.length);
|
|
34
|
-
const suffixed = REVISION_SUFFIX_PATTERN.exec(stem);
|
|
35
|
-
const requestId = suffixed?.[1] ?? stem;
|
|
36
|
-
const revision = suffixed ? Number(suffixed[2]) : 1;
|
|
37
|
-
if (!REQUEST_ID_PATTERN.test(requestId) || revision < 1)
|
|
38
|
-
return null;
|
|
39
|
-
return { requestId, revision, fileName };
|
|
40
|
-
}
|
|
41
9
|
/**
|
|
42
10
|
* Hard redaction boundary. Producers redact their own messages, but this is the
|
|
43
11
|
* last stop before a message reaches `--json`, so a future call site that
|
|
@@ -46,7 +14,7 @@ function parseJournalEntry(fileName) {
|
|
|
46
14
|
*
|
|
47
15
|
* The detector is shared with the record sanitizer. Two independent notions of
|
|
48
16
|
* "looks like a path" is how a path could be scrubbed from an error message and
|
|
49
|
-
*
|
|
17
|
+
* emitted verbatim in the validated record by the same command.
|
|
50
18
|
*/
|
|
51
19
|
export function redactDispatchMessage(message, roots = {}) {
|
|
52
20
|
// Secrets first: a rejected value is echoed by some validation messages (a
|
|
@@ -54,11 +22,10 @@ export function redactDispatchMessage(message, roots = {}) {
|
|
|
54
22
|
// scrubbed here even though the same run also reports it as sensitive.
|
|
55
23
|
let redacted = redactSensitiveValues(message);
|
|
56
24
|
const labelled = [
|
|
57
|
-
['<project>', roots.project],
|
|
58
25
|
['<repo>', roots.repo],
|
|
59
26
|
['<home>', roots.home],
|
|
60
27
|
];
|
|
61
|
-
// Longest root first so a
|
|
28
|
+
// Longest root first so a repository inside home is not masked by home.
|
|
62
29
|
for (const [label, root] of [...labelled].sort(([, left], [, right]) => (right?.length ?? 0) - (left?.length ?? 0))) {
|
|
63
30
|
if (root)
|
|
64
31
|
redacted = redacted.split(root).join(label);
|
|
@@ -87,7 +54,7 @@ function isRecord(value) {
|
|
|
87
54
|
* `metadata` it was derived from. Submitting both is ambiguous and is refused
|
|
88
55
|
* rather than silently preferring one.
|
|
89
56
|
*
|
|
90
|
-
* Both forms are validated here, at the
|
|
57
|
+
* Both forms are validated here, at the recording boundary, rather than
|
|
91
58
|
* being trusted from the producer. An earlier revision normalized only the
|
|
92
59
|
* metadata form, which left the finished-observation form able to assert its
|
|
93
60
|
* own `match`, name a provider the record does not use, and store values the
|
|
@@ -383,184 +350,20 @@ function runtimeIdentityFor(record, reason = null) {
|
|
|
383
350
|
status: observation.status,
|
|
384
351
|
};
|
|
385
352
|
}
|
|
386
|
-
function genericPart(record) {
|
|
387
|
-
const { oat: _oat, ...generic } = record;
|
|
388
|
-
return parseGenericDispatchRecord(generic);
|
|
389
|
-
}
|
|
390
|
-
function sameGenericRecord(left, right) {
|
|
391
|
-
return JSON.stringify(left) === JSON.stringify(right);
|
|
392
|
-
}
|
|
393
|
-
function isMissingError(error) {
|
|
394
|
-
return (typeof error === 'object' &&
|
|
395
|
-
error !== null &&
|
|
396
|
-
'code' in error &&
|
|
397
|
-
error.code === 'ENOENT');
|
|
398
|
-
}
|
|
399
|
-
async function readPersistedRecord(path, reportedPath) {
|
|
400
|
-
let content;
|
|
401
|
-
try {
|
|
402
|
-
content = await readFile(path, 'utf8');
|
|
403
|
-
}
|
|
404
|
-
catch (error) {
|
|
405
|
-
if (isMissingError(error)) {
|
|
406
|
-
return null;
|
|
407
|
-
}
|
|
408
|
-
// A damaged or unreadable journal must not put an absolute project path
|
|
409
|
-
// into durable output; NFR1 treats that as a P0 disclosure.
|
|
410
|
-
throw redactedFsError(error, 'read', reportedPath);
|
|
411
|
-
}
|
|
412
|
-
return parsePersistedOatDispatchRecord(JSON.parse(content));
|
|
413
|
-
}
|
|
414
|
-
/** Highest published revision per request ID. */
|
|
415
|
-
async function readLatestRevisions(dispatchDir) {
|
|
416
|
-
let names;
|
|
417
|
-
try {
|
|
418
|
-
names = await readdir(dispatchDir);
|
|
419
|
-
}
|
|
420
|
-
catch (error) {
|
|
421
|
-
if (isMissingError(error)) {
|
|
422
|
-
return new Map();
|
|
423
|
-
}
|
|
424
|
-
throw redactedFsError(error, 'scan', 'dispatch/');
|
|
425
|
-
}
|
|
426
|
-
const latest = new Map();
|
|
427
|
-
for (const name of names.sort()) {
|
|
428
|
-
const entry = parseJournalEntry(name);
|
|
429
|
-
if (!entry)
|
|
430
|
-
continue;
|
|
431
|
-
const known = latest.get(entry.requestId);
|
|
432
|
-
if (!known || entry.revision > known.revision) {
|
|
433
|
-
latest.set(entry.requestId, entry);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return latest;
|
|
437
|
-
}
|
|
438
|
-
function fallbackTriggerRequestId(event) {
|
|
439
|
-
if (event.kind !== 'fallback-link')
|
|
440
|
-
return null;
|
|
441
|
-
const requestId = event.evidence?.triggerRequestId;
|
|
442
|
-
if (typeof requestId !== 'string' || !REQUEST_ID_PATTERN.test(requestId)) {
|
|
443
|
-
throw new Error('Fallback trigger request ID is invalid.');
|
|
444
|
-
}
|
|
445
|
-
return requestId;
|
|
446
|
-
}
|
|
447
|
-
function isAlreadyPublished(error) {
|
|
448
|
-
return (typeof error === 'object' &&
|
|
449
|
-
error !== null &&
|
|
450
|
-
'code' in error &&
|
|
451
|
-
error.code === 'EEXIST');
|
|
452
|
-
}
|
|
453
|
-
async function publishRevision(projectPath, dispatchDir, requestId, revision, record) {
|
|
454
|
-
if (revision > MAX_REVISION) {
|
|
455
|
-
throw new Error(`Dispatch journal for ${requestId} reached its ${MAX_REVISION}-revision limit.`);
|
|
456
|
-
}
|
|
457
|
-
const fileName = revisionFileName(requestId, revision);
|
|
458
|
-
// Last check before bytes reach the journal. The sanitizer runs at parse, but
|
|
459
|
-
// the journal is committed to a shared repository, so the guarantee is
|
|
460
|
-
// enforced on the exact value being written rather than trusted upstream.
|
|
461
|
-
// Guarantees identity and control fields only; prose redaction is
|
|
462
|
-
// best-effort by design. See absolute-paths.ts.
|
|
463
|
-
assertJournalIdentityHasNoAbsolutePath(identityFieldsOf(genericPart(record)));
|
|
464
|
-
assertBoundedDispatchRecordSize(record);
|
|
465
|
-
try {
|
|
466
|
-
await publishContainedJsonRevision(join(dispatchDir, fileName), record, projectPath);
|
|
467
|
-
}
|
|
468
|
-
catch (error) {
|
|
469
|
-
if (isAlreadyPublished(error)) {
|
|
470
|
-
throw new Error('The dispatch journal advanced to a newer revision while this write was prepared; the concurrent update was preserved and this stale write was refused.', { cause: error });
|
|
471
|
-
}
|
|
472
|
-
throw error;
|
|
473
|
-
}
|
|
474
|
-
return `dispatch/${fileName}`;
|
|
475
|
-
}
|
|
476
353
|
/**
|
|
477
|
-
*
|
|
478
|
-
* here
|
|
354
|
+
* Validate one dispatch record and event and return the augmented record. Parse
|
|
355
|
+
* once, here. An earlier revision parsed in the command layer and again here;
|
|
356
|
+
* because the metadata path resolves to a finished observation, the second
|
|
479
357
|
* parse saw its own output as caller-supplied and overwrote the parser source
|
|
480
358
|
* with `caller-asserted`. Parsing is not idempotent by design — provenance
|
|
481
359
|
* depends on which input form arrived — so it must happen exactly once.
|
|
482
360
|
*/
|
|
483
361
|
export async function recordProjectDispatch(input) {
|
|
484
362
|
const parsedInput = parseDispatchRecordInput(input.input);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
record,
|
|
492
|
-
runtimeIdentity: runtimeIdentityFor(record, parsedInput.observationReason ?? null),
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
const projectPath = input.projectPath;
|
|
496
|
-
const dispatchDir = join(projectPath, 'dispatch');
|
|
497
|
-
const requestId = parsedInput.record.request_id;
|
|
498
|
-
const latest = await readLatestRevisions(dispatchDir);
|
|
499
|
-
const existingEntry = latest.get(requestId) ?? null;
|
|
500
|
-
const existing = existingEntry
|
|
501
|
-
? await readPersistedRecord(join(dispatchDir, existingEntry.fileName), `dispatch/${existingEntry.fileName}`)
|
|
502
|
-
: null;
|
|
503
|
-
if (existing &&
|
|
504
|
-
!sameGenericRecord(genericPart(existing), parsedInput.record)) {
|
|
505
|
-
throw new Error('Existing generic fields are immutable and cannot be redefined.');
|
|
506
|
-
}
|
|
507
|
-
const relatedRecords = [];
|
|
508
|
-
for (const [otherId, entry] of [...latest].sort(([left], [right]) => left < right ? -1 : 1)) {
|
|
509
|
-
if (otherId === requestId)
|
|
510
|
-
continue;
|
|
511
|
-
const related = await readPersistedRecord(join(dispatchDir, entry.fileName), `dispatch/${entry.fileName}`);
|
|
512
|
-
if (related)
|
|
513
|
-
relatedRecords.push(related);
|
|
514
|
-
}
|
|
515
|
-
const triggerRequestId = fallbackTriggerRequestId(parsedInput.event);
|
|
516
|
-
const triggerEntry = triggerRequestId
|
|
517
|
-
? (latest.get(triggerRequestId) ?? null)
|
|
518
|
-
: null;
|
|
519
|
-
const trigger = triggerEntry
|
|
520
|
-
? await readPersistedRecord(join(dispatchDir, triggerEntry.fileName), `dispatch/${triggerEntry.fileName}`)
|
|
521
|
-
: null;
|
|
522
|
-
if (triggerRequestId !== null && trigger === null) {
|
|
523
|
-
throw new Error('Fallback requires the rejected trigger record.');
|
|
524
|
-
}
|
|
525
|
-
await input.raceBarriers?.afterRead?.();
|
|
526
|
-
// One shared, identity-bound transition. The lock serializes the trigger
|
|
527
|
-
// claim and the fallback publication; the exclusive revision name is the
|
|
528
|
-
// compare-and-swap, so a stale concurrent writer loses without any write
|
|
529
|
-
// being able to replace the winner's evidence.
|
|
530
|
-
return withContainedWriterLock(join(projectPath, DISPATCH_LOCK_NAME), projectPath, async () => {
|
|
531
|
-
let triggerRecord = trigger ?? undefined;
|
|
532
|
-
if (trigger && triggerEntry && triggerRequestId) {
|
|
533
|
-
const claimed = augmentDispatchRecord({
|
|
534
|
-
record: trigger,
|
|
535
|
-
event: {
|
|
536
|
-
kind: 'fallback-claim',
|
|
537
|
-
requestId: triggerRequestId,
|
|
538
|
-
source: 'provider-wrapper',
|
|
539
|
-
claim: {
|
|
540
|
-
fallbackRequestId: requestId,
|
|
541
|
-
claimedAt: new Date().toISOString(),
|
|
542
|
-
},
|
|
543
|
-
},
|
|
544
|
-
});
|
|
545
|
-
if (JSON.stringify(claimed) !== JSON.stringify(trigger)) {
|
|
546
|
-
await publishRevision(projectPath, dispatchDir, triggerRequestId, triggerEntry.revision + 1, claimed);
|
|
547
|
-
}
|
|
548
|
-
triggerRecord = claimed;
|
|
549
|
-
}
|
|
550
|
-
const record = augmentDispatchRecord({
|
|
551
|
-
record: existing ?? parsedInput.record,
|
|
552
|
-
event: parsedInput.event,
|
|
553
|
-
...(triggerRecord ? { triggerRecord } : {}),
|
|
554
|
-
relatedRecords,
|
|
555
|
-
});
|
|
556
|
-
const revision = (existingEntry?.revision ?? 0) + 1;
|
|
557
|
-
const path = await publishRevision(projectPath, dispatchDir, requestId, revision, record);
|
|
558
|
-
return {
|
|
559
|
-
status: 'persisted',
|
|
560
|
-
path,
|
|
561
|
-
created: revision === 1,
|
|
562
|
-
record,
|
|
563
|
-
runtimeIdentity: runtimeIdentityFor(record, parsedInput.observationReason ?? null),
|
|
564
|
-
};
|
|
565
|
-
});
|
|
363
|
+
const record = augmentDispatchRecord(parsedInput);
|
|
364
|
+
return {
|
|
365
|
+
status: 'validated-only',
|
|
366
|
+
record,
|
|
367
|
+
runtimeIdentity: runtimeIdentityFor(record, parsedInput.observationReason ?? null),
|
|
368
|
+
};
|
|
566
369
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAyB9C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { createProjectArchiveCommand } from './archive/index.js';
|
|
3
|
+
import { createProjectCloseoutCheckCommand } from './closeout-check/index.js';
|
|
3
4
|
import { createProjectCompleteDiscoveryCommand } from './complete-discovery/index.js';
|
|
4
5
|
import { createProjectCompleteStateCommand } from './complete-state/index.js';
|
|
5
6
|
import { createProjectDispatchCommand } from './dispatch/index.js';
|
|
@@ -24,6 +25,7 @@ export function createProjectCommand() {
|
|
|
24
25
|
return new Command('project')
|
|
25
26
|
.description('Manage OAT project workflows')
|
|
26
27
|
.addCommand(createProjectArchiveCommand())
|
|
28
|
+
.addCommand(createProjectCloseoutCheckCommand())
|
|
27
29
|
.addCommand(createProjectCompleteDiscoveryCommand())
|
|
28
30
|
.addCommand(createProjectCompleteStateCommand())
|
|
29
31
|
.addCommand(createProjectDispatchCommand())
|
|
@@ -61,6 +61,5 @@ export interface ScaffoldProjectDependencies {
|
|
|
61
61
|
setActiveProject: typeof setActiveProject;
|
|
62
62
|
}
|
|
63
63
|
export declare function applyTemplateReplacements(template: string, projectName: string, today: string, nowUtc: string, mode: WorkflowMode): string;
|
|
64
|
-
export declare function resolveTemplateSource(userOatRoot: string, repoRoot: string, templateFile: string): Promise<string>;
|
|
65
64
|
export declare function scaffoldProject(options: ScaffoldProjectOptions, overrides?: Partial<ScaffoldProjectDependencies>): Promise<ScaffoldProjectResult>;
|
|
66
65
|
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAEL,iBAAiB,EAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,4BAA4B,EAC7B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAGL,mBAAmB,EAGnB,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir,
|
|
1
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
4
|
import { ensureScopedRootGitignore } from '../../init/gitignore.js';
|
|
@@ -8,6 +8,7 @@ import { buildSyncedRecord, writeSyncedRecord, } from '../../project/sync/record
|
|
|
8
8
|
import { buildSyncTarget, commitRecordChange, createSyncedProject, pushSynced, rollbackCreatedSyncedProject, } from '../../project/sync/ref-sync.js';
|
|
9
9
|
import { resolveProjectsRoot } from '../../shared/oat-paths.js';
|
|
10
10
|
import { canonicalizePath, PROJECT_SCOPES, resolveDefaultScope, resolveScopeRoot, syncedRecordPath, } from '../../shared/project-scope.js';
|
|
11
|
+
import { resolveTemplate, } from '../../shared/template-source.js';
|
|
11
12
|
import { generateStateDashboard } from '../../state/generate.js';
|
|
12
13
|
import { setActiveProject } from '../../../config/oat-config.js';
|
|
13
14
|
import { resolveEffectiveConfig } from '../../../config/resolve.js';
|
|
@@ -206,18 +207,17 @@ async function commitScaffold(cwd, absoluteProjectPath, projectName, createdFile
|
|
|
206
207
|
return { status: 'failed', committed: false, error: message };
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
|
-
async function scaffoldModeTemplates(
|
|
210
|
+
async function scaffoldModeTemplates(home, repoRoot, absoluteProjectPath, projectName, mode, today, nowUtc) {
|
|
210
211
|
const createdFiles = [];
|
|
211
212
|
const skippedFiles = [];
|
|
212
213
|
for (const entry of TEMPLATES_BY_MODE[mode]) {
|
|
213
214
|
const { source, target } = normalizeTemplateEntry(entry);
|
|
214
|
-
const src = await resolveTemplateSource(userOatRoot, repoRoot, source);
|
|
215
215
|
const dest = join(absoluteProjectPath, target);
|
|
216
216
|
if (await fileExists(dest)) {
|
|
217
217
|
skippedFiles.push(target);
|
|
218
218
|
continue;
|
|
219
219
|
}
|
|
220
|
-
const template = await
|
|
220
|
+
const { content: template } = await resolveProjectTemplate(home, repoRoot, source);
|
|
221
221
|
let rendered = applyTemplateReplacements(template, projectName, today, nowUtc, mode);
|
|
222
222
|
if (mode === 'lite' && target === 'plan.md') {
|
|
223
223
|
rendered = rendered.replace(/^---\n/, '---\noat_template: true\n');
|
|
@@ -231,28 +231,27 @@ async function scaffoldModeTemplates(userOatRoot, repoRoot, absoluteProjectPath,
|
|
|
231
231
|
}
|
|
232
232
|
return { createdFiles, skippedFiles };
|
|
233
233
|
}
|
|
234
|
-
async function scaffoldProjectLog(
|
|
234
|
+
async function scaffoldProjectLog(home, repoRoot, absoluteProjectPath, projectName, today) {
|
|
235
235
|
const templateFile = 'project-log.md';
|
|
236
236
|
const dest = join(absoluteProjectPath, templateFile);
|
|
237
237
|
if (await fileExists(dest)) {
|
|
238
238
|
return 'skipped';
|
|
239
239
|
}
|
|
240
|
-
const
|
|
241
|
-
const template = await readFile(src, 'utf8');
|
|
240
|
+
const { content: template } = await resolveProjectTemplate(home, repoRoot, templateFile);
|
|
242
241
|
await writeFile(dest, instantiateProjectLogTemplate(template, projectName, today), 'utf8');
|
|
243
242
|
return 'created';
|
|
244
243
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Resolve a project lifecycle template in repository, user, then bundle order
|
|
246
|
+
* through the shared resolver.
|
|
247
|
+
*/
|
|
248
|
+
function resolveProjectTemplate(home, repoRoot, templateFile) {
|
|
249
|
+
return resolveTemplate({
|
|
250
|
+
name: templateFile,
|
|
251
|
+
templatesRoot: join(repoRoot, '.oat', 'templates'),
|
|
252
|
+
home,
|
|
253
|
+
assetsRoot: () => resolveAssetsRoot(),
|
|
254
|
+
});
|
|
256
255
|
}
|
|
257
256
|
async function ensureStructure(absoluteProjectPath, mode) {
|
|
258
257
|
await mkdir(absoluteProjectPath, { recursive: true });
|
|
@@ -395,12 +394,12 @@ export async function scaffoldProject(options, overrides = {}) {
|
|
|
395
394
|
syncedCreatedByInvocation = true;
|
|
396
395
|
}
|
|
397
396
|
await ensureStructure(absoluteProjectPath, mode);
|
|
398
|
-
({ createdFiles, skippedFiles } = await scaffoldModeTemplates(
|
|
397
|
+
({ createdFiles, skippedFiles } = await scaffoldModeTemplates(home, options.repoRoot, absoluteProjectPath, options.projectName, mode, today, nowUtc));
|
|
399
398
|
const effectiveProjectLog = options.projectLog ??
|
|
400
399
|
(await resolveEffectiveConfig(options.repoRoot, userOatRoot, env))
|
|
401
400
|
.resolved['workflow.projectLog']?.value === true;
|
|
402
401
|
if (effectiveProjectLog) {
|
|
403
|
-
const projectLogResult = await scaffoldProjectLog(
|
|
402
|
+
const projectLogResult = await scaffoldProjectLog(home, options.repoRoot, absoluteProjectPath, options.projectName, today);
|
|
404
403
|
if (projectLogResult === 'created') {
|
|
405
404
|
createdFiles.push('project-log.md');
|
|
406
405
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { mkdir as defaultMkdir, readFile as defaultReadFile, rename as defaultRename, writeFile as defaultWriteFile } from 'node:fs/promises';
|
|
2
2
|
import { type CommandContext, type GlobalOptions } from '../../../app/command-context.js';
|
|
3
|
-
import { resolveTemplateSource as defaultResolveTemplateSource } from '../../project/new/scaffold.js';
|
|
4
3
|
import { type GitRunner } from '../../project/sync/git.js';
|
|
5
4
|
import { type PushResult, type SyncTarget } from '../../project/sync/ref-sync.js';
|
|
5
|
+
import { resolveTemplate as defaultResolveTemplate } from '../../shared/template-source.js';
|
|
6
6
|
import { fileExists as defaultFileExists } from '../../../fs/io.js';
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
export interface LitePlanSections {
|
|
@@ -28,7 +28,7 @@ export interface ProjectPromoteDependencies {
|
|
|
28
28
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
29
29
|
resolveProjectRoot: (cwd: string) => Promise<string>;
|
|
30
30
|
resolveProjectsRoot: (repoRoot: string, env: NodeJS.ProcessEnv) => Promise<string>;
|
|
31
|
-
|
|
31
|
+
resolveTemplate: typeof defaultResolveTemplate;
|
|
32
32
|
readFile: typeof defaultReadFile;
|
|
33
33
|
writeFile: typeof defaultWriteFile;
|
|
34
34
|
mkdir: typeof defaultMkdir;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/promote/promote.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,IAAI,YAAY,EACrB,QAAQ,IAAI,eAAe,EAC3B,MAAM,IAAI,aAAa,EACvB,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/promote/promote.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,IAAI,YAAY,EACrB,QAAQ,IAAI,eAAe,EAC3B,MAAM,IAAI,aAAa,EACvB,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE7F,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAEzD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,eAAe,GAChB,UAAU,GACV,oBAAoB,GACpB,UAAU,GACV,4BAA4B,GAC5B,mBAAmB,GACnB,kBAAkB,GAClB,oBAAoB,GACpB,qBAAqB,GACrB,cAAc,GACd,oBAAoB,CAAC;AAEzB,MAAM,MAAM,eAAe,GACvB;IACE,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,GACD;IACE,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC7C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAMN,MAAM,WAAW,0BAA0B;IACzC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,eAAe,EAAE,OAAO,sBAAsB,CAAC;IAC/C,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,gBAAgB,CAAC;IACnC,KAAK,EAAE,OAAO,YAAY,CAAC;IAC3B,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,UAAU,EAAE,OAAO,iBAAiB,CAAC;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,CACV,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAC1B,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AA4ED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE,MAAM,GAC3B,gBAAgB,GAAG,IAAI,CAYzB;AAySD,wBAAgB,2BAA2B,CACzC,SAAS,GAAE,OAAO,CAAC,0BAA0B,CAAM,GAClD,OAAO,CA+BT"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdir as defaultMkdir, readFile as defaultReadFile, rename as defaultRename, writeFile as defaultWriteFile, } from 'node:fs/promises';
|
|
2
2
|
import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
3
|
import { buildCommandContext, } from '../../../app/command-context.js';
|
|
4
|
-
import { applyTemplateReplacements
|
|
4
|
+
import { applyTemplateReplacements } from '../../project/new/scaffold.js';
|
|
5
5
|
import { defaultGitRunner } from '../../project/sync/git.js';
|
|
6
6
|
import { buildSyncTarget, pushSynced as defaultPushSynced, } from '../../project/sync/ref-sync.js';
|
|
7
7
|
import { getFrontmatterBlock } from '../../shared/frontmatter.js';
|
|
@@ -9,6 +9,8 @@ import { replaceFrontmatter } from '../../shared/frontmatter-write.js';
|
|
|
9
9
|
import { resolveProjectsRoot as defaultResolveProjectsRoot } from '../../shared/oat-paths.js';
|
|
10
10
|
import { resolveProjectScope } from '../../shared/project-scope.js';
|
|
11
11
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
12
|
+
import { resolveTemplate as defaultResolveTemplate } from '../../shared/template-source.js';
|
|
13
|
+
import { resolveAssetsRoot } from '../../../fs/assets.js';
|
|
12
14
|
import { fileExists as defaultFileExists } from '../../../fs/io.js';
|
|
13
15
|
import { resolveProjectRoot } from '../../../fs/paths.js';
|
|
14
16
|
import { Command } from 'commander';
|
|
@@ -30,7 +32,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
30
32
|
buildCommandContext,
|
|
31
33
|
resolveProjectRoot,
|
|
32
34
|
resolveProjectsRoot: defaultResolveProjectsRoot,
|
|
33
|
-
|
|
35
|
+
resolveTemplate: defaultResolveTemplate,
|
|
34
36
|
readFile: defaultReadFile,
|
|
35
37
|
writeFile: defaultWriteFile,
|
|
36
38
|
mkdir: defaultMkdir,
|
|
@@ -226,11 +228,15 @@ async function promoteProject(projectPath, options, context, dependencies) {
|
|
|
226
228
|
files: [],
|
|
227
229
|
};
|
|
228
230
|
}
|
|
229
|
-
const
|
|
231
|
+
const resolveProjectTemplate = async (name) => (await dependencies.resolveTemplate({
|
|
232
|
+
name,
|
|
233
|
+
templatesRoot: join(repoRoot, '.oat', 'templates'),
|
|
234
|
+
home: context.home,
|
|
235
|
+
assetsRoot: () => resolveAssetsRoot(),
|
|
236
|
+
})).content;
|
|
230
237
|
let liteTemplateContent;
|
|
231
238
|
try {
|
|
232
|
-
|
|
233
|
-
liteTemplateContent = await dependencies.readFile(liteTemplatePath, 'utf8');
|
|
239
|
+
liteTemplateContent = await resolveProjectTemplate('plan-lite.md');
|
|
234
240
|
}
|
|
235
241
|
catch {
|
|
236
242
|
return { status: 'refused', reason: 'template-unreadable', files: [] };
|
|
@@ -251,13 +257,9 @@ async function promoteProject(projectPath, options, context, dependencies) {
|
|
|
251
257
|
let quickPlanContent;
|
|
252
258
|
let quickStateContent;
|
|
253
259
|
try {
|
|
254
|
-
const [discoveryTemplatePath, quickPlanTemplatePath] = await Promise.all([
|
|
255
|
-
dependencies.resolveTemplateSource(userOatRoot, repoRoot, 'discovery.md'),
|
|
256
|
-
dependencies.resolveTemplateSource(userOatRoot, repoRoot, 'plan.md'),
|
|
257
|
-
]);
|
|
258
260
|
const [discoveryTemplate, quickPlanTemplate] = await Promise.all([
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
resolveProjectTemplate('discovery.md'),
|
|
262
|
+
resolveProjectTemplate('plan.md'),
|
|
261
263
|
]);
|
|
262
264
|
discoveryContent = renderDiscovery(discoveryTemplate, projectName, today, nowUtc, sections);
|
|
263
265
|
quickPlanContent = applyTemplateReplacements(quickPlanTemplate, projectName, today, nowUtc, 'quick');
|
|
@@ -80,6 +80,18 @@ export interface ParsedSkillFrontmatter {
|
|
|
80
80
|
};
|
|
81
81
|
malformed: boolean;
|
|
82
82
|
unusableVersionDeclaration: boolean;
|
|
83
|
+
/** Why a `malformed` block is malformed, located within the block. */
|
|
84
|
+
problem?: FrontmatterProblem;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* One problem in a frontmatter block. `line` and `column` are 1-based and
|
|
88
|
+
* relative to the block, which starts on the line after the opening `---`;
|
|
89
|
+
* they are null when the parser reports no position.
|
|
90
|
+
*/
|
|
91
|
+
export interface FrontmatterProblem {
|
|
92
|
+
line: number | null;
|
|
93
|
+
column: number | null;
|
|
94
|
+
message: string;
|
|
83
95
|
}
|
|
84
96
|
export interface SkillVersionConflict {
|
|
85
97
|
metadata: string;
|
|
@@ -98,6 +110,15 @@ export interface ResolvedSkillVersion {
|
|
|
98
110
|
* indentation-based reader cannot tell a nested key from a top-level one.
|
|
99
111
|
*/
|
|
100
112
|
export declare function parseSkillFrontmatter(block: string): ParsedSkillFrontmatter;
|
|
113
|
+
/**
|
|
114
|
+
* Keys whose parsed YAML value has the wrong type, such as `name: 123` or
|
|
115
|
+
* `user-invocable: "true"`, each located within the block. A block that does
|
|
116
|
+
* not parse as a mapping yields nothing here; `parseSkillFrontmatter` reports
|
|
117
|
+
* it.
|
|
118
|
+
*/
|
|
119
|
+
export declare function findSkillFrontmatterTypeProblems(block: string): (FrontmatterProblem & {
|
|
120
|
+
key: string;
|
|
121
|
+
})[];
|
|
101
122
|
/**
|
|
102
123
|
* Resolve the canonical version with `metadata.version` taking precedence over
|
|
103
124
|
* the deprecated top-level `version` alias.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"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"}
|