jinaga-server 3.7.4 → 3.8.0

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.
Files changed (39) hide show
  1. package/.claude/skills/degrees-of-freedom/.openskills.json +7 -0
  2. package/.claude/skills/degrees-of-freedom/SKILL.md +18 -0
  3. package/.claude/skills/degrees-of-freedom/degrees-of-freedom-constitution.md +142 -0
  4. package/.claude/skills/night-shift-setup/.openskills.json +7 -0
  5. package/.claude/skills/night-shift-setup/SKILL.md +95 -0
  6. package/.claude/skills/night-shift-setup/configuring-a-repository.md +111 -0
  7. package/.claude/skills/night-shift-setup/creating-the-log.md +59 -0
  8. package/.claude/skills/night-shift-setup/creating-the-routines.md +80 -0
  9. package/.claude/skills/night-shift-setup/log-model.factual +971 -0
  10. package/.claude/skills/night-shift-worker/.openskills.json +7 -0
  11. package/.claude/skills/night-shift-worker/SKILL.md +199 -0
  12. package/.claude/skills/night-shift-worker/night-shift-log.md +72 -0
  13. package/.claude/skills/night-shift-worker/scripts/register-stack.sh +173 -0
  14. package/.claude/skills/night-shift-worker/stacking.md +57 -0
  15. package/.claude/skills/night-shift-worker/verifying-a-merged-fix.md +16 -0
  16. package/.claude/skills/refining-issues/.openskills.json +7 -0
  17. package/.claude/skills/refining-issues/SKILL.md +327 -0
  18. package/.claude/skills/refining-issues/references/worked-example.md +234 -0
  19. package/.github/workflows/main.yml +2 -2
  20. package/.night-shift/config.md +84 -0
  21. package/.night-shift/skills.md +17 -0
  22. package/README.md +21 -0
  23. package/dist/http/router.js +207 -80
  24. package/dist/http/router.js.map +1 -1
  25. package/dist/http/stream.d.ts +0 -1
  26. package/dist/http/stream.js +6 -17
  27. package/dist/http/stream.js.map +1 -1
  28. package/dist/jinaga-server.js +74 -7
  29. package/dist/jinaga-server.js.map +1 -1
  30. package/integration-test/jinaga-test/package-lock.json +4 -4
  31. package/integration-test/jinaga-test/package.json +1 -1
  32. package/package.json +2 -2
  33. package/src/http/router.ts +249 -99
  34. package/src/http/stream.ts +21 -36
  35. package/src/jinaga-server.ts +92 -4
  36. package/test/http/errorStatusMappingSpec.ts +351 -0
  37. package/test/http/streamLogVolumeSpec.ts +284 -0
  38. package/test/jinaga-server/poolConfigurationSpec.ts +147 -0
  39. package/test/jinaga-server/tracePoolSpec.ts +368 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "source": "michaellperry/skills",
