Skip to content

Commit 4ce20d5

Browse files
committed
release: prepare deckflow-core 0.3.1
1 parent a48eab4 commit 4ce20d5

12 files changed

Lines changed: 2548 additions & 528 deletions

File tree

README.md

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ deckflow update install a newer core beside the running one ✅
1111
```
1212

1313
Core is a **capability broker**: it owns the CLI contract, the result envelope,
14-
the version pin and the safety policy. The provider owns the actual work, stays
15-
independently versioned, and is only fetched when a command needs it.
14+
the version pin, the safety policy, and canonical Source Bundle assembly. The
15+
provider owns parsing and optional parsing engines, stays independently
16+
versioned, and is only fetched when a command needs it.
1617

1718
## What core deliberately does not broker
1819

@@ -66,8 +67,8 @@ deckflow env check
6667

6768
```bash
6869
# Or a managed install by hand — no venv, works on a PEP 668 interpreter
69-
python3 -m pip install --target ~/.deckflow/core/0.3.0 deckflow-core==0.3.0
70-
PYTHONPATH=~/.deckflow/core/0.3.0 python3 -m deckflow_core env check
70+
python3 -m pip install --target ~/.deckflow/core/0.3.1 deckflow-core==0.3.1
71+
PYTHONPATH=~/.deckflow/core/0.3.1 python3 -m deckflow_core env check
7172
```
7273

7374
Requires Python 3.10+. Node.js is not involved anywhere in core.
@@ -90,14 +91,14 @@ JSON is the default output. `--human` is the opt-in, for people.
9091

9192
```json
9293
{
93-
"schema_version": 2, "command": "env check", "core_version": "0.3.0",
94+
"schema_version": 2, "command": "env check", "core_version": "0.3.1",
9495
"status": "succeeded",
95-
"extract": { "status": "not-acquired", "pinned_version": "0.3.0",
96+
"extract": { "status": "not-acquired", "pinned_version": "0.3.1",
9697
"resolution": "missing", "acquired": false, "download_mb": 4 },
9798
"env": {
9899
"skill": { "name": "gezhe-ppt", "version": "0.4.0-beta.2",
99100
"root": "/…/gezhe-ppt", "version_source": "frontmatter" },
100-
"runtime": { "version": "0.3.0", "installation": "managed", "location": "" },
101+
"runtime": { "version": "0.3.1", "installation": "managed", "location": "" },
101102
"python": { "version": "3.14.5", "executable": "/opt/homebrew/bin/python3",
102103
"satisfies_requires_python": true, "externally_managed": true },
103104
"cloud": { "available": false, "reason": "extract-not-acquired",
@@ -130,9 +131,9 @@ deckflow auth set-key --stdin # a space worker secret; no browser needed
130131

131132
The credential lives in `~/.deckflow/credentials` and is **shared with
132133
DeckHTML**. Core owns none of it: every action here forwards to
133-
`deckflow-extract`, which owns that file's merge rules. This is core's one
134-
exception to "core writes only `--out` and `--report`", and it is delegated
135-
rather than reimplemented.
134+
`deckflow-extract`, which owns that file's merge rules. Credential writes are
135+
delegated rather than reimplemented; `parse` is the only command that changes
136+
project state, and it is limited to `<project>/source-bundle`.
136137

137138
Two consequences worth knowing:
138139

@@ -150,34 +151,49 @@ There is no `logout`. Clear a stored credential with
150151
## `deckflow parse`
151152

152153
```bash
153-
deckflow parse <file> --out <dir> [--report r.json] [--overwrite]
154+
deckflow parse <file> \
155+
--project <deck-project> \
156+
--brief "<user task>" \
157+
--deck-language <bcp47> \
158+
[--replace] [--upgrade auto] [--report r.json]
154159
```
155160

156-
Extracts one local file into a Parse Bundle (`parse-manifest.json` +
157-
`document.md` + `assets/`) through the deckflow-extract provider.
158-
159-
Deliberately thin — the provider already has a well-shaped contract, so core
160-
adds boundaries and gets out of the way:
161-
162-
- **the bundle passes through untouched.** Core does not rewrite `document.md`,
163-
recompute fidelity, or invent a second artifact vocabulary alongside it.
164-
- **`recommendations[]` reaches the caller verbatim.** When the provider says a
165-
heavier engine would extract 65 images instead of 5, that surfaces as an
166-
`info` diagnostic — choosing is the caller's job, never core's.
167-
- **engine upgrades default to `never`.** Provider *acquisition* happens
168-
automatically, but the provider's own optional engines (56MB PDF, 107MB OCR)
169-
change what the extraction produces, so they are opt-in via `--upgrade`.
170-
- **`--mode local` is forced and cloud credentials are withheld**, and
171-
`--fetch-remote-images off` is passed explicitly so a change in the
172-
provider's defaults cannot put the content plane on the network. Withholding
173-
means both halves: the credential variables are removed from the child
174-
environment *and* `DECKFLOW_NO_STORED_CREDENTIALS=1` is set, because the
175-
provider also reads `~/.deckflow/credentials` — the file it shares with
176-
DeckHTML — where a logged-in machine would otherwise hand back exactly what
177-
was just removed.
161+
Parses one direct local file, validates the provider's transient Parse Bundle,
162+
and atomically appends the accepted result to
163+
`<project>/source-bundle`. Luna calls this command once; it does not import or
164+
inspect the intermediate bundle.
165+
166+
- **No AI is used.** `brief` is stored after trimming outer whitespace.
167+
`deck-language` is the eventual Deck language. The parser's independently
168+
detected `source_language` is stored under `manifest.imports[]`; no
169+
translation happens here.
170+
- **Only usable results are committed.** The input SHA-256, schema, paths,
171+
files, asset hashes, locator profile, provider report, fidelity, coverage,
172+
gaps and decision must close. `decision.usable` must be true and no gap may
173+
be blocking.
174+
- **The canonical write is transactional.** Core builds and validates a sibling
175+
staging directory, computes the Source Bundle fingerprint, and then swaps it
176+
into place. Any failure leaves the old bundle unchanged.
177+
- **draft and review-ready bundles accept append.** `--replace` rebuilds one
178+
from the current input. A `confirmed` Source Bundle is immutable through this
179+
command because changing it also requires downstream invalidation.
180+
- **engine upgrades default to `never`.** Explicit `--upgrade auto` authorizes
181+
extract to install, self-check, activate and reselect one local enhancement.
182+
If installation fails but the fallback is usable, the bundle is committed
183+
and core reports `partial`.
184+
- **The Parse Bundle is private.** Its directory, manifest path and provider
185+
command never appear in stdout, reports or canonical provenance. Sanitized
186+
fidelity, coverage, gaps, recommendations and acquisition outcome remain
187+
available for audit.
188+
- **Local mode is explicit and cloud credentials are withheld unless
189+
`--mode cloud` is passed.** `--fetch-remote-images off` is also passed so a
190+
change in provider defaults cannot put local content on the network.
191+
Withholding means both halves: credential variables are removed from the
192+
child environment and `DECKFLOW_NO_STORED_CREDENTIALS=1` is set, because the
193+
provider also reads `~/.deckflow/credentials`.
178194
- **URLs are refused.** The provider can fetch them; core does not, because
179195
"the content plane never reaches the network" is not worth stating with an
180-
exception in it. The refusal names the direct provider command.
196+
exception in it.
181197

182198
## How the provider is resolved
183199

@@ -239,7 +255,7 @@ Two separate planes:
239255
| Plane | Policy |
240256
| --- | --- |
241257
| Providers (fetching code) | network allowed, for the pinned package from declared indexes only, written only to the managed home, always reported |
242-
| Content (sources, extracted text, assets) | never uploaded. The provider's cloud mode is used only when you explicitly ask for it; the presence of an API key is not authorization |
258+
| Content (sources, extracted text, assets) | local mode never uploads; the provider's cloud mode uploads only when you explicitly ask for it, and the presence of an API key is not authorization |
243259

244260
## Output contract
245261

@@ -248,7 +264,7 @@ deterministically so two isolated runs over the same inputs produce the same
248264
report bytes.
249265

250266
```json
251-
{"schema_version": 2, "command": "env check", "core_version": "0.3.0",
267+
{"schema_version": 2, "command": "env check", "core_version": "0.3.1",
252268
"status": "succeeded", "started_at": "...", "finished_at": "...",
253269
"extract": null, "inputs": [], "outputs": [], "diagnostics": []}
254270
```
@@ -275,11 +291,16 @@ same shape rather than a traceback.
275291

276292
## Scope of this release
277293

278-
v0.3.0 registers `env`, `auth`, `parse` and `update`, and that is the whole
279-
surface. `editor`, `export`, `validate` and `providers` are not registered at
280-
all: an unregistered name is an argparse invalid choice and exit 2, never a stub
281-
or a "not implemented" response, because either would put the name in `--help`
282-
and let a caller believe core owns the capability.
294+
v0.3.1 keeps `env`, `auth`, `parse` and `update` as the complete command
295+
surface, and changes `parse` into the transactional canonical Source Bundle
296+
ingestion entrypoint. It distinguishes caller-supplied Deck language from
297+
parser-detected source language, supports draft/review-ready append and
298+
replace, and keeps confirmed bundles immutable.
299+
300+
`editor`, `export`, `validate` and `providers` are not registered at all: an
301+
unregistered name is an argparse invalid choice and exit 2, never a stub or a
302+
"not implemented" response, because either would put the name in `--help` and
303+
let a caller believe core owns the capability.
283304

284305
`providers` is on that list because it was core's own word for one package. The
285306
resolution ladder, the pin and the managed install all survive — the noun does

0 commit comments

Comments
 (0)