mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Answer architecture round 1: the publish job's write token reaches only the tag push, publishing names main, and the audit's other findings are filed
This commit is contained in:
@@ -20,13 +20,17 @@ jobs:
|
||||
concurrency:
|
||||
cancel-in-progress: false
|
||||
group: publish
|
||||
if: github.event_name == 'push'
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
needs: gate
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
# The write token reaches only the tag push, never the checkout the build containers mount.
|
||||
- env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
TAG_REMOTE: https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git
|
||||
run: bash publish.sh
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ published_version() {
|
||||
}
|
||||
|
||||
push_tag() {
|
||||
git tag "v$version" && git push origin "v$version"
|
||||
git tag "v$version" && git push "${TAG_REMOTE:-origin}" "v$version"
|
||||
}
|
||||
|
||||
read_field() {
|
||||
|
||||
@@ -4,12 +4,12 @@ import type { InlineNodeModel } from '../../adf/inline-nodes.ts'
|
||||
import type { LineContainer } from '../line-container.ts'
|
||||
import { assembleInlineLine, isSyntax, type InlineEscaping, type InlineSegment, type MarkRun, type NodeRange } from './line-escaping.ts'
|
||||
import { carriedInline } from '../opaque-carry.ts'
|
||||
import { holdsNullCharacter, trimTrailingSpace } from '../commonmark/grammar.ts'
|
||||
import { commonMarkLink, linkHref, markSpelling, spellMarkAttributes } from '../mark-spellings.ts'
|
||||
import { escapeUnbalanced, spellDestination } from '../commonmark/link-syntax.ts'
|
||||
import { identicalMark, isBareText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||
import { highlightDelimiter } from '../plain/conventions.ts'
|
||||
import { holdsNullCharacter, trimTrailingSpace } from '../commonmark/grammar.ts'
|
||||
import { identicalMark, isBareText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
||||
import { joinsWhenRead, textBreakSpelling } from '../adjacent-text.ts'
|
||||
import { largestNesting } from '../../nesting.ts'
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
`Bar = 9`
|
||||
|
||||
`Next ID = 75`
|
||||
`Next ID = 78`
|
||||
|
||||
| Goal | W |
|
||||
|---|---|
|
||||
@@ -33,13 +33,15 @@
|
||||
| 66 | 0.2.0 | defect | **Refuse an attribute value that is not a plain object, array or JSON primitive.** | 3 | 2 | 5 | 8 | 1 | 22.5 |
|
||||
| 71 | 0.2.0 | | **Add a README table comparing the package with the other ADF converters, each cell checked against that package's own docs or behaviour.** | 1 | 3 | 6 | 7 | 3 | 21.2 |
|
||||
| 43 | 0.2.0 | decision | **Give each markdown input its own reader, strict to its own standard.** | 6 | 7 | 8 | 9 | 4, 5 | 20.3 |
|
||||
| 77 | 0.2.0 | question | **Decide whether Goal 1 promises a result for plain data only, or for any value, getters and Proxies included.** | 2 | 2 | 4 | 7 | 1 | 19.5 |
|
||||
| 68 | 0.2.0 | | **Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.** | 3 | 3 | 4 | 7 | 1 | 18.2 |
|
||||
| 75 | 0.2.0 | | **Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.** | 2 | 2 | 3 | 7 | 1 | 17.5 |
|
||||
| 65 | 0.2.0 | defect | **Read an image not alone in its paragraph as its alt text linked to its URL, and a titled image alone in its paragraph as the image captioned with its title.** | 5 | 5 | 7 | 7 | 4, 5, 7 | 17.1 |
|
||||
| 70 | 0.2.0 | | **Give `package.json` the `keywords` someone searching npm for an ADF converter types.** | 1 | 1 | 4 | 6 | 3 | 16.1 |
|
||||
| 49 | 0.2.0 | | **Read a list whose bullet or ordered delimiter changes as two lists, in both readers, and retire `!adf:listBreak`.** | 4 | 5 | 5 | 8 | 4, 5 | 15.5 |
|
||||
| 46 | 0.2.0 | | **Publish the bundle size in the README, failing the release pipeline when it drifts.** | 2 | 4 | 5 | 5 | 3, 8 | 14.8 |
|
||||
| 61 | 0.2.0 | decision | **Have the emitter ask the inline reader how a line reads back, in place of `line-escaping.ts` predicting it.** | 6 | 8 | 3 | 8 | 1 | 14.0 |
|
||||
| 72 | 0.2.0 | decision | **Re-create `gitea.larvit.se/larvit/adf-codec` as a read-only pull mirror of GitHub, its issues off and its description pointing at GitHub.** | 2 | 1 | 3 | 6 | 3 | 13.1 |
|
||||
| 72 | 0.2.0 | decision | **Re-create `gitea.larvit.se/larvit/adf-codec` as a read-only pull mirror of GitHub, its issues and Actions off and its description pointing at GitHub.** | 2 | 1 | 3 | 6 | 3 | 13.1 |
|
||||
| 52 | 0.2.0 | | **Spell `colwidth` as a comma list, `colwidth="340,420"`.** | 3 | 3 | 5 | 6 | 6 | 11.5 |
|
||||
| 51 | 0.2.0 | | **Match a reference label to its definition under Unicode case folding.** | 2 | 2 | 2 | 7 | 4, 5 | 10.9 |
|
||||
| 60 | 0.2.0 | decision | **Collect the questions `parse/` asks `emit/` into one named module.** | 3 | 4 | 2 | 6 | 2 | 10.7 |
|
||||
@@ -56,6 +58,7 @@
|
||||
| 42 | 0.3.0 | defect | **Trim a text leaf's trailing blanks in linear time.** | 1 | 2 | 5 | 9 | 9 | 10.5 |
|
||||
| 33 | 0.3.0 | defect | **Emit a line in time linear in its mark runs, in `adfToMarkdown` and `adfToPlainMarkdown`.** | 4 | 5 | 6 | 9 | 9 | 8.7 |
|
||||
| 56 | 0.3.0 | principle | **Give each piece of `blocks.ts`'s block-walk state and `inline-content.ts`'s `Scan` one owner that returns what it changes.** | 4 | 5 | 2 | 4 | 1 | 6.8 |
|
||||
| 76 | 0.3.0 | principle | **State the files the package does not ship once, so the build, the lint ceiling and the coverage exclusions cannot drift apart.** | 2 | 2 | 1 | 3 | 1 | 5.5 |
|
||||
| 57 | 0.3.0 | principle | **Make each `ci.sh` leg build what it reads, so one leg run alone tests the current tree.** | 2 | 3 | 1 | 3 | 8 | 0.6 |
|
||||
| 58 | 0.3.0 | principle | **Port `ci.sh`, `publish.sh` and `docker-runner.sh` to standalone Python scripts.** | 4 | 6 | 1 | 2 | 8 | -2.6 |
|
||||
| 8 | 0.4.0 | | **Ship a CLI.** | 3 | 7 | 7 | 6 | 3 | 18.6 |
|
||||
@@ -128,6 +131,16 @@ a code fence whose info string opens `adf:` becomes the block carry where Common
|
||||
caller names the markdown it hands in: CommonMark, read as its spec says, or the lossless flavour,
|
||||
read as `spec/flavour.md` says. Breaking: `MIGRATION.md` says which call a caller takes.
|
||||
|
||||
### 77. Decide whether Goal 1 promises a result for plain data only, or for any value, getters and Proxies included.
|
||||
|
||||
`docs/decisions.md` §No value `JSON.parse` or `structuredClone` builds loops a call leaves getters,
|
||||
Proxies and non-enumerable keys to the caller, so `adfToMarkdown`, `adfToPlainMarkdown` and
|
||||
`isAdfDocument` throw on a revoked Proxy or a throwing getter, and walk forever on a getter that
|
||||
mints a fresh child per access. Goal 1 says every call returns a result. Either Goal 1 names plain
|
||||
data, as the README's guarantees already do, or an item wraps the guard walk in a tight `try/catch`
|
||||
returning `not-an-adf-document` with a bound on nodes visited, and the decision cites it. The
|
||||
maintainer's call. Found by the technical-principles audit, 2026-10-04.
|
||||
|
||||
### 68. Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.
|
||||
|
||||
`refuseContentAndText` (`emit/inline-line.ts`) and `emitDirectiveBlock` (`emit/adf-to-markdown.ts`)
|
||||
@@ -136,6 +149,14 @@ round-trips them; `docs/decisions.md` §The code list gives a cause the carry an
|
||||
them from the emitting half of the README's `unsupported-node-shape` row. Found by the README-goals
|
||||
audit, 2026-10-04.
|
||||
|
||||
### 75. Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.
|
||||
|
||||
`blockCarry` and `hostileBlockCarry` (`src/conformance/markdown-property.test.ts`) write a fence
|
||||
whose info string is `carry`, an ordinary code language since §The carry fence names the node type.
|
||||
So the property reaches `readCarriedBlock`'s refusals only where a random edit lands in a canonical
|
||||
document. Write `adf:<type>` and `adf:` fences, canonical and hostile. Found by the
|
||||
technical-principles audit, 2026-10-04.
|
||||
|
||||
### 65. Read an image not alone in its paragraph as its alt text linked to its URL, and a titled image alone in its paragraph as the image captioned with its title.
|
||||
|
||||
Both are refused today with `unmappable-image`: 14 examples in
|
||||
@@ -185,13 +206,15 @@ only the property tests catch drift. It caps the panel's Locality score. The rep
|
||||
time linear in the line: today `mergesWithSyntax`, `touchesSyntax` and `closesHeading` rescan a run
|
||||
of one character from each of its characters.
|
||||
|
||||
### 72. Re-create `gitea.larvit.se/larvit/adf-codec` as a read-only pull mirror of GitHub, its issues off and its description pointing at GitHub.
|
||||
### 72. Re-create `gitea.larvit.se/larvit/adf-codec` as a read-only pull mirror of GitHub, its issues and Actions off and its description pointing at GitHub.
|
||||
|
||||
Lands after the maintainer confirms the GitHub repository's settings, history, CI gate and
|
||||
publishing. The maintainer does this. Gitea cannot convert an existing repository to a mirror, so
|
||||
the copy is deleted and re-created. That drops the copy's commit hashes from before the 2026-10-04
|
||||
history rewrite, and its Actions secrets. The Gitea copy holds no issues or releases to move. When
|
||||
this lands, the `docs/decisions.md` entry "GitHub is canonical" loses its interim sentence.
|
||||
history rewrite, and its Actions secrets. The Gitea copy holds no issues or releases to move.
|
||||
Actions stay off on the mirror: Gitea runs `.github/workflows/` when `.gitea/workflows/` is absent,
|
||||
and the mirrored `publish` job would otherwise run there. When this lands, the `docs/decisions.md`
|
||||
entry "GitHub is canonical" loses its interim sentence.
|
||||
|
||||
### 52. Spell `colwidth` as a comma list, `colwidth="340,420"`.
|
||||
|
||||
@@ -308,6 +331,14 @@ functions write `pending`, `pieces`, `deactivatedBefore` and `openingSpellableLi
|
||||
`writeUnpaired`, `markPairings` and `markHighlights` (`inline-content.ts`), whose order changes the
|
||||
output; and `nestIn` (`plain/adf-to-plain-markdown.ts`), which pushes into its caller's array.
|
||||
|
||||
### 76. State the files the package does not ship once, so the build, the lint ceiling and the coverage exclusions cannot drift apart.
|
||||
|
||||
Technical principle DRY: the set is written in `tsconfig.build.json`'s `exclude`, `.oxlintrc.json`'s
|
||||
`ignorePatterns` and the `test` script's two `--test-coverage-exclude` flags, and §The size ratchet
|
||||
assumes they agree. A helper added to one list lints test code under the shipped ceiling, or drops
|
||||
shipped code from coverage, silently. Derive two from the third, or assert in a test that the three
|
||||
agree. Found by the technical-principles audit, 2026-10-04.
|
||||
|
||||
### 57. Make each `ci.sh` leg build what it reads, so one leg run alone tests the current tree.
|
||||
|
||||
Technical principle "Compose, do not entangle": Deno, Bun and the tests read the install leg's
|
||||
|
||||
Reference in New Issue
Block a user