@bongos/core 1.19.1035 → 1.19.1037
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/.bongos-core.json +102 -92
- package/.claude/skills/grade-recover/SKILL.md +1 -1
- package/clients/bongos-client/index.d.ts +1 -1
- package/docs/adr/0302-the-third-identical-failure-stops-the-session-and-asks.md +3 -2
- package/docs/adr/0329-the-rendered-fit-check-is-a-kit-floor-and-an-advisory-ship-check-row.md +2 -2
- package/docs/adr/0339-a-projects-owner-upgrades-it-and-a-hosted-project-hands-off-to-the-hub-door.md +84 -0
- package/docs/adr/README.md +2 -1
- package/docs/api/openapi.json +7 -5
- package/docs/copy-inventory.md +10 -10
- package/docs/copy-registry.json +13 -13
- package/docs/module-api-changelog.md +4 -0
- package/modules/economy/credits.js +1 -1
- package/modules/grading/grader-config.js +3 -12
- package/modules/grading/grader-no-artifact.js +227 -2
- package/modules/grading/grader-prompt.js +1 -1
- package/modules/grading/grader-rubric.json +1 -86
- package/modules/grading/grader-score.js +1 -169
- package/modules/grading/grader-subagent.js +1 -51
- package/modules/grading/grader.js +26 -211
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/fleet.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell.js +36 -5
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/lifecycle/db-ship.js +3 -3
- package/modules/provisioning/core-upgrade-authz.js +85 -0
- package/modules/provisioning/core-upgrade.js +2 -1
- package/modules/provisioning/provisioning.js +4 -4
- package/modules/provisioning/routes/core-upgrade.js +12 -6
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +20 -0
- package/scripts/gds/claim.js +2 -1
- package/scripts/gds/grade-smoke.js +3 -3
- package/scripts/gds/provision-core-upgrade.js +12 -4
- package/scripts/gds/render-check.js +1 -1
- package/scripts/gds/ship-check.js +1 -1
- package/scripts/gds/ship-flow.js +1 -1
- package/scripts/gds/ship-grade-steps.js +2 -2
- package/scripts/gds/visual-review-nudge.js +2 -1
- package/src/bongos/auth.js +8 -2
- package/src/bongos/routes/core-update.js +25 -3
- package/src/module-api.js +1 -1
- package/tests/adr_0162_gate_citation.mjs +167 -0
- package/tests/core_upgrade_owner_door.mjs +444 -0
- package/tests/grader.mjs +48 -126
- package/tests/grader_unbacked_score.mjs +1 -1
- package/tests/nav_permission_atoms.mjs +1 -1
- package/tests/provisioning_teardown_intent.mjs +28 -2
- package/tests/regrade_actual_minutes.mjs +18 -17
- package/tests/render_check.mjs +1 -1
- package/tests/scouting_page_gate.mjs +11 -3
- package/tests/skill_grade_audit.mjs +3 -3
- package/tests/skill_grader_health.mjs +2 -2
- package/scripts/gds/audit-ships.js +0 -319
- package/tests/audit_ships_git_argv.mjs +0 -173
|
@@ -75,23 +75,28 @@
|
|
|
75
75
|
// module (which receives it via dependency injection to avoid a circular
|
|
76
76
|
// require).
|
|
77
77
|
//
|
|
78
|
-
// ##
|
|
78
|
+
// ## Retired (task 1002842)
|
|
79
79
|
//
|
|
80
|
-
//
|
|
81
|
-
// scripts/gds/audit-ships.js
|
|
80
|
+
// The v1 deterministic process-audit grader (gradeDeterministic and its nine
|
|
81
|
+
// per-criterion scorers) and its one caller, scripts/gds/audit-ships.js, are
|
|
82
|
+
// deleted: the live panel grades every ship at ship time, so a retroactive
|
|
83
|
+
// heuristic audit has nothing left to cover. aggregateShots / runOneShot moved
|
|
84
|
+
// to grader-no-artifact.js, the species that depends on them; they are still
|
|
85
|
+
// re-exported here, and the trivial-diff fast path below still runs one shot.
|
|
82
86
|
|
|
83
87
|
const path = require('node:path');
|
|
84
88
|
const fs = require('node:fs');
|
|
85
89
|
const { spawn } = require('node:child_process');
|
|
86
90
|
|
|
87
|
-
const { ASSUMED_BUILDER_MODEL, DEFAULT_GRADER_MODEL,
|
|
91
|
+
const { ASSUMED_BUILDER_MODEL, DEFAULT_GRADER_MODEL, FALLTHROUGH_CONFIDENCE, RUBRIC, THRESHOLD, VERSION, generatedProvenance, permissionPathPrePass, routeRankPrePass, workers } = require('./grader-config.js');
|
|
88
92
|
const { clamp, isTrivialDiff, median, r1, selectGraderModel, workerModelFor } = require('./grader-model.js');
|
|
89
93
|
const { buildPrompt, extractJson } = require('./grader-prompt.js');
|
|
90
94
|
// task 1004011: the second grade species — a grade over the CLAIM on an
|
|
91
95
|
// --allow-empty ship, where there is no diff for the panel above to read.
|
|
92
|
-
|
|
93
|
-
const {
|
|
94
|
-
const {
|
|
96
|
+
// task 1002842: the generalist-shot plumbing now lives there too.
|
|
97
|
+
const { GRADER_KIND: NO_ARTIFACT_GRADER_KIND, aggregateShots, buildNoArtifactPrompt, gradeNoArtifact, runOneShot } = require('./grader-no-artifact.js');
|
|
98
|
+
const { changeMagnitude, hasPanelEvidence, isSubstantiveIssue, serverSideGuards, validateAndScore } = require('./grader-score.js');
|
|
99
|
+
const { buildContextBundle, diffAddedLinesByFile, extractAssistantResult, extractCostUsd, runSubagent, runSubagentCached } = require('./grader-subagent.js');
|
|
95
100
|
// task 1002903: the severity gate's unbacked low scores, named once for the record.
|
|
96
101
|
const { unbackedLowScores } = require('./grader-workers/worker-verdict.js');
|
|
97
102
|
// task 1002839: the central engine the code panel below registers into (ADR 0089 §1).
|
|
@@ -478,8 +483,8 @@ function aggregatePanel(workerResults, meta = {}) {
|
|
|
478
483
|
grader_version: VERSION,
|
|
479
484
|
// #486: the panel's own API spend (USD), for cost_log (source=grader).
|
|
480
485
|
panel_cost_usd: panelCostUsd,
|
|
481
|
-
// rubric_scores keep the v3 keys so the trend dashboard
|
|
482
|
-
//
|
|
486
|
+
// rubric_scores keep the v3 keys so the trend dashboard and the server's
|
|
487
|
+
// validateAndScore re-validation continue to read them. Phase 2.1 added
|
|
483
488
|
// security_score; Phase 2.2 adds efficiency_score. Both additive —
|
|
484
489
|
// consumers that don't know about them just ignore the fields.
|
|
485
490
|
rubric_scores: {
|
|
@@ -651,12 +656,17 @@ async function gradeSubagent({ task, valueSummary, diff, changedFiles, diffStats
|
|
|
651
656
|
});
|
|
652
657
|
}
|
|
653
658
|
|
|
654
|
-
// ----------
|
|
659
|
+
// ---------- the trivial-diff fast path (#513) ----------
|
|
655
660
|
//
|
|
656
|
-
//
|
|
657
|
-
// (
|
|
658
|
-
//
|
|
659
|
-
|
|
661
|
+
// A small copy/docs-only diff gets ONE generalist shot instead of the four-worker
|
|
662
|
+
// panel — "lighter, not skipped" (ADR 0089 §7 keeps it). The name is historical:
|
|
663
|
+
// the v3 multi-shot GENERATION is retired (task 1002842 removed its 3-shot default
|
|
664
|
+
// and rubric block), and this is what is left of it — the working fast path.
|
|
665
|
+
// Moving it onto a v4 panel needs a reviewer type that reports both
|
|
666
|
+
// functional_fidelity and code_quality, which no v4 worker does; that is a cost
|
|
667
|
+
// and behaviour decision, not a cleanup. `runShot` is a test seam defaulted to
|
|
668
|
+
// the real spawner (the same pattern as gradeNoArtifact); production passes none.
|
|
669
|
+
async function gradeSubagentV3MultiShot({ task, valueSummary, diff, changedFiles, diffStats, shots = 1, builderModel, runOpts = {}, runShot = runOneShot }) {
|
|
660
670
|
const prompt = buildPrompt({ task, valueSummary, diff, changedFiles, diffStats, generatedProvenance: await generatedProvenance.verifyGeneratedProvenanceAsync({ changedFiles, cwd: runOpts.cwd }) }); // task 1002795
|
|
661
671
|
const graderModel = selectGraderModel({ builderModel });
|
|
662
672
|
const N = Math.max(1, Math.trunc(shots));
|
|
@@ -664,7 +674,7 @@ async function gradeSubagentV3MultiShot({ task, valueSummary, diff, changedFiles
|
|
|
664
674
|
const startedAt = Date.now();
|
|
665
675
|
const shotPromises = [];
|
|
666
676
|
for (let i = 0; i < N; i++) {
|
|
667
|
-
shotPromises.push(
|
|
677
|
+
shotPromises.push(runShot({ prompt, model: graderModel, shotIndex: i, runOpts }));
|
|
668
678
|
}
|
|
669
679
|
const shotResults = await Promise.all(shotPromises);
|
|
670
680
|
const totalMs = Date.now() - startedAt;
|
|
@@ -676,189 +686,6 @@ async function gradeSubagentV3MultiShot({ task, valueSummary, diff, changedFiles
|
|
|
676
686
|
});
|
|
677
687
|
}
|
|
678
688
|
|
|
679
|
-
// =========================================================================
|
|
680
|
-
// Legacy v1 (deterministic) — kept for scripts/gds/audit-ships.js only.
|
|
681
|
-
// =========================================================================
|
|
682
|
-
|
|
683
|
-
function scoreEstActualBand(actualMinutes, estMinutes) {
|
|
684
|
-
if (!Number.isFinite(actualMinutes) || actualMinutes <= 0) return 5;
|
|
685
|
-
if (!Number.isFinite(estMinutes) || estMinutes <= 0) return 6;
|
|
686
|
-
const ratio = actualMinutes / estMinutes;
|
|
687
|
-
if (ratio >= 0.5 && ratio <= 2.0) return 10;
|
|
688
|
-
if (ratio < 0.5) {
|
|
689
|
-
if (ratio <= 0.1) return 0;
|
|
690
|
-
return r1(10 * ((ratio - 0.1) / 0.4));
|
|
691
|
-
}
|
|
692
|
-
if (ratio > 2.0) {
|
|
693
|
-
if (ratio >= 10) return 0;
|
|
694
|
-
return r1(10 * (1 - (ratio - 2.0) / 8.0));
|
|
695
|
-
}
|
|
696
|
-
return 5;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
function scoreValueSummary(valueSummary) {
|
|
700
|
-
const s = (valueSummary || '').trim();
|
|
701
|
-
if (s.length === 0) return 0;
|
|
702
|
-
if (s.length < 40) return 5;
|
|
703
|
-
if (s.length < 120) return 8;
|
|
704
|
-
return /\b(add|fix|update|remove|refactor|wire|land|migrate|enable|disable|introduce|deprecate|ship|deploy|prevent|capture|gate|allocate|carry|expose|surface)\b/i.test(s)
|
|
705
|
-
? 10
|
|
706
|
-
: 8;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
function scoreDiffHygiene(diffStats) {
|
|
710
|
-
if (!diffStats) return 5;
|
|
711
|
-
const files = Number(diffStats.files_changed) || 0;
|
|
712
|
-
const added = Number(diffStats.lines_added) || 0;
|
|
713
|
-
const removed = Number(diffStats.lines_removed) || 0;
|
|
714
|
-
if (files === 0 || added + removed === 0) return 0;
|
|
715
|
-
if (files > 50) return 5;
|
|
716
|
-
return 10;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function scoreScannerSmoke(verification) {
|
|
720
|
-
if (!verification) return 5;
|
|
721
|
-
return verification.scanner_clean && verification.smoke_clean ? 10 : 5;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function scoreScopingSignal(scopingConfidence) {
|
|
725
|
-
if (scopingConfidence == null) return 6;
|
|
726
|
-
const c = Number(scopingConfidence);
|
|
727
|
-
if (c <= 0) return 2;
|
|
728
|
-
if (c === 1) return 4;
|
|
729
|
-
if (c === 2) return 6;
|
|
730
|
-
if (c === 3) return 7;
|
|
731
|
-
if (c === 4) return 8;
|
|
732
|
-
return 10;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
function scoreLocNetNegative(diffStats) {
|
|
736
|
-
if (!diffStats) return 5;
|
|
737
|
-
const added = Number(diffStats.lines_added) || 0;
|
|
738
|
-
const removed = Number(diffStats.lines_removed) || 0;
|
|
739
|
-
if (removed > added) return 10;
|
|
740
|
-
if (removed === added) return 5;
|
|
741
|
-
return 0;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
function scoreLearningRow(learningRow) {
|
|
745
|
-
if (!learningRow) return 0;
|
|
746
|
-
const body = (learningRow.body_md || '').trim();
|
|
747
|
-
if (body.length > 100) return 10;
|
|
748
|
-
if (body.length > 0) return 5;
|
|
749
|
-
return 0;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
function scoreArtRubricAvg(value) {
|
|
753
|
-
if (!Number.isFinite(value)) return null;
|
|
754
|
-
return clamp(r1(value), 0, 10);
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
function blendWeightsForKind(kind) {
|
|
758
|
-
const blended = {};
|
|
759
|
-
for (const [name, def] of Object.entries(V1.weights.common)) {
|
|
760
|
-
blended[name] = def.weight;
|
|
761
|
-
}
|
|
762
|
-
const kindBonus = V1.weights.kind_specific[kind];
|
|
763
|
-
if (kindBonus) {
|
|
764
|
-
for (const [name, def] of Object.entries(kindBonus)) {
|
|
765
|
-
if (name === 'loc_net_negative' && 'diff_hygiene' in blended) delete blended.diff_hygiene;
|
|
766
|
-
if (name === 'learning_row' && 'diff_hygiene' in blended) delete blended.diff_hygiene;
|
|
767
|
-
blended[name] = def.weight;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
const total = Object.values(blended).reduce((a, b) => a + b, 0);
|
|
771
|
-
for (const k of Object.keys(blended)) blended[k] = blended[k] / total;
|
|
772
|
-
return blended;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
// Legacy v1 entry. Renamed from `grade()` in V3.R18 (#209). Now ONLY
|
|
776
|
-
// called from scripts/gds/audit-ships.js (retroactive #204 audit). The
|
|
777
|
-
// runtime ship path uses gradeSubagent (v3 multi-shot).
|
|
778
|
-
function gradeDeterministic({ task, verification, actualMinutes, valueSummary, learningRow }) {
|
|
779
|
-
const kind = task?.kind || 'unclassified';
|
|
780
|
-
const weights = blendWeightsForKind(kind);
|
|
781
|
-
const rubricScores = {};
|
|
782
|
-
const signals = {
|
|
783
|
-
kind,
|
|
784
|
-
est_minutes: task?.est_minutes ?? null,
|
|
785
|
-
actual_minutes: actualMinutes ?? null,
|
|
786
|
-
scoping_confidence: task?.scoping_confidence ?? null,
|
|
787
|
-
scanner_clean: verification?.scanner_clean ?? null,
|
|
788
|
-
smoke_clean: verification?.smoke_clean ?? null,
|
|
789
|
-
diff_stats: verification?.diff_stats ?? null,
|
|
790
|
-
art_rubric_avg: verification?.art_rubric_avg ?? null,
|
|
791
|
-
value_summary_chars: (valueSummary || '').trim().length,
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
if ('est_actual_band' in weights) {
|
|
795
|
-
rubricScores.est_actual_band = scoreEstActualBand(actualMinutes, task?.est_minutes);
|
|
796
|
-
}
|
|
797
|
-
if ('value_summary' in weights) {
|
|
798
|
-
rubricScores.value_summary = scoreValueSummary(valueSummary);
|
|
799
|
-
}
|
|
800
|
-
if ('diff_hygiene' in weights) {
|
|
801
|
-
rubricScores.diff_hygiene = scoreDiffHygiene(verification?.diff_stats);
|
|
802
|
-
}
|
|
803
|
-
if ('scanner_smoke' in weights) {
|
|
804
|
-
rubricScores.scanner_smoke = scoreScannerSmoke(verification);
|
|
805
|
-
}
|
|
806
|
-
if ('scoping_signal' in weights) {
|
|
807
|
-
rubricScores.scoping_signal = scoreScopingSignal(task?.scoping_confidence);
|
|
808
|
-
}
|
|
809
|
-
if ('loc_net_negative' in weights) {
|
|
810
|
-
rubricScores.loc_net_negative = scoreLocNetNegative(verification?.diff_stats);
|
|
811
|
-
}
|
|
812
|
-
if ('learning_row' in weights) {
|
|
813
|
-
rubricScores.learning_row = scoreLearningRow(learningRow);
|
|
814
|
-
}
|
|
815
|
-
if ('art_rubric_avg' in weights) {
|
|
816
|
-
const s = scoreArtRubricAvg(verification?.art_rubric_avg);
|
|
817
|
-
if (s == null) {
|
|
818
|
-
const w = weights.art_rubric_avg;
|
|
819
|
-
delete weights.art_rubric_avg;
|
|
820
|
-
const remaining = Object.values(weights).reduce((a, b) => a + b, 0);
|
|
821
|
-
if (remaining > 0) {
|
|
822
|
-
for (const k of Object.keys(weights)) weights[k] = weights[k] / remaining;
|
|
823
|
-
}
|
|
824
|
-
} else {
|
|
825
|
-
rubricScores.art_rubric_avg = s;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
let score = 0;
|
|
830
|
-
for (const [name, w] of Object.entries(weights)) {
|
|
831
|
-
if (rubricScores[name] != null) score += rubricScores[name] * w;
|
|
832
|
-
}
|
|
833
|
-
score = r1(clamp(score, 0, 10));
|
|
834
|
-
|
|
835
|
-
const threshold = V1.threshold;
|
|
836
|
-
const passed = score >= threshold;
|
|
837
|
-
|
|
838
|
-
const lines = [];
|
|
839
|
-
lines.push(`Auto-grader ${V1.version} (deprecated) — task_kind=${kind}.`);
|
|
840
|
-
lines.push(`Score ${score}/10 vs threshold ${threshold} → ${passed ? 'PASS' : 'FAIL'}.`);
|
|
841
|
-
lines.push('');
|
|
842
|
-
lines.push('Per-criterion:');
|
|
843
|
-
for (const [name, w] of Object.entries(weights)) {
|
|
844
|
-
const s = rubricScores[name];
|
|
845
|
-
if (s == null) continue;
|
|
846
|
-
const contrib = r1(s * w);
|
|
847
|
-
lines.push(` - ${name.padEnd(20)} ${String(s).padStart(4)}/10 × ${w.toFixed(2)} = ${contrib}`);
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
return {
|
|
851
|
-
score,
|
|
852
|
-
passed,
|
|
853
|
-
threshold,
|
|
854
|
-
grader_kind: 'auto',
|
|
855
|
-
grader_version: V1.version,
|
|
856
|
-
rubric_scores: rubricScores,
|
|
857
|
-
signals,
|
|
858
|
-
notes_md: lines.join('\n'),
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
|
|
862
689
|
module.exports = {
|
|
863
690
|
// v4 surface (active panel-based gate)
|
|
864
691
|
aggregatePanel,
|
|
@@ -888,25 +715,13 @@ module.exports = {
|
|
|
888
715
|
runSubagent,
|
|
889
716
|
runSubagentCached, // System 5 (task 1359): opt-in content-addressed cached path
|
|
890
717
|
runOneShot,
|
|
891
|
-
gradeSubagentV3MultiShot, //
|
|
718
|
+
gradeSubagentV3MultiShot, // the trivial-diff fast path (#513) — one generalist shot
|
|
892
719
|
extractJson,
|
|
893
720
|
extractAssistantResult,
|
|
894
721
|
extractCostUsd, // #486: parse total_cost_usd from the envelope
|
|
895
722
|
THRESHOLD,
|
|
896
723
|
VERSION,
|
|
897
724
|
DEFAULT_GRADER_MODEL,
|
|
898
|
-
DEFAULT_SHOTS,
|
|
899
725
|
ASSUMED_BUILDER_MODEL,
|
|
900
|
-
// legacy v1 (audit-ships.js only)
|
|
901
|
-
gradeDeterministic,
|
|
902
|
-
scoreEstActualBand,
|
|
903
|
-
scoreValueSummary,
|
|
904
|
-
scoreDiffHygiene,
|
|
905
|
-
scoreScannerSmoke,
|
|
906
|
-
scoreScopingSignal,
|
|
907
|
-
scoreLocNetNegative,
|
|
908
|
-
scoreLearningRow,
|
|
909
|
-
scoreArtRubricAvg,
|
|
910
|
-
blendWeightsForKind,
|
|
911
726
|
RUBRIC,
|
|
912
727
|
};
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
|
|
92
92
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
93
93
|
|
|
94
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
94
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
95
95
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
96
96
|
<script src="/builders/palette.js" defer></script>
|
|
97
97
|
<script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
54
54
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
55
55
|
<script src="/builders/palette.js" defer></script>
|
|
56
56
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
62
62
|
|
|
63
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
63
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
64
64
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
65
65
|
<script src="/builders/palette.js" defer></script>
|
|
66
66
|
<script src="/builders/dom-utils.js?v=2026-06-16-board"></script>
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
|
|
149
149
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
150
150
|
|
|
151
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
151
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
152
152
|
<script src="/builders/palette.js" defer></script>
|
|
153
153
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
154
154
|
<script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
|
|
178
178
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
179
179
|
|
|
180
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
180
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
181
181
|
<script src="/builders/palette.js" defer></script>
|
|
182
182
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
183
183
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
62
62
|
|
|
63
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
63
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
64
64
|
<script src="/builders/palette.js" defer></script>
|
|
65
65
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
66
66
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
99
99
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
100
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
100
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
101
101
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
102
102
|
<script src="/builders/palette.js" defer></script>
|
|
103
103
|
<script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
|
|
99
99
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
100
100
|
|
|
101
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
101
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
102
102
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
103
103
|
<script src="/builders/palette.js" defer></script>
|
|
104
104
|
<script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
56
|
|
|
57
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
57
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
58
58
|
<script src="/builders/palette.js" defer></script>
|
|
59
59
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
60
60
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
<div id="gate-modal-root"></div>
|
|
77
77
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
78
78
|
|
|
79
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
79
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
80
80
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
81
81
|
<script src="/builders/palette.js" defer></script>
|
|
82
82
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -235,7 +235,7 @@
|
|
|
235
235
|
|
|
236
236
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
237
237
|
|
|
238
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
238
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
239
239
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
240
240
|
<script src="/builders/palette.js" defer></script>
|
|
241
241
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
|
|
135
135
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
136
136
|
|
|
137
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
137
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
138
138
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
139
139
|
<script src="/builders/palette.js" defer></script>
|
|
140
140
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
54
54
|
|
|
55
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
55
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
56
56
|
<script src="/builders/palette.js" defer></script>
|
|
57
57
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
|
|
58
58
|
<!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
|
|
226
226
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
227
227
|
|
|
228
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
228
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
229
229
|
<script src="/builders/palette.js" defer></script>
|
|
230
230
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
231
231
|
<!-- task 1003069 (R08) — the quick-filing form's routed result links a task
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75" defer></script>
|
|
103
103
|
<!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
|
|
104
104
|
BEFORE builders.js so the chrome ids exist when events are wired. -->
|
|
105
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
105
|
+
<script src="/builders/shell.js?v=2026-09-26-own1" defer></script>
|
|
106
106
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
107
107
|
<script src="/builders/palette.js" defer></script>
|
|
108
108
|
<!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
82
82
|
|
|
83
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
83
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
84
84
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
85
85
|
<script src="/builders/palette.js" defer></script>
|
|
86
86
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
|
|
67
67
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
68
68
|
chrome exists before the page script runs. -->
|
|
69
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
69
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
70
70
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
71
71
|
<script src="/builders/palette.js" defer></script>
|
|
72
72
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
|
|
116
116
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
117
117
|
|
|
118
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
118
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
119
119
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
120
120
|
<script src="/builders/palette.js" defer></script>
|
|
121
121
|
<!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
|
|
188
188
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
189
189
|
chrome exists before the page script runs. -->
|
|
190
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
190
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
191
191
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
192
192
|
<script src="/builders/palette.js" defer></script>
|
|
193
193
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
60
60
|
|
|
61
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
61
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
62
62
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
63
63
|
<script src="/builders/palette.js" defer></script>
|
|
64
64
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
|
|
69
69
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
70
70
|
chrome exists before the page script runs. -->
|
|
71
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
71
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
72
72
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
73
73
|
<script src="/builders/palette.js" defer></script>
|
|
74
74
|
<!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
43
|
|
|
44
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
44
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
45
45
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
46
46
|
<script src="/builders/palette.js" defer></script>
|
|
47
47
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
54
54
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
55
55
|
<script src="/builders/palette.js" defer></script>
|
|
56
56
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
101
101
|
chrome exists before the page script runs. -->
|
|
102
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
102
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
103
103
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
104
104
|
<script src="/builders/palette.js" defer></script>
|
|
105
105
|
<!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
|
|
@@ -416,7 +416,7 @@
|
|
|
416
416
|
|
|
417
417
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
418
418
|
chrome exists before the page scripts run. -->
|
|
419
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
419
|
+
<script src="/builders/shell.js?v=2026-09-26-own1"></script>
|
|
420
420
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
421
421
|
<script src="/builders/palette.js" defer></script>
|
|
422
422
|
<!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
|
|
@@ -344,7 +344,12 @@
|
|
|
344
344
|
// The deploy door (task 1003159, ADR 0293). Gated 'archon' here to mirror the
|
|
345
345
|
// `core.pin.move` atom its page and both its routes check — cosmetic only, as
|
|
346
346
|
// every item in this list is; the wall is server-side.
|
|
347
|
-
|
|
347
|
+
//
|
|
348
|
+
// THE DOOR IS THE PROVISIONING MODULE'S, and a hosted project does not run it, so
|
|
349
|
+
// there this link opened a page with nothing behind it (task 1004174). It is
|
|
350
|
+
// dropped where the module is off, and re-pointed at the hub's own door for THIS
|
|
351
|
+
// project once /core-update names one (pointDeployAtHub, ADR 0339).
|
|
352
|
+
{ id: 'deploy', label: 'Deploy', icon: 'admin', href: '/deploy', gate: 'archon', module: 'provisioning' },
|
|
348
353
|
// task 1001949: what each hosted project costs. 'government' mirrors the metic floor
|
|
349
354
|
// of `provisioning.fleet.manage`, the atom its page and its one read check (the
|
|
350
355
|
// Deploy precedent above); dropped where the provisioning module is not enabled.
|
|
@@ -622,16 +627,40 @@
|
|
|
622
627
|
if (!perms || perms['core.pin.move'] !== true) return;
|
|
623
628
|
coreUpdateAsked = true;
|
|
624
629
|
api.request('GET', '/api/bongos/core-update').then(function (res) {
|
|
625
|
-
if (!res || res.status !== 200 || !res.data
|
|
626
|
-
|
|
630
|
+
if (!res || res.status !== 200 || !res.data) return;
|
|
631
|
+
var handoff = hubHandoff(res.data.deploy_url);
|
|
632
|
+
if (handoff) pointDeployAtHub(handoff);
|
|
633
|
+
if (res.data.update) renderCoreUpdateBanner(res.data.update, handoff);
|
|
627
634
|
}, function () { /* fail-soft: no banner is the correct answer to no answer */ });
|
|
628
635
|
}
|
|
629
636
|
|
|
637
|
+
// task 1004174 (ADR 0339) — where a HOSTED project's owner takes the upgrade: the
|
|
638
|
+
// hub's own deploy door scoped to this project, which the server names as
|
|
639
|
+
// `deploy_url` when this project is federated with a hub. Only where this hall has no
|
|
640
|
+
// door of its own: on the platform the local /deploy is the door, and a link away
|
|
641
|
+
// from it would be a second road to the same button. An address that is not a plain
|
|
642
|
+
// http(s) URL is ignored rather than trusted into an href.
|
|
643
|
+
function hubHandoff(url) {
|
|
644
|
+
if (moduleOn('provisioning')) return null;
|
|
645
|
+
if (typeof url !== 'string' || !/^https?:\/\/[^\s"'<>]+$/i.test(url)) return null;
|
|
646
|
+
return url;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// The rail's Deploy item is hidden on a hosted project (its module gate); this gives
|
|
650
|
+
// it back, aimed at the hub. Its rank gate still applies, exactly as on the platform.
|
|
651
|
+
function pointDeployAtHub(url) {
|
|
652
|
+
var item = document.getElementById('nav-deploy');
|
|
653
|
+
if (!item) return;
|
|
654
|
+
item.setAttribute('href', url);
|
|
655
|
+
if (item.dataset) delete item.dataset.module;
|
|
656
|
+
item.hidden = !gateAllows(item.dataset && item.dataset.gate);
|
|
657
|
+
}
|
|
658
|
+
|
|
630
659
|
// SAY NOTHING WHEN THERE IS NOTHING TO SAY. `behind` is false both when the box
|
|
631
660
|
// is current AND when the registry could not be read; `reading` separates them,
|
|
632
661
|
// and neither renders. A banner is a claim about being out of date, and a wrong
|
|
633
662
|
// one on a project that is actually current is worse than silence.
|
|
634
|
-
function renderCoreUpdateBanner(update) {
|
|
663
|
+
function renderCoreUpdateBanner(update, handoff) {
|
|
635
664
|
if (!update || update.reading !== 'ok' || !update.behind || !update.latest) return;
|
|
636
665
|
// A dismissal is remembered PER VERSION, not forever: the next release is new
|
|
637
666
|
// news and must re-announce itself, or the surface is dead after one click.
|
|
@@ -659,8 +688,10 @@
|
|
|
659
688
|
// happen": nothing had, and nothing had been asked for. The control is on that page
|
|
660
689
|
// already, so on it the banner informs and points, and does not pretend to act.
|
|
661
690
|
var onDeploy = window.location && String(window.location.pathname || '').replace(/\/+$/, '') === '/deploy';
|
|
691
|
+
// A hosted project has no door of its own; it hands its owner to the hub's door for
|
|
692
|
+
// this project when the server named one (task 1004174), and otherwise only informs.
|
|
662
693
|
var action = !moduleOn('provisioning')
|
|
663
|
-
? ''
|
|
694
|
+
? (handoff ? '<a class="core-update-notice__action" href="' + esc(handoff) + '">Upgrade</a>' : '')
|
|
664
695
|
: (onDeploy
|
|
665
696
|
? '<span class="core-update-notice__hint">Use the control below to take it.</span>'
|
|
666
697
|
: '<a class="core-update-notice__action" href="/deploy">Upgrade</a>');
|