@open-agent-toolkit/cli 0.2.65 → 0.2.67
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/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +33 -2
- package/assets/docs/cli-utilities/index.md +3 -0
- package/assets/docs/cli-utilities/project-log.md +63 -4
- package/assets/docs/cli-utilities/remote-project-management.md +191 -0
- package/assets/docs/contributing/code.md +8 -4
- package/assets/docs/contributing/skills.md +29 -17
- package/assets/docs/docs-tooling/commands.md +3 -1
- package/assets/docs/provider-sync/manifest-and-drift.md +2 -18
- package/assets/docs/reference/cli-reference.md +12 -1
- package/assets/docs/reference/file-locations.md +22 -0
- package/assets/docs/reference/oat-directory-structure.md +30 -17
- package/assets/docs/reference/troubleshooting.md +44 -0
- package/assets/docs/workflows/projects/lifecycle.md +17 -0
- package/assets/docs/workflows/projects/picking-up-projects.md +18 -0
- package/assets/docs/workflows/skills/index.md +33 -0
- package/assets/docs/workflows/skills/repo-improve.md +7 -3
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/SKILL.md +19 -37
- package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +58 -15
- package/assets/skills/create-agnostic-skill/references/skill-template.md +17 -15
- package/assets/skills/oat-agent-instructions-apply/SKILL.md +1 -1
- package/assets/skills/oat-agent-instructions-apply/references/instruction-file-templates/glob-scoped-rule.md +1 -4
- package/assets/skills/oat-doctor/SKILL.md +3 -6
- package/assets/skills/oat-pjm-remote/SKILL.md +101 -0
- package/assets/skills/oat-pjm-remote/references/external-action-protocol.md +43 -0
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
- package/assets/skills/oat-project-complete/SKILL.md +158 -30
- package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +26 -7
- package/assets/skills/oat-project-complete/scripts/validate-durable-archive-receipt.mjs +183 -0
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-retro/SKILL.md +1 -1
- package/assets/skills/oat-project-retro/references/apply-procedure.md +11 -0
- package/assets/skills/oat-project-review-provide/SKILL.md +4 -4
- package/assets/skills/oat-project-summary/SKILL.md +24 -2
- package/assets/skills/oat-repo-improve/SKILL.md +9 -2
- package/assets/skills/oat-repo-improve/references/plan-template.md +4 -6
- package/assets/skills/oat-repo-knowledge-index/SKILL.md +11 -9
- package/assets/skills/oat-wave-execute/SKILL.md +20 -6
- package/assets/skills/oat-wave-program/SKILL.md +9 -4
- package/dist/commands/backlog/new.d.ts +1 -0
- package/dist/commands/backlog/new.d.ts.map +1 -1
- package/dist/commands/backlog/new.js +3 -1
- package/dist/commands/config/index.d.ts +3 -1
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +362 -36
- package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/index.js +68 -12
- package/dist/commands/docs/init/index.d.ts +11 -0
- package/dist/commands/docs/init/index.d.ts.map +1 -1
- package/dist/commands/docs/init/index.js +19 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +10 -2
- package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.js +42 -9
- package/dist/commands/internal/validate-skill-version-bumps.d.ts.map +1 -1
- package/dist/commands/internal/validate-skill-version-bumps.js +5 -5
- package/dist/commands/pjm/doctor.d.ts +2 -0
- package/dist/commands/pjm/doctor.d.ts.map +1 -1
- package/dist/commands/pjm/doctor.js +71 -1
- package/dist/commands/pjm/index.d.ts +2 -0
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +3 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts +60 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts.map +1 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.js +151 -0
- package/dist/commands/pjm/remote/association.d.ts +27 -0
- package/dist/commands/pjm/remote/association.d.ts.map +1 -0
- package/dist/commands/pjm/remote/association.js +68 -0
- package/dist/commands/pjm/remote/authority.d.ts +210 -0
- package/dist/commands/pjm/remote/authority.d.ts.map +1 -0
- package/dist/commands/pjm/remote/authority.js +341 -0
- package/dist/commands/pjm/remote/batch.d.ts +15 -0
- package/dist/commands/pjm/remote/batch.d.ts.map +1 -0
- package/dist/commands/pjm/remote/batch.js +126 -0
- package/dist/commands/pjm/remote/closeout.d.ts +69 -0
- package/dist/commands/pjm/remote/closeout.d.ts.map +1 -0
- package/dist/commands/pjm/remote/closeout.js +208 -0
- package/dist/commands/pjm/remote/create-binding.d.ts +62 -0
- package/dist/commands/pjm/remote/create-binding.d.ts.map +1 -0
- package/dist/commands/pjm/remote/create-binding.js +126 -0
- package/dist/commands/pjm/remote/credential-safety.d.ts +7 -0
- package/dist/commands/pjm/remote/credential-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/credential-safety.js +21 -0
- package/dist/commands/pjm/remote/discussion.d.ts +49 -0
- package/dist/commands/pjm/remote/discussion.d.ts.map +1 -0
- package/dist/commands/pjm/remote/discussion.js +124 -0
- package/dist/commands/pjm/remote/doctor.d.ts +22 -0
- package/dist/commands/pjm/remote/doctor.d.ts.map +1 -0
- package/dist/commands/pjm/remote/doctor.js +380 -0
- package/dist/commands/pjm/remote/external-action.d.ts +208 -0
- package/dist/commands/pjm/remote/external-action.d.ts.map +1 -0
- package/dist/commands/pjm/remote/external-action.js +367 -0
- package/dist/commands/pjm/remote/host-execution.d.ts +28 -0
- package/dist/commands/pjm/remote/host-execution.d.ts.map +1 -0
- package/dist/commands/pjm/remote/host-execution.js +63 -0
- package/dist/commands/pjm/remote/index.d.ts +41 -0
- package/dist/commands/pjm/remote/index.d.ts.map +1 -0
- package/dist/commands/pjm/remote/index.js +280 -0
- package/dist/commands/pjm/remote/jira-adf.d.ts +35 -0
- package/dist/commands/pjm/remote/jira-adf.d.ts.map +1 -0
- package/dist/commands/pjm/remote/jira-adf.js +169 -0
- package/dist/commands/pjm/remote/lifecycle.d.ts +163 -0
- package/dist/commands/pjm/remote/lifecycle.d.ts.map +1 -0
- package/dist/commands/pjm/remote/lifecycle.js +224 -0
- package/dist/commands/pjm/remote/local-projection.d.ts +30 -0
- package/dist/commands/pjm/remote/local-projection.d.ts.map +1 -0
- package/dist/commands/pjm/remote/local-projection.js +95 -0
- package/dist/commands/pjm/remote/managed-markdown.d.ts +30 -0
- package/dist/commands/pjm/remote/managed-markdown.d.ts.map +1 -0
- package/dist/commands/pjm/remote/managed-markdown.js +128 -0
- package/dist/commands/pjm/remote/migrate.d.ts +14 -0
- package/dist/commands/pjm/remote/migrate.d.ts.map +1 -0
- package/dist/commands/pjm/remote/migrate.js +32 -0
- package/dist/commands/pjm/remote/operation-state.d.ts +15 -0
- package/dist/commands/pjm/remote/operation-state.d.ts.map +1 -0
- package/dist/commands/pjm/remote/operation-state.js +143 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.d.ts +25 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.js +99 -0
- package/dist/commands/pjm/remote/output.d.ts +60 -0
- package/dist/commands/pjm/remote/output.d.ts.map +1 -0
- package/dist/commands/pjm/remote/output.js +48 -0
- package/dist/commands/pjm/remote/preview.d.ts +88 -0
- package/dist/commands/pjm/remote/preview.d.ts.map +1 -0
- package/dist/commands/pjm/remote/preview.js +154 -0
- package/dist/commands/pjm/remote/provider-conformance.d.ts +13 -0
- package/dist/commands/pjm/remote/provider-conformance.d.ts.map +1 -0
- package/dist/commands/pjm/remote/provider-conformance.js +37 -0
- package/dist/commands/pjm/remote/provider.d.ts +57 -0
- package/dist/commands/pjm/remote/provider.d.ts.map +1 -0
- package/dist/commands/pjm/remote/provider.js +28 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts +46 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.js +126 -0
- package/dist/commands/pjm/remote/providers/github.d.ts +207 -0
- package/dist/commands/pjm/remote/providers/github.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/github.js +1456 -0
- package/dist/commands/pjm/remote/providers/jira.d.ts +245 -0
- package/dist/commands/pjm/remote/providers/jira.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/jira.js +1650 -0
- package/dist/commands/pjm/remote/providers/linear.d.ts +182 -0
- package/dist/commands/pjm/remote/providers/linear.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/linear.js +1289 -0
- package/dist/commands/pjm/remote/purpose-policy.d.ts +29 -0
- package/dist/commands/pjm/remote/purpose-policy.d.ts.map +1 -0
- package/dist/commands/pjm/remote/purpose-policy.js +118 -0
- package/dist/commands/pjm/remote/reconcile.d.ts +42 -0
- package/dist/commands/pjm/remote/reconcile.d.ts.map +1 -0
- package/dist/commands/pjm/remote/reconcile.js +101 -0
- package/dist/commands/pjm/remote/resolution.d.ts +122 -0
- package/dist/commands/pjm/remote/resolution.d.ts.map +1 -0
- package/dist/commands/pjm/remote/resolution.js +243 -0
- package/dist/commands/pjm/remote/schema.d.ts +9309 -0
- package/dist/commands/pjm/remote/schema.d.ts.map +1 -0
- package/dist/commands/pjm/remote/schema.js +1503 -0
- package/dist/commands/pjm/remote/service.d.ts +20 -0
- package/dist/commands/pjm/remote/service.d.ts.map +1 -0
- package/dist/commands/pjm/remote/service.js +5121 -0
- package/dist/commands/pjm/remote/shared-storage.d.ts +36 -0
- package/dist/commands/pjm/remote/shared-storage.d.ts.map +1 -0
- package/dist/commands/pjm/remote/shared-storage.js +110 -0
- package/dist/commands/pjm/remote/snapshot.d.ts +32 -0
- package/dist/commands/pjm/remote/snapshot.d.ts.map +1 -0
- package/dist/commands/pjm/remote/snapshot.js +140 -0
- package/dist/commands/pjm/remote/storage-locator.d.ts +29 -0
- package/dist/commands/pjm/remote/storage-locator.d.ts.map +1 -0
- package/dist/commands/pjm/remote/storage-locator.js +62 -0
- package/dist/commands/pjm/remote/store.d.ts +85 -0
- package/dist/commands/pjm/remote/store.d.ts.map +1 -0
- package/dist/commands/pjm/remote/store.js +553 -0
- package/dist/commands/pjm/remote/verification.d.ts +40 -0
- package/dist/commands/pjm/remote/verification.d.ts.map +1 -0
- package/dist/commands/pjm/remote/verification.js +100 -0
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +32 -18
- package/dist/commands/project/log/append.d.ts +48 -0
- package/dist/commands/project/log/append.d.ts.map +1 -1
- package/dist/commands/project/log/append.js +207 -30
- package/dist/commands/project/log/check.d.ts +87 -1
- package/dist/commands/project/log/check.d.ts.map +1 -1
- package/dist/commands/project/log/check.js +139 -5
- package/dist/commands/project/log/grammar.d.ts +165 -0
- package/dist/commands/project/log/grammar.d.ts.map +1 -1
- package/dist/commands/project/log/grammar.js +219 -1
- package/dist/commands/project/log/rollup.d.ts +16 -1
- package/dist/commands/project/log/rollup.d.ts.map +1 -1
- package/dist/commands/project/log/rollup.js +22 -2
- package/dist/commands/project/log/synthesize.d.ts +16 -0
- package/dist/commands/project/log/synthesize.d.ts.map +1 -1
- package/dist/commands/project/log/synthesize.js +85 -9
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +24 -2
- package/dist/commands/sync/apply.d.ts.map +1 -1
- package/dist/commands/sync/apply.js +6 -4
- package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-manifest.js +1 -0
- package/dist/config/dispatch-matrix.d.ts.map +1 -1
- package/dist/config/dispatch-matrix.js +13 -5
- package/dist/config/oat-config.d.ts +41 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +247 -9
- package/dist/config/own-keys.d.ts +22 -0
- package/dist/config/own-keys.d.ts.map +1 -0
- package/dist/config/own-keys.js +32 -0
- package/dist/config/resolve.d.ts +11 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +35 -11
- package/dist/config/sync-config.d.ts.map +1 -1
- package/dist/config/sync-config.js +16 -0
- package/dist/drift/detector.d.ts.map +1 -1
- package/dist/drift/detector.js +52 -1
- package/dist/drift/skill-view-diagnostic.d.ts.map +1 -1
- package/dist/drift/skill-view-diagnostic.js +2 -23
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +22 -72
- package/dist/engine/managed-copy-hash.d.ts +69 -0
- package/dist/engine/managed-copy-hash.d.ts.map +1 -0
- package/dist/engine/managed-copy-hash.js +175 -0
- package/dist/fs/assets.d.ts +11 -0
- package/dist/fs/assets.d.ts.map +1 -1
- package/dist/fs/assets.js +1 -1
- package/dist/manifest/hash.d.ts +110 -0
- package/dist/manifest/hash.d.ts.map +1 -1
- package/dist/manifest/hash.js +111 -13
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +6 -1
- package/dist/providers/identity/dispatch-report.d.ts.map +1 -1
- package/dist/providers/identity/dispatch-report.js +4 -1
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +21 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +305 -40
- package/package.json +2 -2
|
@@ -5,8 +5,39 @@ import { type ProjectLogSection, type ProjectLogScope, type ProjectLogType } fro
|
|
|
5
5
|
export declare const PROJECT_LOG_FILENAME = "project-log.md";
|
|
6
6
|
export declare const SYNTHESIS_PENDING_HEADING = "## End-of-run synthesis (pending \u2014 do not skip at project completion)";
|
|
7
7
|
export declare const SYNTHESIS_COMPLETE_HEADING = "## End-of-run synthesis";
|
|
8
|
+
/**
|
|
9
|
+
* The completion seal a project log already carries.
|
|
10
|
+
*
|
|
11
|
+
* `count` is reported rather than collapsed so a log double-sealed before the
|
|
12
|
+
* seal append became idempotent stays legible instead of looking like a normal
|
|
13
|
+
* single-sealed log; `heading` is always the **first** seal, which is the one
|
|
14
|
+
* that actually closed the log.
|
|
15
|
+
*/
|
|
16
|
+
export interface ProjectLogSeal {
|
|
17
|
+
heading: string;
|
|
18
|
+
date: string;
|
|
19
|
+
keyed: boolean;
|
|
20
|
+
count: number;
|
|
21
|
+
}
|
|
8
22
|
export interface ProjectLogCheckResult {
|
|
9
|
-
|
|
23
|
+
/**
|
|
24
|
+
* A *sealed* log deliberately keeps its ordinary status and carries `sealed`
|
|
25
|
+
* alongside it, because it is a healthy log that must keep routing normally —
|
|
26
|
+
* a distinct value there would break every `status: "ok"` route in
|
|
27
|
+
* `oat-project-complete/SKILL.md` and `oat-project-summary/SKILL.md`.
|
|
28
|
+
*
|
|
29
|
+
* `ambiguous` is the opposite case and is the one value that may join them.
|
|
30
|
+
* The log's markers have two readings, so no verdict below can be computed
|
|
31
|
+
* honestly: every other field is zeroed and must be treated as unknown, not as
|
|
32
|
+
* a finding. Breaking the routing is the point — both mutators already refuse
|
|
33
|
+
* this file, and `check` answering `ok` while they refuse is what let the
|
|
34
|
+
* completion gate trust a reader that disagreed with every writer.
|
|
35
|
+
*/
|
|
36
|
+
status: 'ok' | 'absent' | 'synthesis_pending' | 'ambiguous';
|
|
37
|
+
/** Why the log has two readings, or null when it has one. */
|
|
38
|
+
ambiguity: string | null;
|
|
39
|
+
sealed: boolean;
|
|
40
|
+
seal: ProjectLogSeal | null;
|
|
10
41
|
logPath: string | null;
|
|
11
42
|
entryCounts: {
|
|
12
43
|
structural: number;
|
|
@@ -60,7 +91,62 @@ export interface ProjectLogCheckCommandDependencies extends CheckProjectLogDepen
|
|
|
60
91
|
resolveProjectRoot: (cwd: string) => Promise<string>;
|
|
61
92
|
}
|
|
62
93
|
export declare function findCanonicalProjectLogSynthesisSection(content: string): ProjectLogSynthesisSection;
|
|
94
|
+
/**
|
|
95
|
+
* Parses the entries region into typed entries.
|
|
96
|
+
*
|
|
97
|
+
* The split is `/\r?\n/`, not `'\n'`. With a bare LF split every line of a
|
|
98
|
+
* CRLF log keeps a trailing `\r`, which no heading pattern can match — their
|
|
99
|
+
* `$` sits after a `[^·\r\n]+` run — so a CRLF log parsed to zero entries and
|
|
100
|
+
* an existing completion seal was invisible to `check` and to the append guard.
|
|
101
|
+
* A *lone* CR is still not a boundary, which is what keeps a body from forging
|
|
102
|
+
* a heading; only the CRLF pair is folded in.
|
|
103
|
+
*/
|
|
63
104
|
export declare function parseProjectLogEntries(content: string): ParsedProjectLog;
|
|
105
|
+
/**
|
|
106
|
+
* Summarizes the completion seal carried by already-parsed entries.
|
|
107
|
+
*
|
|
108
|
+
* Seal identity is `isProjectLogSealEntry` and nothing else, so `check` and
|
|
109
|
+
* `append` cannot drift apart on what "sealed" means.
|
|
110
|
+
*/
|
|
111
|
+
export declare function summarizeProjectLogSeal(entries: readonly ParsedProjectLogEntry[]): ProjectLogSeal | null;
|
|
112
|
+
/**
|
|
113
|
+
* Finds the completion seal in raw project-log content.
|
|
114
|
+
*
|
|
115
|
+
* `append` uses this so its refusal and `check`'s report are the same reading
|
|
116
|
+
* of the same file.
|
|
117
|
+
*/
|
|
118
|
+
/**
|
|
119
|
+
* The reason this log has two readings, or undefined when it has one.
|
|
120
|
+
*
|
|
121
|
+
* The single question `check`, `rollup`, both append paths and `synthesize` all
|
|
122
|
+
* ask before trusting a parse. It is one function rather than one call each,
|
|
123
|
+
* because a surface that asked a slightly different question is exactly how
|
|
124
|
+
* `rollup` came to rewrite `summary.md` from a log the other three refused,
|
|
125
|
+
* reporting output byte-identical to an empty log.
|
|
126
|
+
*
|
|
127
|
+
* Two shapes qualify. A heading that a `^…$/m` reader starts a line at and the
|
|
128
|
+
* line-feed-only parser does not; and a completion seal that is physically in
|
|
129
|
+
* the file but outside the region the parser reads, where "is this sealed?" has
|
|
130
|
+
* one answer to a human and another to the parser.
|
|
131
|
+
*/
|
|
132
|
+
export declare function findProjectLogAmbiguity(content: string, logPath: string): string | undefined;
|
|
133
|
+
/**
|
|
134
|
+
* Explains a refusal caused by a seal the entries parser cannot reach, naming
|
|
135
|
+
* the actual obstruction.
|
|
136
|
+
*
|
|
137
|
+
* The first version of this message assumed the only way to hide a seal was to
|
|
138
|
+
* place it outside `## Entries`, and offered that remedy for a CRLF log whose
|
|
139
|
+
* seal sat exactly where it belonged — a remedy that did not apply and could
|
|
140
|
+
* not be followed, on the one path a completion run cannot get past.
|
|
141
|
+
*
|
|
142
|
+
* Shared by both mutators so one file cannot produce two different accounts of
|
|
143
|
+
* why it was refused.
|
|
144
|
+
*/
|
|
145
|
+
export declare function unreachableProjectLogSealError(logPath: string, content: string, seal: {
|
|
146
|
+
line: string;
|
|
147
|
+
index: number;
|
|
148
|
+
}): Error;
|
|
149
|
+
export declare function findProjectLogSeal(content: string): ProjectLogSeal | null;
|
|
64
150
|
export declare function checkProjectLog(input: CheckProjectLogInput, overrides?: Partial<CheckProjectLogDependencies>): Promise<ProjectLogCheckResult>;
|
|
65
151
|
export declare function createProjectLogCheckCommand(overrides?: Partial<ProjectLogCheckCommandDependencies>): Command;
|
|
66
152
|
//# sourceMappingURL=check.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/check.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { resolveActiveProject, } from '../../../config/oat-config.js';
|
|
|
6
6
|
import { dirExists, fileExists } from '../../../fs/io.js';
|
|
7
7
|
import { resolveProjectRoot } from '../../../fs/paths.js';
|
|
8
8
|
import { Command } from 'commander';
|
|
9
|
-
import { findProjectLogSections, isProjectLogEntryMarker, JUDGMENT_HEADING_RE, PROJECT_LOG_TYPES, STRUCTURAL_HEADING_RE, } from './grammar.js';
|
|
9
|
+
import { carriesProjectLogSealKey, containsAmbiguousProjectLogMarker, findProjectLogSealHeadingLine, findProjectLogSections, isProjectLogEntryMarker, isProjectLogSealEntry, JUDGMENT_HEADING_RE, PROJECT_LOG_TYPES, STRUCTURAL_HEADING_RE, } from './grammar.js';
|
|
10
10
|
export const PROJECT_LOG_FILENAME = 'project-log.md';
|
|
11
11
|
export const SYNTHESIS_PENDING_HEADING = '## End-of-run synthesis (pending — do not skip at project completion)';
|
|
12
12
|
export const SYNTHESIS_COMPLETE_HEADING = '## End-of-run synthesis';
|
|
@@ -32,8 +32,10 @@ function emptyCounts() {
|
|
|
32
32
|
scopeCounts: { project: 0, general: 0 },
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
+
/** The heading that opens the region entries are parsed from. */
|
|
36
|
+
const ENTRIES_HEADING = '## Entries';
|
|
35
37
|
function entriesSection(content) {
|
|
36
|
-
const section = findProjectLogSections(content).find(({ heading }) => heading ===
|
|
38
|
+
const section = findProjectLogSections(content).find(({ heading }) => heading === ENTRIES_HEADING);
|
|
37
39
|
if (!section) {
|
|
38
40
|
return '';
|
|
39
41
|
}
|
|
@@ -54,8 +56,18 @@ export function findCanonicalProjectLogSynthesisSection(content) {
|
|
|
54
56
|
section,
|
|
55
57
|
};
|
|
56
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Parses the entries region into typed entries.
|
|
61
|
+
*
|
|
62
|
+
* The split is `/\r?\n/`, not `'\n'`. With a bare LF split every line of a
|
|
63
|
+
* CRLF log keeps a trailing `\r`, which no heading pattern can match — their
|
|
64
|
+
* `$` sits after a `[^·\r\n]+` run — so a CRLF log parsed to zero entries and
|
|
65
|
+
* an existing completion seal was invisible to `check` and to the append guard.
|
|
66
|
+
* A *lone* CR is still not a boundary, which is what keeps a body from forging
|
|
67
|
+
* a heading; only the CRLF pair is folded in.
|
|
68
|
+
*/
|
|
57
69
|
export function parseProjectLogEntries(content) {
|
|
58
|
-
const lines = entriesSection(content).split(
|
|
70
|
+
const lines = entriesSection(content).split(/\r?\n/);
|
|
59
71
|
const entries = [];
|
|
60
72
|
const grammarViolations = [];
|
|
61
73
|
for (let index = 0; index < lines.length; index += 1) {
|
|
@@ -101,6 +113,90 @@ export function parseProjectLogEntries(content) {
|
|
|
101
113
|
}
|
|
102
114
|
return { entries, grammarViolations };
|
|
103
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Summarizes the completion seal carried by already-parsed entries.
|
|
118
|
+
*
|
|
119
|
+
* Seal identity is `isProjectLogSealEntry` and nothing else, so `check` and
|
|
120
|
+
* `append` cannot drift apart on what "sealed" means.
|
|
121
|
+
*/
|
|
122
|
+
export function summarizeProjectLogSeal(entries) {
|
|
123
|
+
const seals = entries.filter((entry) => entry.class === 'structural' && isProjectLogSealEntry(entry));
|
|
124
|
+
const first = seals[0];
|
|
125
|
+
if (first === undefined) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
heading: first.heading,
|
|
130
|
+
date: first.date,
|
|
131
|
+
keyed: carriesProjectLogSealKey(first.body),
|
|
132
|
+
count: seals.length,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Finds the completion seal in raw project-log content.
|
|
137
|
+
*
|
|
138
|
+
* `append` uses this so its refusal and `check`'s report are the same reading
|
|
139
|
+
* of the same file.
|
|
140
|
+
*/
|
|
141
|
+
/**
|
|
142
|
+
* The reason this log has two readings, or undefined when it has one.
|
|
143
|
+
*
|
|
144
|
+
* The single question `check`, `rollup`, both append paths and `synthesize` all
|
|
145
|
+
* ask before trusting a parse. It is one function rather than one call each,
|
|
146
|
+
* because a surface that asked a slightly different question is exactly how
|
|
147
|
+
* `rollup` came to rewrite `summary.md` from a log the other three refused,
|
|
148
|
+
* reporting output byte-identical to an empty log.
|
|
149
|
+
*
|
|
150
|
+
* Two shapes qualify. A heading that a `^…$/m` reader starts a line at and the
|
|
151
|
+
* line-feed-only parser does not; and a completion seal that is physically in
|
|
152
|
+
* the file but outside the region the parser reads, where "is this sealed?" has
|
|
153
|
+
* one answer to a human and another to the parser.
|
|
154
|
+
*/
|
|
155
|
+
export function findProjectLogAmbiguity(content, logPath) {
|
|
156
|
+
if (containsAmbiguousProjectLogMarker(content)) {
|
|
157
|
+
return `Project log ${logPath} has a '## ' heading, or a dated '### ' entry heading, starting a line after a carriage return, U+2028, or U+2029 rather than a line feed, so its structure has two readings and no seal or count can be reported honestly. Replace those line terminators with line feeds.`;
|
|
158
|
+
}
|
|
159
|
+
if (findProjectLogSeal(content) === null) {
|
|
160
|
+
const unreachableSeal = findProjectLogSealHeadingLine(content);
|
|
161
|
+
if (unreachableSeal !== undefined) {
|
|
162
|
+
// Delegated so the precise diagnosis — which of the two obstructions this
|
|
163
|
+
// is — survives being reached through the shared predicate. Collapsing
|
|
164
|
+
// both causes into one sentence here would undo the round that made the
|
|
165
|
+
// remedy actionable.
|
|
166
|
+
return unreachableProjectLogSealError(logPath, content, unreachableSeal)
|
|
167
|
+
.message;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Explains a refusal caused by a seal the entries parser cannot reach, naming
|
|
174
|
+
* the actual obstruction.
|
|
175
|
+
*
|
|
176
|
+
* The first version of this message assumed the only way to hide a seal was to
|
|
177
|
+
* place it outside `## Entries`, and offered that remedy for a CRLF log whose
|
|
178
|
+
* seal sat exactly where it belonged — a remedy that did not apply and could
|
|
179
|
+
* not be followed, on the one path a completion run cannot get past.
|
|
180
|
+
*
|
|
181
|
+
* Shared by both mutators so one file cannot produce two different accounts of
|
|
182
|
+
* why it was refused.
|
|
183
|
+
*/
|
|
184
|
+
export function unreachableProjectLogSealError(logPath, content, seal) {
|
|
185
|
+
// Compared by offset, not by substring membership: prose inside `## Entries`
|
|
186
|
+
// can quote a seal heading verbatim, and a membership test would then report a
|
|
187
|
+
// seal that really sits under a later section as correctly placed, sending the
|
|
188
|
+
// operator to rewrite line terminators that were never the obstruction.
|
|
189
|
+
const entries = findProjectLogSections(content).find(({ heading }) => heading === ENTRIES_HEADING);
|
|
190
|
+
const outsideEntries = entries === undefined ||
|
|
191
|
+
seal.index < entries.start ||
|
|
192
|
+
seal.index >= entries.end;
|
|
193
|
+
return new Error(`Project log ${logPath} already carries the completion-seal heading '${seal.line.trim()}', but the entries parser cannot reach it, so whether the log is sealed has two answers and nothing may be read from it or written to it with confidence. ${outsideEntries
|
|
194
|
+
? `The seal sits outside the '${ENTRIES_HEADING}' section; move it under that heading, then retry.`
|
|
195
|
+
: 'The seal is under the correct heading, so the obstruction is its line terminators; rewrite the log with line feeds, then retry.'}`);
|
|
196
|
+
}
|
|
197
|
+
export function findProjectLogSeal(content) {
|
|
198
|
+
return summarizeProjectLogSeal(parseProjectLogEntries(content).entries);
|
|
199
|
+
}
|
|
104
200
|
async function resolveTargetProject(input, dependencies) {
|
|
105
201
|
if (input.project) {
|
|
106
202
|
const projectPath = isAbsolute(input.project)
|
|
@@ -125,6 +221,9 @@ export async function checkProjectLog(input, overrides = {}) {
|
|
|
125
221
|
if (!(await fileExists(logPath))) {
|
|
126
222
|
return {
|
|
127
223
|
status: 'absent',
|
|
224
|
+
ambiguity: null,
|
|
225
|
+
sealed: false,
|
|
226
|
+
seal: null,
|
|
128
227
|
logPath: null,
|
|
129
228
|
...emptyCounts(),
|
|
130
229
|
lastEntryDate: null,
|
|
@@ -133,6 +232,24 @@ export async function checkProjectLog(input, overrides = {}) {
|
|
|
133
232
|
};
|
|
134
233
|
}
|
|
135
234
|
const content = await readFile(logPath, 'utf8');
|
|
235
|
+
// Fail closed, exactly as every other surface does on this same file. `check`
|
|
236
|
+
// used to be the one reader that always produced a confident verdict: on a
|
|
237
|
+
// `preamble<U+2028>## Entries` log it answered `sealed` and count fields the
|
|
238
|
+
// writers refused to act on, and the completion gate keys on those fields.
|
|
239
|
+
const ambiguity = findProjectLogAmbiguity(content, logPath);
|
|
240
|
+
if (ambiguity !== undefined) {
|
|
241
|
+
return {
|
|
242
|
+
status: 'ambiguous',
|
|
243
|
+
ambiguity,
|
|
244
|
+
sealed: false,
|
|
245
|
+
seal: null,
|
|
246
|
+
logPath,
|
|
247
|
+
...emptyCounts(),
|
|
248
|
+
lastEntryDate: null,
|
|
249
|
+
synthesisPending: false,
|
|
250
|
+
grammarViolations: [],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
136
253
|
const parsed = parseProjectLogEntries(content);
|
|
137
254
|
const counts = emptyCounts();
|
|
138
255
|
for (const entry of parsed.entries) {
|
|
@@ -145,8 +262,12 @@ export async function checkProjectLog(input, overrides = {}) {
|
|
|
145
262
|
}
|
|
146
263
|
}
|
|
147
264
|
const synthesisPending = findProjectLogSections(content).some(({ heading }) => heading === SYNTHESIS_PENDING_HEADING);
|
|
265
|
+
const seal = summarizeProjectLogSeal(parsed.entries);
|
|
148
266
|
return {
|
|
149
267
|
status: synthesisPending ? 'synthesis_pending' : 'ok',
|
|
268
|
+
ambiguity: null,
|
|
269
|
+
sealed: seal !== null,
|
|
270
|
+
seal,
|
|
150
271
|
logPath,
|
|
151
272
|
...counts,
|
|
152
273
|
lastEntryDate: parsed.entries.at(-1)?.date ?? null,
|
|
@@ -161,14 +282,27 @@ async function runCheckCommand(options, context, dependencies) {
|
|
|
161
282
|
if (context.json) {
|
|
162
283
|
context.logger.json(result);
|
|
163
284
|
}
|
|
285
|
+
else if (result.status === 'ambiguous') {
|
|
286
|
+
context.logger.error(result.ambiguity ?? 'Project log has two readings.');
|
|
287
|
+
}
|
|
164
288
|
else {
|
|
165
289
|
context.logger.info(result.status === 'absent'
|
|
166
290
|
? 'Project log: absent'
|
|
167
291
|
: `Project log: ${result.status}; entries: ${result.entryCounts.structural +
|
|
168
|
-
PROJECT_LOG_TYPES.reduce((total, type) => total + result.entryCounts.judgment[type], 0)}
|
|
292
|
+
PROJECT_LOG_TYPES.reduce((total, type) => total + result.entryCounts.judgment[type], 0)}${result.seal
|
|
293
|
+
? `; sealed${result.seal.count > 1
|
|
294
|
+
? ` (${result.seal.count} seal entries)`
|
|
295
|
+
: ''}`
|
|
296
|
+
: ''}`);
|
|
169
297
|
}
|
|
298
|
+
// An ambiguous log exits non-zero whether or not synthesis was required: a
|
|
299
|
+
// caller that only checks the exit status must not read this as a clean log,
|
|
300
|
+
// and both mutators refuse the same file.
|
|
170
301
|
process.exitCode =
|
|
171
|
-
|
|
302
|
+
result.status === 'ambiguous' ||
|
|
303
|
+
(options.requireSynthesis === true && result.synthesisPending)
|
|
304
|
+
? 1
|
|
305
|
+
: 0;
|
|
172
306
|
}
|
|
173
307
|
catch (error) {
|
|
174
308
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -13,7 +13,103 @@ export interface ProjectLogSection {
|
|
|
13
13
|
}
|
|
14
14
|
export declare function isProjectLogSectionMarker(line: string): boolean;
|
|
15
15
|
export declare function isProjectLogEntryMarker(line: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Every character JavaScript treats as a LineTerminator, and therefore every
|
|
18
|
+
* character a multiline `^` anchors after: LF, CR, U+2028 LINE SEPARATOR, and
|
|
19
|
+
* U+2029 PARAGRAPH SEPARATOR. VT, FF, and U+0085 NEL are deliberately absent —
|
|
20
|
+
* ECMAScript does not count them, so `^` does not match after them either.
|
|
21
|
+
*
|
|
22
|
+
* The set is exported rather than inlined because the append validator and this
|
|
23
|
+
* parser must enumerate exactly the same characters. A validator that split on
|
|
24
|
+
* fewer terminators than the parser anchored after is precisely how a body
|
|
25
|
+
* could smuggle a `## ` past validation and have it become a real section
|
|
26
|
+
* boundary, silently truncating the parsed entries region and voiding the
|
|
27
|
+
* completion seal.
|
|
28
|
+
*/
|
|
29
|
+
export declare const PROJECT_LOG_LINE_TERMINATOR_RE: RegExp;
|
|
30
|
+
/**
|
|
31
|
+
* A *lone* line terminator: a carriage return not followed by a line feed, or a
|
|
32
|
+
* U+2028 / U+2029 separator.
|
|
33
|
+
*
|
|
34
|
+
* CRLF is deliberately excluded, and that carve-out is the whole point. Every
|
|
35
|
+
* reader in this module treats `\r\n` as exactly one boundary — `splitProjectLogLines`,
|
|
36
|
+
* the `/\r?\n/` scans, and `parseProjectLogEntries` — so a CRLF body has one
|
|
37
|
+
* reading and is accepted, as it was before this guard existed. A *lone* CR has
|
|
38
|
+
* two readings (a boundary to a multiline `^`, body text to everything here),
|
|
39
|
+
* and so do U+2028 and U+2029, so those stay refused.
|
|
40
|
+
*
|
|
41
|
+
* Written as one pattern rather than a strip-then-test so the rule is legible at
|
|
42
|
+
* the point of use: `\r(?!\n)` is "a carriage return that is not part of CRLF".
|
|
43
|
+
*/
|
|
44
|
+
export declare const PROJECT_LOG_LONE_TERMINATOR_RE: RegExp;
|
|
45
|
+
/**
|
|
46
|
+
* Canonicalizes accepted line endings to LF.
|
|
47
|
+
*
|
|
48
|
+
* The command parses leniently and writes strictly: CRLF is accepted from a
|
|
49
|
+
* caller — a `--body -` fed from a file, tool output, or a pasted buffer — and
|
|
50
|
+
* stored as LF, so a log this command writes never contains a terminator other
|
|
51
|
+
* than LF. That makes the file's single reading a property of its bytes rather
|
|
52
|
+
* than of every reader agreeing about them, which is the weaker guarantee this
|
|
53
|
+
* module kept failing to hold.
|
|
54
|
+
*
|
|
55
|
+
* It is not needed to satisfy `rollup`'s `^…$/m` ledger scan: a multiline `$`
|
|
56
|
+
* matches before a CR as readily as before an LF, so that scan reads a CRLF log
|
|
57
|
+
* correctly and always did. Storing LF is a narrowing of what future readers
|
|
58
|
+
* must cope with, not a repair of a present disagreement.
|
|
59
|
+
*/
|
|
60
|
+
export declare function normalizeProjectLogLineEndings(value: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Splits on every LineTerminator, treating CRLF as one boundary.
|
|
63
|
+
*
|
|
64
|
+
* Validators use this rather than a `/\r?\n/` split so that a lone CR, a
|
|
65
|
+
* U+2028, or a U+2029 starts a new line for validation just as it would for a
|
|
66
|
+
* regular expression's multiline `^`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function splitProjectLogLines(content: string): string[];
|
|
69
|
+
/**
|
|
70
|
+
* The log's `## ` section boundaries, where a boundary is a `## ` that begins
|
|
71
|
+
* the content or directly follows a line feed.
|
|
72
|
+
*
|
|
73
|
+
* LF is the only boundary on purpose. The previous `/^## [^\r\n]+/gm` anchored
|
|
74
|
+
* after all four LineTerminators while the append validator only split on
|
|
75
|
+
* `/\r?\n/`, so a judgment body reading `carrier<CR>## Injected` passed
|
|
76
|
+
* validation and then became a real section boundary — truncating `## Entries`
|
|
77
|
+
* so `check` reported an already-written seal as `sealed: false` and appends
|
|
78
|
+
* kept succeeding onto a sealed log. Anchoring on LF alone keeps this parser
|
|
79
|
+
* and `parseProjectLogEntries`, which splits its section on `/\r?\n/`, reading
|
|
80
|
+
* the same file the same way, and it holds for a log written by hand as well as one
|
|
81
|
+
* the command wrote.
|
|
82
|
+
*/
|
|
16
83
|
export declare function findProjectLogSections(content: string): ProjectLogSection[];
|
|
84
|
+
/**
|
|
85
|
+
* Whether the log contains a heading that a `^…$/m` reader starts a line at but
|
|
86
|
+
* an LF-only reader does not — that is, whether the file has two readings.
|
|
87
|
+
*
|
|
88
|
+
* The two competing readers are enumerated rather than approximated: the
|
|
89
|
+
* pre-fix section scan `/^## [^\r\n]+/gm`, and `rollup.ts`'s ledger scan, which
|
|
90
|
+
* recognizes only the complete dated judgment grammar. A `### ` line that
|
|
91
|
+
* neither recognizes — `carrier<CR>### Notes` — is body text to every reader and
|
|
92
|
+
* is deliberately *not* flagged; refusing it would strand logs a previous
|
|
93
|
+
* release could legitimately have written.
|
|
94
|
+
*
|
|
95
|
+
* Mutators consult this and refuse rather than guess, because a file with two
|
|
96
|
+
* readings cannot answer "is this sealed?". Tightening the section parser to LF
|
|
97
|
+
* alone would otherwise silently *widen* such logs: a hand-written
|
|
98
|
+
* `preamble<U+2028>## Entries` used to parse, so its seal was found and a
|
|
99
|
+
* replayed seal was deduplicated, and under an LF-only reading the same file has
|
|
100
|
+
* no entries region, reports unsealed, and accepts a second seal. Refusing is
|
|
101
|
+
* the only resolution that is not weaker than the reading it replaces.
|
|
102
|
+
*
|
|
103
|
+
* CRLF is deliberately not caught, and the entries parser now earns that
|
|
104
|
+
* exemption rather than merely asserting it. The character immediately before a
|
|
105
|
+
* marker on a `\r\n`-terminated line is the LF, so a `## ` section boundary was
|
|
106
|
+
* always unambiguous; `### ` entries and the structural heading pattern were not,
|
|
107
|
+
* because their `$` cannot match before a trailing `\r`, so a CRLF log parsed to
|
|
108
|
+
* zero entries and an existing seal was invisible. `parseProjectLogEntries` now
|
|
109
|
+
* splits on `/\r?\n/`, which makes all three agree and makes "CRLF has exactly
|
|
110
|
+
* one reading" a fact about this module rather than a hope.
|
|
111
|
+
*/
|
|
112
|
+
export declare function containsAmbiguousProjectLogMarker(content: string): boolean;
|
|
17
113
|
export declare function composeJudgmentHeading(input: {
|
|
18
114
|
date: string;
|
|
19
115
|
scope: ProjectLogScope;
|
|
@@ -25,4 +121,73 @@ export declare function composeStructuralHeading(input: {
|
|
|
25
121
|
producer: string;
|
|
26
122
|
ref: string;
|
|
27
123
|
}): string;
|
|
124
|
+
/**
|
|
125
|
+
* The producer and ref that together identify the completion seal — the last
|
|
126
|
+
* entry a project log may ever receive.
|
|
127
|
+
*
|
|
128
|
+
* Both fields are required. A `seal` ref from another producer is an ordinary
|
|
129
|
+
* structural entry, and an `oat-project-complete` entry with another ref is an
|
|
130
|
+
* ordinary lifecycle entry; treating either as a seal would let a foreign
|
|
131
|
+
* append freeze a log that was never completed.
|
|
132
|
+
*/
|
|
133
|
+
export declare const PROJECT_LOG_SEAL_PRODUCER = "oat-project-complete";
|
|
134
|
+
export declare const PROJECT_LOG_SEAL_REF = "seal";
|
|
135
|
+
/**
|
|
136
|
+
* The prefix of the seal's idempotency token (`oat-seal:<project>`).
|
|
137
|
+
*
|
|
138
|
+
* The token is what makes a replayed seal recognize its own entry, so it is
|
|
139
|
+
* prefixed rather than bare: a project name alone could occur in ordinary prose
|
|
140
|
+
* and match an unrelated body.
|
|
141
|
+
*/
|
|
142
|
+
export declare const PROJECT_LOG_SEAL_KEY_PREFIX = "oat-seal:";
|
|
143
|
+
/**
|
|
144
|
+
* The single definition of "this entry is the completion seal", shared by the
|
|
145
|
+
* `check` probe and the `append` guard.
|
|
146
|
+
*
|
|
147
|
+
* Both callers route on this one predicate on purpose: two definitions of
|
|
148
|
+
* sealed is the regression that lets a log report itself unsealed to one
|
|
149
|
+
* command and sealed to the other.
|
|
150
|
+
*/
|
|
151
|
+
export declare function isProjectLogSealEntry(entry: {
|
|
152
|
+
producer: string;
|
|
153
|
+
ref: string;
|
|
154
|
+
}): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Whether a composed or parsed entry *heading* is the completion seal's.
|
|
157
|
+
*
|
|
158
|
+
* The heading-level counterpart of `isProjectLogSealEntry`, and it delegates to
|
|
159
|
+
* it rather than restating the rule. One predicate serves both directions —
|
|
160
|
+
* "is this request the seal?" and "does this already-appended heading name a
|
|
161
|
+
* seal?" — so the two can never drift into disagreeing about what a seal
|
|
162
|
+
* heading is. It reads the producer and ref back out of the heading text rather
|
|
163
|
+
* than from a caller's flags, which is the same normalization
|
|
164
|
+
* `parseProjectLogEntries` applies.
|
|
165
|
+
*/
|
|
166
|
+
export declare function isProjectLogSealHeading(heading: string): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* The raw line of `content` that is a completion-seal heading, or undefined.
|
|
169
|
+
*
|
|
170
|
+
* Deliberately independent of `parseProjectLogEntries`: it answers "is a seal
|
|
171
|
+
* physically in this file?" where the parser answers "can this file's structure
|
|
172
|
+
* be read to contain a seal?". The gap between those two questions is the state
|
|
173
|
+
* every mutator must refuse, and all of them ask it the same way.
|
|
174
|
+
*
|
|
175
|
+
* The offset is returned alongside the text because callers must locate the
|
|
176
|
+
* seal, not merely recognize it: prose inside `## Entries` can quote a seal
|
|
177
|
+
* heading verbatim, so a substring test would place a seal that really sits
|
|
178
|
+
* under a later section inside the entries region and blame the wrong cause.
|
|
179
|
+
*/
|
|
180
|
+
export declare function findProjectLogSealHeadingLine(content: string): {
|
|
181
|
+
line: string;
|
|
182
|
+
index: number;
|
|
183
|
+
} | undefined;
|
|
184
|
+
/**
|
|
185
|
+
* Whether a seal body carries the canonical stand-alone seal token.
|
|
186
|
+
*
|
|
187
|
+
* `idempotencyToken` records the whole whitespace-delimited word containing a
|
|
188
|
+
* key, so a key glued to the varying completion timestamp never matches its own
|
|
189
|
+
* earlier append. A seal written before this convention carries no token at
|
|
190
|
+
* all, which is exactly why the seal is also recognized structurally.
|
|
191
|
+
*/
|
|
192
|
+
export declare function carriesProjectLogSealKey(body: string): boolean;
|
|
28
193
|
//# sourceMappingURL=grammar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grammar.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/grammar.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,YAC5B,KAAK,EACL,UAAU,EACV,aAAa,EACb,UAAU,CACF,CAAC;AACX,eAAO,MAAM,kBAAkB,YAAI,SAAS,EAAE,SAAS,CAAU,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,6BAA6B,WAAM,CAAC;AAEjD,eAAO,MAAM,mBAAmB,QACqE,CAAC;AACtG,eAAO,MAAM,qBAAqB,QACoC,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAO3E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAET;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,MAAM,CAET"}
|
|
1
|
+
{"version":3,"file":"grammar.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/log/grammar.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,YAC5B,KAAK,EACL,UAAU,EACV,aAAa,EACb,UAAU,CACF,CAAC;AACX,eAAO,MAAM,kBAAkB,YAAI,SAAS,EAAE,SAAS,CAAU,CAAC;AAElE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,6BAA6B,WAAM,CAAC;AAEjD,eAAO,MAAM,mBAAmB,QACqE,CAAC;AACtG,eAAO,MAAM,qBAAqB,QACoC,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,8BAA8B,QAAuB,CAAC;AAEnE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,8BAA8B,QAA4B,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAO3E;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc1E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAET;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,MAAM,CAET;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAChE,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,cAAc,CAAC;AAEvD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAKV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAShE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAY7C;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ9D"}
|