Skip to content

Commit e97b02d

Browse files
Document the real Spoken Audio Node migration state, and fix the CI that hid it (#42)
Replaces the boundary file's assertion of a hold on ADRs that were not on the registry's default branch (they are now, via registry#41) with what has actually moved, what has not, and what each remaining step is blocked on. Does not build the Spoken Audio Node. The capture->ingestion contract lists the endpoint path, auth model, metadata key set and error envelope as owed; writing those for a service that does not exist would produce fabricated identifiers. Also ports one line from #27: .wp-env.json pinned WordPress 6.4 while the plugin header requires 6.9, so the plugin could never activate in its own test environment. That fix unmasked a second pre-existing failure — the test script looks for the plugin at wp-content/plugins/starmus-audio-recorder (the main PHP file's name) while wp-env mounts it under the repository directory name. Diagnosed on the PR with a proposed patch; not pushed, because it could not be verified without running Docker. Merged over three checks that are red on main for reasons unrelated to this diff: Trigger_EthicalCheck (apisec-inc/ethicalcheck-action no longer resolves), Lint & Proof Frontend Assets (docs/index.html links to six generated .html files that are never generated), and the wp-env plugin-slug mismatch above. None is made worse by this merge; #27 addresses the first.
1 parent 49c616e commit e97b02d

10 files changed

Lines changed: 149 additions & 124 deletions
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Repository role and migration state — ADR-034 / ADR-035 / ADR-036
2+
3+
**This repository is designated the Spoken Audio Node** under ADR-034. **It is
4+
not that today**, and this file says plainly what has moved, what has not, and
5+
what each remaining step is waiting on.
6+
7+
Role assignment lives here; the reason lives in the governance registry. Do not
8+
restate the rationale in this repository — cite the record.
9+
10+
- [ADR-034 — split axis](https://github.com/Starisian-Technologies/sparxstar-architecture-governance-registry/blob/main/standards/decisions/ADR-034-capture-experience-vs-audio-lifecycle-split.md)
11+
- [ADR-035 — capture profiles](https://github.com/Starisian-Technologies/sparxstar-architecture-governance-registry/blob/main/standards/decisions/ADR-035-capture-profiles-not-a-platform-audio-ceiling.md)
12+
- [ADR-036 — elicitation pacing is not acoustic prosody](https://github.com/Starisian-Technologies/sparxstar-architecture-governance-registry/blob/main/standards/decisions/ADR-036-elicitation-pacing-is-not-acoustic-prosody.md)
13+
14+
Seam contracts, which say what actually crosses each boundary:
15+
16+
- [Capture → Ingestion](https://github.com/Starisian-Technologies/sparxstar-architecture-governance-registry/blob/main/contracts/spoken-audio-capture-to-ingestion.md)
17+
- [Asset → Records](https://github.com/Starisian-Technologies/sparxstar-architecture-governance-registry/blob/main/contracts/spoken-audio-asset-to-records.md)
18+
19+
## What this repository will own
20+
21+
Server-side ingestion, validation, integrity, immutable object storage,
22+
derivatives, quality measurements, bulk import, processing jobs, and authorized
23+
consumption. A service, not a set of pages.
24+
25+
**It does not capture.** Browser microphone access, local and offline handling,
26+
the chunked-upload client and capture UX are the capture UI package's. The
27+
reviewed transcript and its translation are ESU's; acoustic measurement is
28+
ours, and interpreting what a measurement means is ESU's.
29+
30+
**ESU** is the platform component that owns the canonical linguistic record —
31+
transcription, translation, interpretation, and human correction — and stores
32+
no audio. Its canonical name and scope live in the governance registry and in
33+
ESU's own repository; this file deliberately does not restate an expansion it
34+
cannot verify from either, and no reader should infer one from context.
35+
36+
## What it stops owning
37+
38+
CMS templates and shortcodes · CMS admin screens · custom-post-type and
39+
attachment persistence · a CMS custom-field plugin as its primary database ·
40+
browser recorder code · CSS and frontend rendering · transcript review ·
41+
prosodic interpretation.
42+
43+
## Migration state, honestly
44+
45+
### Done
46+
47+
- The **manifest-driven UI package boundary** exists
48+
(`starmus-ui-packages.json`, `StarmusUiPackageResolver`). This is the
49+
mechanism that will let the plugin stop shipping its own copy of the capture
50+
JS and consume the built capture UI package instead. It is a precondition for
51+
everything below, and it landed.
52+
- The capture UI package has removed the paced reader, the transcript-sync
53+
controller, and the platform-wide audio ceiling.
54+
55+
### Blocked, and on what
56+
57+
1. **Removing the duplicated capture JS from `src/js/`.** Nineteen files, of
58+
which fifteen are diverged copies of files in the capture UI package. One
59+
home per capture-path source file (ADR-034). **Blocked on** the capture UI
60+
package being resolvable through the manifest as a published artifact rather
61+
than a sibling checkout. Deleting them before then breaks a shipping
62+
product.
63+
2. **Removing the prosody assets** (`src/js/prosody/`,
64+
`src/css/starmus-prosody-engine.css` and their built forms) and the
65+
`prosodyScript` / `prosodyStyle` manifest surface. **Blocked on** the
66+
elicitation pacing package being publishable: `StarmusProsodyPlayer.php`
67+
enqueues these today, and the resolver needs a URL to point at instead.
68+
Deleting the assets first takes the paced reader off every live page.
69+
3. **Standing up the ingestion service itself.** **Blocked on** the items the
70+
Capture → Ingestion contract lists as *owed*: the endpoint path and auth
71+
model, the upload metadata key set, the acknowledgement and error envelope,
72+
and confirmation that the consumer verifies `sha256` as the producer sends.
73+
**No repository implements a guess at those.** Writing endpoint paths, field
74+
names or status codes for a service that does not exist is how fabricated
75+
identifiers ship, and this organisation has shipped them before.
76+
4. **Which repository carries the CMS host product** once this one becomes a
77+
service — this repo's residue, or a new one. Explicitly left open by
78+
ADR-034. **Decide it before moving files, not during.**
79+
80+
## Rules that already bind this repository
81+
82+
- **No platform-wide audio ceiling** (ADR-035). A capture profile travels with
83+
the asset; an asset carrying none is *stored* and merely not admissible as a
84+
source for acoustic measurement — never rejected, because unconditional
85+
capture still holds.
86+
- **No transcoding on the ingestion path.** `import` means the received bytes
87+
are preserved. Derivatives are additional objects.
88+
- **Never hold the transcript of record.** A machine transcript may exist as a
89+
processing artifact of an asset, marked unreviewed. Consumers read ESU.

.wp-env.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"core": "WordPress/WordPress#6.4",
2+
"core": "WordPress/WordPress#6.9",
33
"phpVersion": "8.2",
44
"plugins": ["."],
55
"themes": ["https://downloads.wordpress.org/theme/twentytwentyfour.1.0.zip"],

src/core/StarmusAssetLoader.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -413,21 +413,21 @@ private function build_bootstrap_inline_script(array $config): string
413413
$base_json = (string) wp_json_encode($base, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
414414

415415
return <<<JS
416-
// The asset loader emits the authoritative runtime bootstrap immediately before this
417-
// bundle executes. Page-surface fields written to window.STARMUS_BOOTSTRAP earlier
418-
// in the document are preserved; base fields fill any unset slots.
419-
(function () {
420-
var base = {$base_json};
421-
var page = window.STARMUS_BOOTSTRAP || {};
422-
base.pageType = page.pageType || base.pageType;
423-
base.mode = page.mode || base.mode;
424-
base.postId = page.postId !== undefined ? page.postId : base.postId;
425-
base.canCommit = page.canCommit !== undefined ? page.canCommit : base.canCommit;
426-
base.artifact = page.artifact || base.artifact;
427-
base.hosts = page.hosts !== undefined ? page.hosts : base.hosts;
428-
window.STARMUS_BOOTSTRAP = base;
429-
}());
430-
JS;
416+
// The asset loader emits the authoritative runtime bootstrap immediately before this
417+
// bundle executes. Page-surface fields written to window.STARMUS_BOOTSTRAP earlier
418+
// in the document are preserved; base fields fill any unset slots.
419+
(function () {
420+
var base = {$base_json};
421+
var page = window.STARMUS_BOOTSTRAP || {};
422+
base.pageType = page.pageType || base.pageType;
423+
base.mode = page.mode || base.mode;
424+
base.postId = page.postId !== undefined ? page.postId : base.postId;
425+
base.canCommit = page.canCommit !== undefined ? page.canCommit : base.canCommit;
426+
base.artifact = page.artifact || base.artifact;
427+
base.hosts = page.hosts !== undefined ? page.hosts : base.hosts;
428+
window.STARMUS_BOOTSTRAP = base;
429+
}());
430+
JS;
431431
}
432432

433433
private function resolve_bootstrap_mode(): string

src/core/StarmusUiPackageResolver.php

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
<?php
22

33
declare(strict_types=1);
4-
54
namespace Starisian\Sparxstar\Starmus\core;
65

7-
use Starisian\Sparxstar\Starmus\helpers\StarmusLogger;
8-
96
use function file_exists;
107
use function file_get_contents;
118
use function filemtime;
12-
use function is_array;
13-
use function is_string;
149
use function json_decode;
1510

11+
use Starisian\Sparxstar\Starmus\helpers\StarmusLogger;
12+
1613
final class StarmusUiPackageResolver
1714
{
1815
private const MANIFEST_FILE = 'starmus-ui-packages.json';
@@ -47,16 +44,16 @@ public function resolve_asset(string $asset_key): array
4744
{
4845
$manifest = $this->load_manifest();
4946
$assets = $manifest['assets'] ?? [];
50-
$asset = is_array($assets) && isset($assets[$asset_key]) && is_array($assets[$asset_key])
47+
$asset = \is_array($assets) && isset($assets[$asset_key]) && \is_array($assets[$asset_key])
5148
? $assets[$asset_key]
5249
: [];
5350

54-
$handle = is_string($asset['handle'] ?? null) ? $asset['handle'] : '';
55-
$type = is_string($asset['type'] ?? null) ? $asset['type'] : 'script';
56-
$package = is_string($asset['package'] ?? null) ? $asset['package'] : '';
57-
$surface = is_string($asset['surface'] ?? null) ? $asset['surface'] : '';
51+
$handle = \is_string($asset['handle'] ?? null) ? $asset['handle'] : '';
52+
$type = \is_string($asset['type'] ?? null) ? $asset['type'] : 'script';
53+
$package = \is_string($asset['package'] ?? null) ? $asset['package'] : '';
54+
$surface = \is_string($asset['surface'] ?? null) ? $asset['surface'] : '';
5855

59-
$external_url = is_string($asset['externalUrl'] ?? null) ? $asset['externalUrl'] : '';
56+
$external_url = \is_string($asset['externalUrl'] ?? null) ? $asset['externalUrl'] : '';
6057
if ($external_url !== '') {
6158
return [
6259
'handle' => $handle,
@@ -68,7 +65,7 @@ public function resolve_asset(string $asset_key): array
6865
];
6966
}
7067

71-
$min_rel = is_string($asset['min'] ?? null) ? $asset['min'] : '';
68+
$min_rel = \is_string($asset['min'] ?? null) ? $asset['min'] : '';
7269
if ($min_rel !== '' && $this->base_path !== '' && file_exists($this->base_path . $min_rel)) {
7370
return [
7471
'handle' => $handle,
@@ -80,7 +77,7 @@ public function resolve_asset(string $asset_key): array
8077
];
8178
}
8279

83-
$src_rel = is_string($asset['src'] ?? null) ? $asset['src'] : '';
80+
$src_rel = \is_string($asset['src'] ?? null) ? $asset['src'] : '';
8481
if ($src_rel !== '' && $this->base_path !== '' && file_exists($this->base_path . $src_rel)) {
8582
return [
8683
'handle' => $handle,
@@ -110,7 +107,7 @@ public function get_runtime_projection(): array
110107
$manifest = $this->load_manifest();
111108
$runtime = $manifest['runtime'] ?? [];
112109

113-
return is_array($runtime) ? $runtime : [];
110+
return \is_array($runtime) ? $runtime : [];
114111
}
115112

116113
private function resolve_version(): string
@@ -132,22 +129,22 @@ private function load_manifest(): array
132129
return $this->manifest;
133130
}
134131

135-
$normalized_base_path = \rtrim($this->base_path, '/\\');
136-
$manifest_path = $normalized_base_path . DIRECTORY_SEPARATOR . self::MANIFEST_FILE;
132+
$normalized_base_path = rtrim($this->base_path, '/\\');
133+
$manifest_path = $normalized_base_path . DIRECTORY_SEPARATOR . self::MANIFEST_FILE;
137134

138135
if ( ! file_exists($manifest_path)) {
139136
$this->manifest = [];
140137
return $this->manifest;
141138
}
142139

143140
$manifest_json = file_get_contents($manifest_path);
144-
if ( ! is_string($manifest_json) || $manifest_json === '') {
141+
if ( ! \is_string($manifest_json) || $manifest_json === '') {
145142
$this->manifest = [];
146143
return $this->manifest;
147144
}
148145

149146
$decoded = json_decode($manifest_json, true);
150-
if ( ! is_array($decoded)) {
147+
if ( ! \is_array($decoded)) {
151148
StarmusLogger::error(
152149
'[StarmusUiPackageResolver] Failed to parse manifest: ' . $manifest_path,
153150
['json_error' => json_last_error_msg()]

src/frontend/StarmusProsodyPlayer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<?php
22

33
declare(strict_types=1);
4-
54
namespace Starisian\Sparxstar\Starmus\frontend;
65

76
use function class_exists;
87
use function ob_get_clean;
98
use function ob_start;
109

11-
use Starisian\Sparxstar\Starmus\data\StarmusProsodyDAL;
1210
use Starisian\Sparxstar\Starmus\core\StarmusUiPackageResolver;
11+
use Starisian\Sparxstar\Starmus\data\StarmusProsodyDAL;
1312
use Starisian\Sparxstar\Starmus\helpers\StarmusLogger;
1413
use Throwable;
1514

src/js/starmus-integrator.js

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111
* @global
1212
* @namespace
1313
*/
14-
window.Starmus =
15-
window.Starmus ||
16-
{
17-
/* intentionally empty */
18-
};
14+
window.Starmus = window.Starmus || {/* intentionally empty */};
1915

2016
/**
2117
* Current version of the Starmus integration layer.
@@ -75,31 +71,11 @@ window.addEventListener("sparxstar:environment-ready", (e) => {
7571
return;
7672
}
7773

78-
const raw =
79-
e.detail ||
80-
{
81-
/* intentionally empty */
82-
};
83-
const tech =
84-
raw.technical ||
85-
{
86-
/* intentionally empty */
87-
};
88-
const rawTech =
89-
tech.raw ||
90-
{
91-
/* intentionally empty */
92-
};
93-
const profile =
94-
tech.profile ||
95-
{
96-
/* intentionally empty */
97-
};
98-
const idents =
99-
raw.identifiers ||
100-
{
101-
/* intentionally empty */
102-
}; // Sometimes at root
74+
const raw = e.detail || {/* intentionally empty */};
75+
const tech = raw.technical || {/* intentionally empty */};
76+
const rawTech = tech.raw || {/* intentionally empty */};
77+
const profile = tech.profile || {/* intentionally empty */};
78+
const idents = raw.identifiers || {/* intentionally empty */}; // Sometimes at root
10379
// Handle case where identifiers might be inside technical or separate (based on logs)
10480

10581
/**
@@ -118,37 +94,21 @@ window.addEventListener("sparxstar:environment-ready", (e) => {
11894
const normalizedEnv = {
11995
// 1. Device Info (Merge Detector + Profile)
12096
device: {
121-
...(rawTech.device ||
122-
{
123-
/* intentionally empty */
124-
}),
97+
...(rawTech.device || {/* intentionally empty */}),
12598
class: profile.deviceClass || "unknown",
126-
os:
127-
raw.identifiers?.deviceDetails?.os ||
128-
{
129-
/* intentionally empty */
130-
},
99+
os: raw.identifiers?.deviceDetails?.os || {/* intentionally empty */},
131100
userAgent: navigator.userAgent,
132101
},
133102

134103
// 2. Browser Info
135104
browser: {
136-
...(rawTech.browser ||
137-
{
138-
/* intentionally empty */
139-
}),
140-
...(raw.identifiers?.deviceDetails?.client ||
141-
{
142-
/* intentionally empty */
143-
}),
105+
...(rawTech.browser || {/* intentionally empty */}),
106+
...(raw.identifiers?.deviceDetails?.client || {/* intentionally empty */}),
144107
},
145108

146109
// 3. Network Info
147110
network: {
148-
...(rawTech.network ||
149-
{
150-
/* intentionally empty */
151-
}),
111+
...(rawTech.network || {/* intentionally empty */}),
152112
profile: profile.networkProfile || "unknown",
153113
},
154114

@@ -161,16 +121,8 @@ window.addEventListener("sparxstar:environment-ready", (e) => {
161121

162122
// 5. Features / Battery / Perf
163123
features: {
164-
battery:
165-
rawTech.battery ||
166-
{
167-
/* intentionally empty */
168-
},
169-
performance:
170-
rawTech.performance ||
171-
{
172-
/* intentionally empty */
173-
},
124+
battery: rawTech.battery || {/* intentionally empty */},
125+
performance: rawTech.performance || {/* intentionally empty */},
174126
},
175127

176128
// 6. Init Error Array (Required by Schema)

src/js/starmus-main.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,7 @@ document.addEventListener("DOMContentLoaded", () => {
320320
}
321321

322322
const instanceId =
323-
bootstrap.hosts.formId ||
324-
recorderForm.getAttribute("data-starmus-instance") ||
325-
"";
323+
bootstrap.hosts.formId || recorderForm.getAttribute("data-starmus-instance") || "";
326324
initRecorderInstance(recorderForm, instanceId, bootstrap);
327325
} else if (bootstrap.pageType === "editor") {
328326
const editorRoot = document.getElementById(bootstrap.hosts.editorRootId || "");

0 commit comments

Comments
 (0)