3
+ "sourceType": "git",
4
+ "repoUrl": "https://github.com/michaellperry/skills",
5
+ "subpath": "skills/degrees-of-freedom",
6
+ "installedAt": "2026-10-15T03:05:22.754Z"
7
+ }
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: degrees-of-freedom
3
+ description: Scores a design, a specification, or an issue's requirement against the degrees-of-freedom constitution — whether a representation has exactly as many independent variables as the problem it represents. Use when a repository names this constitution under ## Authority or in its contributor docs, when an issue's Conformance section cites one of its articles, when reviewing a design for invalid states, redundant state, forbidden combinations, or coupling that ripples across sites, or when deciding whether to remove a redundant copy of a fact or to guard it with a check.
4
+ ---
5
+
6
+ # Degrees of freedom
7
+
8
+ The constitution is [degrees-of-freedom-constitution.md](degrees-of-freedom-constitution.md), beside this file. Read it in full before you cite it. It is short, and every citation depends on its exact wording.
9
+
10
+ ## Citing it
11
+
12
+ Cite an article by its number, as `Art. 2`, and quote the sentence you are relying on. Part IV is the evaluation procedure: its questions name the articles they test. The Appendix states where the constitution accepts a compromise, so read it before you call a trade-off a violation.
13
+
14
+ ## Where it governs
15
+
16
+ Only in a repository that adopts it, by naming it as authority — under `## Authority` in `.night-shift/config.md`, or in its own contributor docs. Nothing outside such a repository is held to it.
17
+
18
+ An adopting repository installs this skill and commits it, and changes it only by refreshing from this repository. Its copy is never edited in place, so every adopting repository cites the same text.
@@ -0,0 +1,142 @@
1
+ # A Constitution of Degrees of Freedom
2
+
3
+ *A basis for evaluating whether a system's representation is faithful to its problem.*
4
+
5
+ ---
6
+
7
+ ## Preamble
8
+
9
+ Every system carries two spaces. There is the **problem space**: the set of situations the system must genuinely distinguish and respond to. And there is the **representation space**: the set of configurations the system can actually hold, whether in code, state, or configuration.
10
+
11
+ A system is well-designed to the exact degree that these two spaces are the same shape. When the representation space is larger than the problem space, the surplus shows up as invalid states, redundant state, forbidden combinations, and coupling. When the representation space is smaller, meaningful variation becomes inexpressible, forcing forks and special cases.
12
+
13
+ The single governing quantity is the **number of degrees of freedom**: the count of independent variables that can be changed. This constitution holds that a system's degrees of freedom must equal the dimensionality of the problem, no more and no fewer. Everything below is a consequence of that one requirement.
14
+
15
+ ---
16
+
17
+ ## Part I. The Law of State
18
+
19
+ ### Article 1 — Exactness of Freedom
20
+
21
+ The number of independent variables equals the number of dimensions along which the problem can vary.
22
+
23
+ This is a two-sided bound, not a minimization. Too many independent variables create configurations that must be forbidden. Too few make valid behaviors unreachable. The target is a bijection between what can be represented and what can meaningfully differ.
24
+
25
+ *Diagnostic.* Count the inputs a user or operator can set independently. Count the axes along which the problem's behavior should actually vary. If the first number exceeds the second, locate the surplus. If it falls short, locate the variation you cannot express without editing code.
26
+
27
+ ### Article 2 — Derivation of Dependents
28
+
29
+ Only a generating set is stored. Every value that can be computed from that set is computed, never stored alongside it.
30
+
31
+ Choose a basis (the sources of truth), then derive the rest by projection. A shared secret is defined once and deployed to both ends. Dependent props descend from a common `useState`. The dependent value has no independent existence, so it cannot drift, and it contributes no degree of freedom of its own.
32
+
33
+ *Diagnostic.* Look for the same fact maintained in two places, for "keep these in sync" comments, and for update anomalies where changing one field silently invalidates another. Each is stored dependent state that should have been derived.
34
+
35
+ ### Article 3 — Totality of Meaning
36
+
37
+ Every configuration the system can represent is meaningful. No representable state denotes an error.
38
+
39
+ A reachable error state is not a bug to be caught. It is evidence that the representation admits a configuration the problem does not contain. The remedy is not a validation check that rejects the state at runtime. It is a representation in which the state cannot be formed. Make illegal states unrepresentable, and the validation becomes unnecessary because it becomes vacuous.
40
+
41
+ *Diagnostic.* Enumerate the runtime validations that reject inputs the type system or schema permits. Each such guard marks a gap between representation and meaning. Ask whether the representation could be narrowed until the guard has nothing left to reject.
42
+
43
+ ### Article 4 — Canonicity of Representation
44
+
45
+ No two distinct representations denote the same meaning.
46
+
47
+ This is the dual of Article 3. Article 3 forbids representations with no meaning; Article 4 forbids distinct representations with identical meaning. Redundant encodings, dead configuration, and flags that produce indistinguishable behavior are all surplus freedom that per instance is harmless but in aggregate invites drift and confusion. The representation should be the quotient of the raw space by semantic equivalence: one representative per meaning.
48
+
49
+ *Diagnostic.* Search for two configurations that are always behaviorally identical, for options whose values never change any observable outcome, and for encodings with more than one spelling of the same intent.
50
+
51
+ > **Theorem (Faithful Representation).** Articles 1 through 4 hold jointly if and only if the map from representation space to meaning space is a bijection. Article 3 gives totality (the map is defined everywhere). Article 4 gives injectivity (no collisions). Article 1 fixes the dimension of the domain to match the codomain. Article 2 is the constructive method by which the domain is reduced to its true dimension.
52
+
53
+ ---
54
+
55
+ ## Part II. The Law of Behavior
56
+
57
+ ### Article 5 — Stratification by Rate of Change
58
+
59
+ Behavior is layered by how often it changes. Decisions that change frequently are expressed high, where they are cheap to change and broad in reach. Mechanism that changes rarely is expressed low, where it is stable.
60
+
61
+ Layers sheared by their rate of change do not grind against each other. A frequently revised decision that lives inside stable mechanism forces the mechanism to change at the decision's pace, which is the definition of friction.
62
+
63
+ *Diagnostic.* Chart what changed in the last several revisions and where the change landed. If high-frequency decisions require edits to low-level mechanism, or if a routine policy change demands a code deployment, the layers are misassigned.
64
+
65
+ ### Article 6 — Specification over Process
66
+
67
+ High-level behavior is stated declaratively and read like a specification. It says what holds, not how it is carried out. Stable machinery, a DSL or an interpreter or a framework, gives the specification its operational meaning.
68
+
69
+ A single specification governs many processes at once, because the machinery that reads it is shared. This is where Article 5's high layer acquires its reach: one declarative statement, many affected processes.
70
+
71
+ *Diagnostic.* Read the top layer aloud. If it reads as a sequence of steps rather than a statement of intended properties, behavior is still bound to process. Ask how many processes a single change at this layer affects. One is a warning sign.
72
+
73
+ ### Article 7 — Closure of the Specification Language
74
+
75
+ Every well-formed specification denotes valid behavior. Changing a specification yields new valid behavior, never a bug.
76
+
77
+ This is Articles 3 and 4 applied to the specification layer itself. The specification language is a state space, and the same demand governs it: no well-formed sentence should be meaningless or erroneous. When the language is closed in this sense, its guarantees are structural. The author of a specification cannot express an invalid behavior because the grammar and semantics have already absorbed the invariants. The constitution is self-similar: the discipline that governs runtime state governs the language in which behavior is written.
78
+
79
+ *Diagnostic.* Attempt to write a syntactically valid specification that produces a broken system. Every way you succeed is an invariant the language failed to enforce and pushed onto the author's vigilance.
80
+
81
+ ### Article 8 — Independence of Axes
82
+
83
+ Changing one part of a specification requires no corresponding change in another part.
84
+
85
+ Where two parts must change together, the co-varying quantity is a single degree of freedom wearing the costume of two. This is the deep identity in the constitution: **accidental coupling is latent redundancy.** The shared quantity should be named once and derived into both sites, which returns the problem to Article 2. Essential coupling, the kind the problem genuinely imposes, is not eliminated. It is expressed exactly once, inside the derivation, rather than replicated across the sites it governs.
86
+
87
+ *Diagnostic.* Look for changes that ripple: one intended edit forcing several coordinated edits elsewhere. Trace the ripple to the quantity being kept consistent by hand, and derive it from a single source instead.
88
+
89
+ ---
90
+
91
+ ## Part III. The Unifying Law
92
+
93
+ Invalid states, redundant states, forbidden combinations, and rippling coupling are not four defects. They are one defect seen from four angles.
94
+
95
+ > **The representation space has more degrees of freedom than the problem it represents.**
96
+
97
+ - Surplus freedom that maps to *no* meaning appears as an **invalid state** (Article 3).
98
+ - Surplus freedom that maps to a *duplicated* meaning appears as **redundancy** (Article 4).
99
+ - Surplus freedom constrained *after the fact* appears as a **forbidden combination**, which is a constraint the representation failed to absorb (Article 1).
100
+ - Surplus freedom split *across sites* appears as **coupling**, the hand-maintained consistency of what should have been one derived value (Article 8).
101
+
102
+ Reduce the degrees of freedom to the dimensionality of the problem and all four dissolve together.
103
+
104
+ ---
105
+
106
+ ## Part IV. Evaluation Procedure
107
+
108
+ To score a system against this constitution, answer each question. Every "yes" localizes a specific surplus and names the article it offends.
109
+
110
+ **On state**
111
+
112
+ 1. Can I represent a state I would then have to forbid, reject, or guard against? *(Art. 1, 3)*
113
+ 2. Is any value stored that could be computed from other stored values? *(Art. 2)*
114
+ 3. Do two distinct configurations ever produce identical behavior? *(Art. 4)*
115
+ 4. Does the valid range of one variable depend on the current value of another? *(Art. 1, 8)*
116
+
117
+ **On behavior**
118
+
119
+ 5. Do frequently changing decisions live inside rarely changing mechanism? *(Art. 5)*
120
+ 6. Does the top layer read as steps rather than as a specification of intent? *(Art. 6)*
121
+ 7. Can a well-formed specification produce a broken system? *(Art. 7)*
122
+ 8. Does one intended change force several coordinated changes elsewhere? *(Art. 8)*
123
+
124
+ A system honors the constitution when both of these are true:
125
+
126
+ > There is no state I can represent that I must then forbid, and there is no state I must keep consistent by hand.
127
+
128
+ The first clause is the state law (Part I). The second is the behavior law (Part II). Together they assert the bijection between representation and problem that the Preamble demands.
129
+
130
+ ---
131
+
132
+ ## Appendix. Boundaries and Tensions
133
+
134
+ A constitution is more useful when its limits are stated, so that a compromise can be recognized as a compromise rather than mistaken for a violation.
135
+
136
+ **Deliberate physical redundancy is permitted; conceptual redundancy is not.** A cache, a denormalized read model, or a replica adds redundant *storage* for performance or fault tolerance. This is consistent with the constitution provided the redundant copy is a pure function of its source, is regenerable, and is never authoritative. The conceptual degrees of freedom are unchanged because the source alone determines meaning. The test is whether the copy could be dropped and rebuilt with no loss.
137
+
138
+ **Essential coupling is expressed, not erased.** Article 8 removes accidental coupling. It does not deny that the problem itself couples some quantities. Genuine coupling belongs in the single derivation that produces the coupled values, where it is stated once, rather than replicated at every site those values appear.
139
+
140
+ **Minimality is exactness, not compression.** Driving degrees of freedom *below* the problem's dimensionality, whether by clever encoding or by collapsing distinctions the problem actually makes, is a violation of Article 1 as surely as surplus freedom is. The aim is a faithful representation, not the smallest one. Legibility is part of faithfulness.
141
+
142
+ **Invariants must live somewhere.** Making illegal states unrepresentable moves an invariant from a runtime check into the structure of the representation or the semantics of the language. It does not make the invariant free. The work is in choosing a representation whose shape encodes the constraint, so the cost is paid once at design time rather than repeatedly at runtime and in the author's attention.
@@ -0,0 +1,7 @@
1
+ {
2
+ "source": "factoryengineering/skills",
3
+ "sourceType": "git",
4
+ "repoUrl": "https://github.com/factoryengineering/skills",
5
+ "subpath": "skills/night-shift-setup",
6
+ "installedAt": "2026-10-15T02:59:05.063Z"
7
+ }
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: night-shift-setup
3
+ description: Stands up the night-shift protocol for an organization, from nothing to a running nightly sweep. Creates the Night Shift Log application from a committed seed, registers the practice and each tracked repository exactly once, writes the per-repository configuration file the worker refuses to run without, and creates the scheduled sessions that fire the sweep. Use when adopting the night-shift protocol for the first time, when adding a repository to an existing practice, or when a run stopped because it found no practice or no repository matching the one it was sweeping.
4
+ ---
5
+
6
+ # Night Shift Setup
7
+
8
+ The night shift is a coordinator that sweeps a labelled issue queue and one worker per repository that takes a single issue to a pull request. Neither keeps state between runs, so both read a log, and the log is an application you create once and share across every repository you track.
9
+
10
+ This skill covers the one-time acts. `night-shift-coordinator` and `night-shift-worker` cover everything that happens nightly.
11
+
12
+ ## When to use
13
+
14
+ - **Adopting the protocol** for the first time in an organization.
15
+ - **Adding a repository** to a practice that already exists.
16
+ - **A run stopped** because it found no practice, no matching repository, or more than one of either.
17
+ - **A run stopped** because a repository's configuration file was missing a required heading.
18
+
19
+ ---
20
+
21
+ ## What you are building
22
+
23
+ | Piece | Where it lives | How many |
24
+ |---|---|---|
25
+ | The Night Shift Log application | your Factual workspace | one per organization |
26
+ | A practice, and one repository record per tracked repository | inside that application | one practice, one record each |
27
+ | `.night-shift/config.md` | each tracked repository | one per repository |
28
+ | `.night-shift/routines.md` | the coordinator's own repository | one |
29
+ | The installed skills | committed into each repository | worker in each tracked repository, coordinator in its own |
30
+ | The scheduled sessions | your agent host | one coordinator, one worker per repository |
31
+
32
+ ```
33
+ Task Progress:
34
+ - [ ] Create the log application and publish the seed
35
+ - [ ] Create the practice, exactly once
36
+ - [ ] Register each tracked repository, exactly once
37
+ - [ ] Write .night-shift/config.md in each tracked repository
38
+ - [ ] Install and commit night-shift-worker and refining-issues in each tracked repository
39
+ - [ ] Install and commit night-shift-coordinator in its own repository
40
+ - [ ] Write .night-shift/routines.md
41
+ - [ ] Create the sessions and fire the coordinator once by hand
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Create the log
47
+
48
+ Read **[creating-the-log.md](creating-the-log.md)**. It publishes `log-model.factual` into a new application, then runs the practice and repository ceremony.
49
+
50
+ **Two calls in that ceremony are not idempotent.** Creating a practice and registering a repository both mint a new record every time they run, and a duplicate splits your history across two records that nothing joins. Never call either without first running, in the same session, the query that would have found the thing.
51
+
52
+ ---
53
+
54
+ ## Configure each repository
55
+
56
+ Read **[configuring-a-repository.md](configuring-a-repository.md)**. It lists the required headings, says why each one cannot be derived or defaulted, and gives a filled-in example.
57
+
58
+ The rule that keeps this from growing back into a second protocol: **anything that is not one of those headings belongs in the skill, not in the config.**
59
+
60
+ ---
61
+
62
+ ## Install the skills
63
+
64
+ ```bash
65
+ npx openskills install factoryengineering/skills
66
+ ```
67
+
68
+ Install `night-shift-worker` and `refining-issues` into each tracked repository, and `night-shift-coordinator` into the repository the coordinator checks out.
69
+
70
+ `refining-issues` is what fills the queue the worker drains. It is installed beside the worker, in the same repository, because it reads the same `.night-shift/config.md` and audits that repository's issues — and because the bar the queue label asserts should be legible to anyone looking at the repository whose issues carry it. A person runs it; nothing schedules it. **Commit what you install.** A scheduled run that installs from the network at execution time can have its protocol changed by an upstream edit it never reviewed, and gains a failure mode at whatever hour it wakes.
71
+
72
+ Record which upstream commit each installed copy came from, so a later reader can tell an intentional local edit from an old copy.
73
+
74
+ ---
75
+
76
+ ## Create the sessions
77
+
78
+ Read **[creating-the-routines.md](creating-the-routines.md)**. Each session's prompt is a loader that names its skill and its configuration file, and nothing more. Protocol restated in a prompt is protocol that can disagree with the skill, and the disagreement will not surface until a run acts on the wrong half.
79
+
80
+ ---
81
+
82
+ ## Verify before you leave it running
83
+
84
+ 1. Fire the coordinator by hand, in daylight, appending `Dry run. Sweep and report; dispatch nothing.` to the message.
85
+ 2. Confirm it resolves the practice and every repository, reads each configuration file, and reports a queue per repository.
86
+ 3. Let one scheduled run go unattended, then read the sweep back out of the log and check that its dispatch count matches its report.
87
+
88
+ ## Resources
89
+
90
+ | Resource | Purpose |
91
+ |---|---|
92
+ | [creating-the-log.md](creating-the-log.md) | Publishing the seed, and the one-time practice and repository ceremony |
93
+ | [configuring-a-repository.md](configuring-a-repository.md) | The required headings, with a worked example |
94
+ | [creating-the-routines.md](creating-the-routines.md) | The scheduled sessions and their loader prompts |
95
+ | [log-model.factual](log-model.factual) | Read and send. The log's 47 definitions and its manifest, in four batches |
@@ -0,0 +1,111 @@
1
+ # Configuring a tracked repository
2
+
3
+ Every tracked repository carries `.night-shift/config.md` at its root. The worker reads it from its checkout; the coordinator reads the same file over the hosting API; `refining-issues` reads it before it audits anything. There is one copy, in the repository it describes, so the roles cannot disagree about it.
4
+
5
+ It sits outside `.claude/skills/`, so reinstalling a skill cannot clobber it, and outside `.claude/` entirely, because that directory is agent-harness configuration and this is protocol configuration a person maintains.
6
+
7
+ ## Contents
8
+
9
+ - [The headings](#the-headings)
10
+ - [What is deliberately not here](#what-is-deliberately-not-here)
11
+ - [Worked example](#worked-example)
12
+
13
+ ## The headings
14
+
15
+ Every heading in the table below is required. `## Branch prefix` is recognized too, and is optional.
16
+
17
+ **A missing required heading is a stop, not a default.** A worker that cannot find one names it and opens no pull request. `none` and `Nothing.` are legal values; absence is not, because absence cannot be told apart from an oversight.
18
+
19
+ | Heading | Why it cannot be derived or defaulted |
20
+ |---|---|
21
+ | `## Visibility` | `private` carries a rule against quoting the repository's contents into any public place. A wrong guess is a leak, and nothing inside the container can tell you. |
22
+ | `## Issue label` | A wrong guess silently sweeps the wrong queue, or nothing at all. |
23
+ | `## Read first` | Which files a worker must read before touching an issue. One repository points at a build guide, another at an accepted specification, another at nothing. |
24
+ | `## Authority` | The documents an issue must answer to, and what citing each one means. `refining-issues` runs R4 against this and nothing else. It is not derivable: which document governs, and whether citing it means naming a section or citing a principle, is a decision about how the project is run. `none` is a complete answer, and it makes R4 vacuous rather than failed. |
25
+ | `## Before you fix` | Where "reproduce first" is replaced by something else, such as conformance criteria a change is held to. |
26
+ | `## Verification commands` | The exact commands, in order, that must be green before every push. |
27
+ | `## CI workflow` | The workflow *file* that gates the merge. Deriving it means parsing every workflow in the repository at whatever hour the run wakes. |
28
+ | `## After the pull request` | Post-pull-request hooks. This is the heading the rule exists for: `none` says a person decided there is nothing, while absence says nobody looked. |
29
+ | `## What is different about this repository` | Free prose for anything the protocol does not fix. `Nothing.` is a complete answer. |
30
+
31
+ `## Branch prefix` is optional and defaults to `claude/issue-<number>-<slug>`. It is cosmetic, and a wrong guess costs nothing.
32
+
33
+ ## What is deliberately not here
34
+
35
+ Four values a reader might expect. Each is derivable, and a stored copy can only be wrong later.
36
+
37
+ - **The repository's owner and name** come from `git remote get-url origin`.
38
+ - **Whether `gh` is installed** comes from `command -v gh`.
39
+ - **Whether stacked pull requests are enabled** comes from `register-stack.sh list` returning exit 3.
40
+ - **Whether a workflow strips the queue label on close** changes nothing a run does, because the protocol always filters for open issues.
41
+
42
+ **Anything that is not one of those headings belongs in the skill.** This file is where a second, per-repository protocol would grow if it were allowed to, and the closed list is what prevents it.
43
+
44
+ ## Worked example
45
+
46
+ ````markdown
47
+ # Night shift configuration
48
+
49
+ The `night-shift-worker`, `night-shift-coordinator`, and `refining-issues`
50
+ skills read this file. Every `##` heading below except `## Branch prefix` is
51
+ required. A missing heading is an error, not a default: stop and name the
52
+ heading you could not find. Anything that is not one of these headings is
53
+ protocol, and protocol lives in the skill.
54
+
55
+ ## Visibility
56
+
57
+ `private`
58
+
59
+ Never quote this repository's contents into a public repository, issue, or
60
+ pull request. Its sibling repositories are public.
61
+
62
+ ## Issue label
63
+
64
+ `ready`
65
+
66
+ ## Read first
67
+
68
+ - `CONTRIBUTING.md` — build commands, subsystem layout, testing rules.
69
+
70
+ ## Authority
71
+
72
+ - `docs/architecture.md` — the accepted design. An issue names the section it
73
+ answers to wherever one covers the change. An amendment to it is the
74
+ maintainer's decision and never lands in an implementation slice.
75
+
76
+ ## Before you fix
77
+
78
+ Reproduce first. An issue's repro may have been reconstructed rather than
79
+ verified by its reporter, so a repro that fails is a finding, not a failure.
80
+
81
+ ## Verification commands
82
+
83
+ Both green before every push, in this order.
84
+
85
+ ```
86
+ npm run typecheck
87
+ npm test
88
+ ```
89
+
90
+ `npm test` builds first, so a fresh container needs no separate build step.
91
+ `npm run typecheck` reaches scripts the workspace build leaves out.
92
+
93
+ ## CI workflow
94
+
95
+ `ci.yml`
96
+
97
+ Read runs for this file; it is the merge gate. A second workflow also runs on
98
+ pull requests, and neither carries a `branches:` filter, so every layer of a
99
+ stack gets check runs from its own pull request event.
100
+
101
+ ## After the pull request
102
+
103
+ `none`
104
+
105
+ ## What is different about this repository
106
+
107
+ Issues carry their own dependencies. Many close with a `Depends on #<n>` line,
108
+ and epics carry an order clause the maintainer rewrites as sessions find
109
+ things, so read the clause on each sweep rather than trusting a remembered
110
+ sequence.
111
+ ````
@@ -0,0 +1,59 @@
1
+ # Creating the Night Shift Log
2
+
3
+ ## Contents
4
+
5
+ - [Publishing the seed](#publishing-the-seed)
6
+ - [The practice ceremony](#the-practice-ceremony)
7
+ - [Registering a repository](#registering-a-repository)
8
+ - [References are session tokens, not identifiers](#references-are-session-tokens-not-identifiers)
9
+
10
+ ## Publishing the seed
11
+
12
+ The log is a Jinaga application reached through the Factual MCP server. Create it once per organization.
13
+
14
+ 1. Open a console. It starts unbound.
15
+ 2. `let $apps = applications`. The response lists every workspace you can reach, each carrying its own `ref`. Pick the workspace you want and take that `ref`. Spend it in a **second** call, because a batch that binds and indexes in one go is guessing at an index it has not seen yet.
16
+ 3. `create application "Night Shift Log" in <the ref you took>`, on a clean console.
17
+
18
+ The indexes are one flat sequence across workspaces and the applications inside them, so the workspace you want is not reliably `$apps[0]`. Read the ref off the response rather than assuming a position.
19
+ 4. Send `log-model.factual` in its four marked batches, **in file order**. Do not reorder: fact types precede the specifications that walk them, specifications precede the actions that write them, and within the fact types each one follows every type it names as a predecessor. Sending the batches separately makes a failure name its layer, because a batch stops at its first failure.
20
+ 5. `publish` after batch 3. Expect a `manifest_missing` warning; batch 4 is the answer to it.
21
+ 6. Send batch 4, then publish again.
22
+
23
+ **Batch 4 is not decoration.** It carries the routing that lets anything discover the application, and the per-action argument guidance that both night-shift skills tell a run to read instead of trusting a list in a file. An application published without it works and is undiscoverable.
24
+
25
+ ## The practice ceremony
26
+
27
+ A **practice** is one person's night-shift setup, and one practice covers every repository tracked. It roots at a single-use owner, so you reach it through `practicesForAdministrator` rather than by owning it.
28
+
29
+ ```
30
+ query practicesForAdministrator($me)
31
+ ```
32
+
33
+ | Rows | What it means | What to do |
34
+ |---|---|---|
35
+ | exactly one | Already set up | Use it. **Do not call `createPractice`.** |
36
+ | none | First time | `call createPractice($me)`, then re-run and confirm exactly one. |
37
+ | more than one | Setup ran twice | **Stop.** Two practices split the history. Ask which to keep; `deletePractice` retires the other. |
38
+
39
+ ## Registering a repository
40
+
41
+ Inside the practice, find the repository whose current name matches the one you are adding.
42
+
43
+ ```
44
+ query repositoriesInPractice($practice)
45
+ ```
46
+
47
+ | Rows matching the name | What to do |
48
+ |---|---|
49
+ | exactly one | Already registered. **Do not call `registerGitHubRepository`.** |
50
+ | none | Read the numeric repository id from the host, then `call registerGitHubRepository($practice, $githubId, "owner/name")`. Re-run and confirm exactly one. |
51
+ | more than one | **Stop.** Two bindings for one repository split the history the same way two practices do. |
52
+
53
+ The numeric id is what survives a rename or a transfer. The name is a mutable property superseded through `prior`, which is why a rename uses `renameRepository` and never edits anything.
54
+
55
+ **`createPractice` and `registerGitHubRepository` are the only non-idempotent writes in this system.** Neither may ever sit in a retry or a fallback position. A shell `cmd-a || cmd-b` runs `cmd-b` when `cmd-a` merely prints something unexpected, and that second call is a real write, not a test.
56
+
57
+ ## References are session tokens, not identifiers
58
+
59
+ A `practiceRef`, a `repositoryRef` and a `nameRef` are scoped to the console that produced them. **Never write one into a configuration file.** Store the application title and the repository name, and re-resolve the references through `practicesForAdministrator` at the start of every run. A stored reference is a value derived from something else, and it goes stale silently.
@@ -0,0 +1,80 @@
1
+ # Creating the scheduled sessions
2
+
3
+ The night shift runs as scheduled Claude Code sessions: one coordinator on a cron schedule, and one worker per tracked repository that the coordinator fires on demand.
4
+
5
+ Each worker checks out the repository it works, because it builds, tests and pushes there. The coordinator's checkout is free, since it only reads and fires, so give it the repository that holds its own configuration rather than borrowing one of the tracked repositories. A coordinator that checks out a tracked repository reads that repository's copy of everything as if it were authoritative for all of them.
6
+
7
+ ## The routine table
8
+
9
+ The coordinator's repository carries `.night-shift/routines.md`: one row per session, with the session identifier, its role, its prompt file, the repository it checks out, the repository it targets, its token's environment variable name, and its schedule.
10
+
11
+ One table, not two. The coordinator reads the worker rows to know what to fire; a person reads every row to know what exists. Storing a session identifier in two places is how the two fall out of step.
12
+
13
+ The token *names* belong in the table. The tokens themselves belong in the session environment, never in a repository.
14
+
15
+ ## Prompts are loaders
16
+
17
+ A prompt names the skill and the configuration, and stops. Everything else is protocol, and protocol restated in a prompt is protocol that can disagree with the skill it duplicates. The disagreement will not surface until a run acts on the wrong half.
18
+
19
+ One worker prompt serves every worker session. Nothing in it is repository-specific: the checkout already names the repository, and everything that varies is in that repository's `.night-shift/config.md`.
20
+
21
+ **Coordinator:**
22
+
23
+ ```
24
+ You are the night-shift coordinator.
25
+
26
+ Read `.night-shift/routines.md` in this checkout. It lists the repositories to
27
+ sweep, the session to fire for each, and the environment variable holding that
28
+ session's token.
29
+
30
+ Then follow the night-shift-coordinator skill exactly. That skill is the
31
+ protocol. This prompt is not: where the two disagree, the skill wins, and say
32
+ so in your report.
33
+
34
+ Budget: <n> dispatches per sweep. State this number in every skip rationale
35
+ that leans on it, and in your report.
36
+
37
+ Do not poll the workers. End your turn once every fire has returned and been
38
+ recorded, and report what you dispatched, what you skipped and why.
39
+ ```
40
+
41
+ **Worker:**
42
+
43
+ ```
44
+ You are a night-shift worker.
45
+
46
+ The message you were fired with names one issue in this repository, and may
47
+ name a lower issue to stack on.
48
+
49
+ Read `.night-shift/config.md` in this checkout, then follow the
50
+ night-shift-worker skill exactly. That skill is the protocol. This prompt is
51
+ not: where the two disagree, the skill wins, and say so in your report.
52
+ ```
53
+
54
+ The budget belongs in the coordinator's prompt rather than in the skill, because it is an operator's choice about one night's capacity and not a property of the protocol. The skill's part is to require that the number be stated wherever a skip leans on it.
55
+
56
+ ## Tool access
57
+
58
+ The coordinator needs to read issues, pull requests and branches across every tracked repository, and to attach the repositories it does not check out. It needs the Factual MCP server for the log, and the ability to fire the worker sessions. It needs nothing that writes to a repository.
59
+
60
+ A worker needs the hosting API for issues and pull requests, the Factual MCP server, and permission to run `register-stack.sh` at its installed path. **When the script's path changes, the worker's allowed-tools list changes in the same edit.** A path that no longer matches does not error; the call is simply refused at whatever hour the run wakes, and the chain is silently left unregistered.
61
+
62
+ **Both roles need the harness's push-notification tool on their allowed-tools list.** A session sends that notification itself, so it does not depend on the routine's own completion-notification setting: the routine setting reports that a run finished, and the tool reports something from inside the run. They are separate mechanisms, and a routine whose completion notifications are off should still deliver one a session sends. **That last point is read from the tool contracts and has not been confirmed against a live run**, so confirm it on the first run below before you rely on it; a run whose only way of reporting an unreachable log is a notification that never arrives reports nothing at all.
63
+
64
+ ## Keeping prompts and files in step
65
+
66
+ The prompt files live in the coordinator's repository; the live prompts live in the routine API. They drift the moment one is edited without the other.
67
+
68
+ Sync in one direction only, from the files to the sessions, and make it a reviewed step rather than something a run does to itself:
69
+
70
+ 1. Read the live prompt.
71
+ 2. Archive it verbatim if no archived copy exists yet. That copy is the rollback.
72
+ 3. Compare against the file. Identical means nothing to do.
73
+ 4. Write the file's contents, with the tool list and the checkout, in one update.
74
+ 5. Read it back and confirm it matches. **If it does not, report the difference and stop. Never retry a write.**
75
+
76
+ ## First run
77
+
78
+ Fire the coordinator by hand, in daylight, appending `Dry run. Sweep and report; dispatch nothing.` Confirm it resolves every repository and reports a queue for each. Only then let the schedule run it unattended.
79
+
80
+ **Confirm the push notification on that same run**, by appending `Send a push notification saying the dry run started.` and watching for it to arrive. Do it with the routine's own completion notifications set the way you intend to leave them, because that is the combination the night shift will actually run in. If nothing arrives, the unreachable-log rule in `night-shift-log.md` has no way to reach anyone, and the tool list or the routine's settings need fixing before the schedule takes over.