clearotron 0.4.0-beta.1 → 0.4.0-beta.2
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/INSTALL.md +4 -31
- package/README.md +5 -5
- package/bin/brandowner.mjs +1 -1
- package/bin/onboard.mjs +18 -74
- package/bin/start.mjs +58 -14
- package/bin/update.mjs +4 -1
- package/build-info.json +2 -2
- package/demo/full-country-search/run/_driver/search-policy.json +1 -1
- package/demo/full-country-search/run/status.json +1 -1
- package/demo/global-preliminary-search/run/_driver/search-policy.json +1 -1
- package/demo/global-preliminary-search/run/status.json +1 -1
- package/demo/knockout-search/run/_driver/search-policy.json +1 -1
- package/demo/knockout-search/run/status.json +1 -1
- package/demo/multi-country-focus-search/run/_driver/search-policy.json +1 -1
- package/demo/multi-country-focus-search/run/status.json +1 -1
- package/docs/README.md +1 -0
- package/docs/SECURITY-OWASP.md +298 -0
- package/docs/SECURITY.md +18 -13
- package/docs/architecture/02-architecture.md +5 -5
- package/docs/architecture/03-run-lifecycle.md +28 -29
- package/docs/architecture/04-configuration-reference.md +3 -4
- package/docs/architecture/05-config-governance.md +5 -7
- package/docs/architecture/06-operations-runbook.md +0 -12
- package/docs/architecture/07-quality-and-audit.md +12 -13
- package/docs/architecture/09-security-and-data.md +9 -4
- package/driver/CHANGELOG.md +60 -0
- package/driver/ask-ledger.mjs +2 -0
- package/driver/authority-trees.mjs +90 -8
- package/driver/band-shape.mjs +5 -5
- package/driver/case-law-ledger.mjs +19 -3
- package/driver/claim-liveness.mjs +30 -1
- package/driver/clearance-variants-record.mjs +10 -3
- package/driver/common-law-receipts.mjs +62 -12
- package/driver/commonlaw-carry.mjs +1 -1
- package/driver/compare.mjs +2 -2
- package/driver/connotation-search.mjs +30 -101
- package/driver/contract-arm2-baseline.json +6 -5
- package/driver/contract-e3-backlog.mjs +60 -60
- package/driver/contract-vocabulary.mjs +38 -31
- package/driver/coverage-form-io.mjs +13 -1
- package/driver/coverage-form.mjs +42 -4
- package/driver/coverage-ledger.mjs +3 -5
- package/driver/cross-check-wait.mjs +43 -0
- package/driver/declination-call.mjs +33 -9
- package/driver/declination-tool.mjs +27 -15
- package/driver/deferral-row.mjs +139 -0
- package/driver/degraded-parts.mjs +377 -0
- package/driver/deliver-trigger.sh +1 -1
- package/driver/demo-container.mjs +4 -1
- package/driver/dev-portal.mjs +4 -4
- package/driver/dispatch-record.mjs +2 -2
- package/driver/driver.config.mjs +177 -87
- package/driver/effective-scope.mjs +58 -2
- package/driver/engine/anthropic-agent.mjs +103 -27
- package/driver/engine/auth.mjs +2 -2
- package/driver/engine/child-record.mjs +11 -0
- package/driver/engine/cli-version.mjs +4 -3
- package/driver/engine/common.mjs +17 -2
- package/driver/engine/deny-authority-write.mjs +3 -1
- package/driver/engine/engine-env.mjs +174 -0
- package/driver/engine/engine-spawn.mjs +179 -0
- package/driver/engine/mcp/band-server.mjs +1 -1
- package/driver/engine/mcp/codex-config.mjs +112 -3
- package/driver/engine/mcp/declination-server.mjs +9 -8
- package/driver/engine/mcp/dispositions-server.mjs +2 -1
- package/driver/engine/mcp/fetch-server.mjs +14 -11
- package/driver/engine/mcp/gather-config.mjs +22 -10
- package/driver/engine/mcp/perplexity-server.mjs +96 -16
- package/driver/engine/mcp/probe-server.mjs +43 -21
- package/driver/engine/mcp/public-fetch.mjs +195 -0
- package/driver/engine/mcp/recording-server.mjs +78 -13
- package/driver/engine/mcp/supplemental.mjs +13 -13
- package/driver/engine/mcp/unit-note-server.mjs +50 -1
- package/driver/engine/openai-agent.mjs +109 -28
- package/driver/engine/probe.mjs +152 -19
- package/driver/enqueue-schema.mjs +3 -3
- package/driver/findings-model.mjs +64 -13
- package/driver/floor-duty.mjs +21 -5
- package/driver/form-neighbourhood.mjs +5 -2
- package/driver/framework-method.mjs +304 -0
- package/driver/gateway.mjs +44 -16
- package/driver/hand-off-exits.mjs +129 -0
- package/driver/jx.mjs +8 -5
- package/driver/knockout-assess-record.mjs +7 -1
- package/driver/knockout-frame-record.mjs +96 -34
- package/driver/knockout-review-record.mjs +7 -2
- package/driver/matter-frame-record.mjs +31 -2
- package/driver/methodology-witness.mjs +6 -3
- package/driver/named-band.mjs +1 -1
- package/driver/owner-use-check.mjs +45 -10
- package/driver/package.json +1 -1
- package/driver/partial-payload-baseline.json +4 -0
- package/driver/phase0.mjs +2 -2
- package/driver/pipeline-knockout.mjs +128 -35
- package/driver/pipeline.mjs +373 -598
- package/driver/placement-carry.mjs +20 -1
- package/driver/placement-form-io.mjs +18 -4
- package/driver/placement-form.mjs +52 -3
- package/driver/placement-union.mjs +32 -5
- package/driver/portal-report.mjs +3 -3
- package/driver/portal-service.mjs +4 -3
- package/driver/portal-static.mjs +11 -18
- package/driver/profile-page.html +5 -5
- package/driver/profiles.mjs +5 -5
- package/driver/progress.mjs +5 -3
- package/driver/provider-usage.mjs +1 -1
- package/driver/publish/index.mjs +94 -22
- package/driver/publish/knockout.mjs +133 -12
- package/driver/publish/profiles-page.mjs +2 -0
- package/driver/publish/publish-inputs.mjs +10 -4
- package/driver/publish/render-knockout.mjs +47 -20
- package/driver/publish/render.mjs +12 -7
- package/driver/publish/report-data.mjs +2 -0
- package/driver/publish/search-depth.mjs +77 -4
- package/driver/publish/templates/report.css +1 -1
- package/driver/publish/xlsx.mjs +34 -15
- package/driver/reasoning-tripwires.mjs +2 -160
- package/driver/recall-receipt.mjs +27 -0
- package/driver/record-carry.mjs +8 -8
- package/driver/reference-score.mjs +142 -20
- package/driver/register-count.mjs +5 -3
- package/driver/register-digest-record.mjs +13 -0
- package/driver/register-plan.mjs +156 -75
- package/driver/register-records.mjs +27 -3
- package/driver/registration-scripts.mjs +22 -0
- package/driver/repair-composers.mjs +19 -3
- package/driver/repair-contract.mjs +1 -1
- package/driver/repairs.mjs +5 -2
- package/driver/reviewer-open-points.mjs +33 -0
- package/driver/rule-shape.mjs +8 -8
- package/driver/run-economics.mjs +2 -2
- package/driver/run-integrity.mjs +2 -2
- package/driver/runner.mjs +17 -5
- package/driver/scope-facts.mjs +89 -12
- package/driver/score-redaction.mjs +247 -0
- package/driver/search-policy.mjs +17 -0
- package/driver/skills/README.md +2 -2
- package/driver/skills/clearance-common-law/SKILL.md +29 -36
- package/driver/skills/clearance-common-law/perplexity-prompts.md +5 -27
- package/driver/skills/clearance-register/SKILL.md +15 -16
- package/driver/skills/clearance-register/digest.md +14 -30
- package/driver/skills/clearance-register/register-recipes.md +14 -56
- package/driver/skills/clearance-register/unit.md +36 -47
- package/driver/skills/clearance-search/SKILL.md +6 -8
- package/driver/skills/clearance-search/delivery-contract.md +0 -7
- package/driver/skills/clearance-search/firm-wide-reasoning.md +5 -4
- package/driver/skills/clearance-search/phase2-execution.md +5 -6
- package/driver/skills/clearance-search/risk-framework-triage.md +2 -2
- package/driver/skills/clearance-search/synthesis-rules.md +5 -5
- package/driver/skills/clearance-search/template-formatting.md +2 -2
- package/driver/skills/clearance-variants/SKILL.md +6 -6
- package/driver/skills/clearance-variants/transliteration-scripts.md +1 -1
- package/driver/skills/knockout-assess/SKILL.md +31 -1
- package/driver/skills/knockout-frame/SKILL.md +42 -10
- package/driver/skills/matter-frame/SKILL.md +12 -5
- package/driver/skills/narrative-refutation/SKILL.md +3 -1
- package/driver/skills/placement-inquiry/SKILL.md +4 -0
- package/driver/stage-context.mjs +23 -2
- package/driver/stages-knockout.mjs +92 -79
- package/driver/stages.mjs +88 -53
- package/driver/stray-artifacts.mjs +9 -5
- package/driver/suite-census.json +620 -140
- package/driver/synthesis-record.mjs +26 -4
- package/driver/systemd/README.md +5 -6
- package/driver/systemd/clearotron-worker.service +6 -1
- package/driver/tokens.mjs +2 -2
- package/driver/unit-inventory.mjs +21 -40
- package/driver/variant-manifest-model.mjs +21 -2
- package/driver/verify-knockout.mjs +163 -4
- package/driver/verify.mjs +40 -14
- package/driver/web-grid.mjs +150 -0
- package/driver/withheld-families.mjs +113 -4
- package/driver/worker-heartbeat.mjs +13 -2
- package/mcp-server/CHANGELOG.md +4 -0
- package/mcp-server/README.md +1 -1
- package/mcp-server/lib/knockout.mjs +1 -1
- package/mcp-server/lib/ops.mjs +10 -10
- package/mcp-server/lib/scrub.mjs +1 -1
- package/mcp-server/lib/trace.mjs +3 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/server.mjs +2 -2
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-D_O_55vK.js → index-BPAUjcI0.js} +1 -1
- package/portal-ui/dist/assets/{index-5CCwiJG7.css → index-D2wrw9cH.css} +18 -2
- package/portal-ui/dist/assets/plus-jakarta-sans-BUCHxqJ-.woff2 +0 -0
- package/portal-ui/dist/index.html +2 -15
- package/portal-ui/package.json +1 -1
- package/providers/_shared/enumerate.mjs +155 -50
- package/providers/_shared/execute-plan.mjs +62 -16
- package/providers/_shared/ledger.mjs +1 -1
- package/providers/_shared/plan-guards.mjs +7 -0
- package/providers/clarivate/src/core.js +54 -6
- package/providers/corsearch/README.md +1 -2
- package/providers/corsearch/src/core.js +2 -2
- package/providers/oauth-mcp-bridge/CHANGELOG.md +4 -0
- package/providers/oauth-mcp-bridge/README.md +8 -7
- package/providers/oauth-mcp-bridge/bridge.mjs +21 -5
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/oauth-mcp-bridge/systemd/courtlistener-mcp.service +1 -1
- package/providers/oauth-mcp-bridge/warm-server.mjs +16 -5
- package/providers/perplexity/src/core.js +246 -21
- package/providers/signa/src/core.js +27 -25
- package/scripts/README.md +2 -1
- package/scripts/added-reference-check.mjs +2 -1
- package/scripts/backup-recall-stores.mjs +5 -5
- package/scripts/demo-evidence.mjs +2 -1
- package/scripts/drive-env-check.mjs +2 -1
- package/scripts/e2e-first-time.mjs +469 -0
- package/scripts/e2e-scenario-ops.mjs +441 -0
- package/scripts/e2e.mjs +104 -16
- package/scripts/env-audit.mjs +8 -0
- package/scripts/freeze-example-run.mjs +7 -7
- package/scripts/generated-files-are-current.mjs +2 -1
- package/scripts/hand-off-exits-probe.mjs +75 -0
- package/scripts/import-cycle-check.mjs +2 -1
- package/scripts/merge-shape-check.mjs +2 -1
- package/scripts/package-size-budget.mjs +2 -1
- package/scripts/record-carry-probe.mjs +1 -1
- package/scripts/release-install-check.mjs +4 -1
- package/scripts/release-note-required.mjs +44 -10
- package/scripts/render-check.mjs +5 -2
- package/scripts/report-offline-render-check.mjs +169 -0
- package/scripts/score.mjs +76 -5
- package/scripts/strip-titles-and-attributions.mjs +2 -1
- package/scripts/strip-tracker-citations.mjs +2 -1
- package/scripts/test-full.mjs +2 -1
- package/scripts/test-run.mjs +10 -3
- package/scripts/third-party-notices.mjs +3 -1
- package/scripts/travelling-predicates.mjs +1 -1
- package/scripts/writing-standard-check.mjs +2 -1
- package/shared/brand-fonts.mjs +59 -0
- package/shared/brand.mjs +5 -5
- package/shared/browser-temp-root.mjs +3 -2
- package/shared/doctrine-overlay.mjs +1 -1
- package/shared/driver-dir.mjs +27 -2
- package/shared/fonts/OFL-fira-code.txt +93 -0
- package/shared/fonts/OFL-plus-jakarta-sans.txt +93 -0
- package/shared/fonts/README.md +37 -0
- package/shared/fonts/fira-code.woff2 +0 -0
- package/shared/fonts/plus-jakarta-sans.woff2 +0 -0
- package/shared/npm-cli.mjs +23 -0
- package/shared/os-advice.mjs +14 -2
- package/shared/path-seps.mjs +42 -0
- package/shared/process-table.mjs +71 -3
- package/shared/reference-guard-classes.mjs +30 -6
- package/shared/root-doc-commands.mjs +6 -2
- package/shared/running-start.mjs +24 -7
- package/shared/scope.mjs +2 -2
- package/shared/wsl.mjs +1 -1
- package/driver/known-conflicts.mjs +0 -345
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2014-2020 The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The Plus Jakarta Sans Project Authors (https://github.com/tokotype/PlusJakartaSans)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Fonts
|
|
2
|
+
|
|
3
|
+
The two typefaces every report, pool index and portal page is set in. They ship inside the package, and
|
|
4
|
+
each report carries them inside its own file, so opening a report fetches nothing from anywhere.
|
|
5
|
+
|
|
6
|
+
| File | Typeface | Licence |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `plus-jakarta-sans.woff2` | Plus Jakarta Sans, the text face, weights 200–800 | SIL Open Font License 1.1, [`OFL-plus-jakarta-sans.txt`](OFL-plus-jakarta-sans.txt) |
|
|
9
|
+
| `fira-code.woff2` | Fira Code, the code face, weights 300–700 | SIL Open Font License 1.1, [`OFL-fira-code.txt`](OFL-fira-code.txt) |
|
|
10
|
+
|
|
11
|
+
Neither licence reserves a font name, so these subsets keep their names.
|
|
12
|
+
|
|
13
|
+
## Where they come from
|
|
14
|
+
|
|
15
|
+
Each file is a subset of the variable font in the [google/fonts](https://github.com/google/fonts)
|
|
16
|
+
repository:
|
|
17
|
+
|
|
18
|
+
| File | Source | Last upstream commit to that folder | sha256 of the source file |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| `plus-jakarta-sans.woff2` | `ofl/plusjakartasans/PlusJakartaSans[wght].ttf` | `8b0a1d0f5983c89bc2b93f1b5fb55f9e252744b5` | `89b3fb38aa0d275d7a731d0d817a4f1622b316b4d7fbdedcf02ee9099ff68bc8` |
|
|
21
|
+
| `fira-code.woff2` | `ofl/firacode/FiraCode[wght].ttf` | `5020a98352f1909554697e1da4132da253727138` | `9335b082b3c7850d98a64b584f3417f65355f3471278bb5eeb8c6c0e8657aeeb` |
|
|
22
|
+
|
|
23
|
+
The licence files are that repository's `OFL.txt` for each family.
|
|
24
|
+
|
|
25
|
+
The subset keeps the Latin and Latin Extended ranges Google Fonts serves, plus the four arrows U+2190–2193,
|
|
26
|
+
which the reports use and Google's Latin range leaves out. It keeps every layout feature, the whole
|
|
27
|
+
weight axis and every name record, so the copyright and licence notices stay inside each file. Made with
|
|
28
|
+
fonttools 4.65.0:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pyftsubset <source>.ttf --flavor=woff2 --layout-features='*' --name-IDs='*' --name-languages='*' \
|
|
32
|
+
--name-legacy --notdef-outline --output-file=<file>.woff2 \
|
|
33
|
+
--unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2190-2193,U+2212,U+2215,U+FEFF,U+FFFD,U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A character outside that set, such as Japanese or Greek, is drawn by the reader's own system fonts, as it
|
|
37
|
+
was before these files existed.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
3
|
+
// npm-cli.mjs — HOW TO RUN NPM WITHOUT A SHELL, on every platform.
|
|
4
|
+
//
|
|
5
|
+
// ON WINDOWS NPM IS A BATCH FILE. `npm` there is `npm.cmd`, and Node refuses to start a batch file without
|
|
6
|
+
// a shell (EINVAL, since the 2024 fix for batch-file argument injection). A shell is no way round it here:
|
|
7
|
+
// the engine install passes `<package>@>=<floor>`, and cmd.exe reads that `>` as a redirection into a file.
|
|
8
|
+
// npm itself is a Node program, `npm-cli.js`, so on Windows it runs through the Node running now: the one
|
|
9
|
+
// npm named when it launched this process, else the one beside `node.exe`, which is where Node's own
|
|
10
|
+
// Windows installer puts it. Elsewhere `npm` is run as it always was.
|
|
11
|
+
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { win32 } from "node:path";
|
|
14
|
+
|
|
15
|
+
/** The command and arguments that run npm with `args`: `{command, args}`. `platform` is a parameter so the Windows branch runs on a Linux CI. */
|
|
16
|
+
export function npmInvocation(args = [], { platform = process.platform, env = process.env, execPath = process.execPath, exists = existsSync } = {}) {
|
|
17
|
+
if (platform !== "win32") return { command: "npm", args };
|
|
18
|
+
const named = String(env.npm_execpath ?? "");
|
|
19
|
+
if (/npm-cli\.js$/i.test(named) && exists(named)) return { command: execPath, args: [named, ...args] };
|
|
20
|
+
const beside = win32.join(win32.dirname(execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
21
|
+
if (exists(beside)) return { command: execPath, args: [beside, ...args] };
|
|
22
|
+
return { command: "npm", args };
|
|
23
|
+
}
|
package/shared/os-advice.mjs
CHANGED
|
@@ -85,7 +85,19 @@ export const chdirPrefix = (dir, { platform = process.platform } = {}) =>
|
|
|
85
85
|
*
|
|
86
86
|
* `null` where this platform has no such mechanism in the product, so a caller prints nothing rather
|
|
87
87
|
* than naming a service manager the reader does not have. Windows was told the background form was
|
|
88
|
-
* "managed by systemd", which is not on the machine and cannot be installed onto it
|
|
88
|
+
* "managed by systemd", which is not on the machine and cannot be installed onto it, and a Mac was told
|
|
89
|
+
* the same: `--background` installs systemd units, and of the platforms the product runs on only Linux
|
|
90
|
+
* has systemd.
|
|
89
91
|
*/
|
|
90
92
|
export const backgroundManager = ({ platform = process.platform } = {}) =>
|
|
91
|
-
(
|
|
93
|
+
(platform === "linux" ? "systemd" : null);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* What `start --background` answers on Windows, where it has nothing to install: the background form is
|
|
97
|
+
* systemd units, and Windows has no systemd. Printed as it stands and nothing else, before `start` writes
|
|
98
|
+
* anything or calls systemctl (owner's ruling, 2026-09-23). `null` elsewhere. Asked of Windows by name
|
|
99
|
+
* rather than of `backgroundManager`, which answers `null` on other machines too, and a Mac must not be
|
|
100
|
+
* told it is Windows.
|
|
101
|
+
*/
|
|
102
|
+
export const backgroundRefusal = ({ platform = process.platform } = {}) =>
|
|
103
|
+
(isWindows(platform) ? "Background mode isn't available on Windows. Run `clearotron start` and keep its window open." : null);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
3
|
+
// path-seps.mjs — THE SEPARATOR A PATH WAS BUILT WITH, for code that reads a path with a regex.
|
|
4
|
+
//
|
|
5
|
+
// `join` builds a path with the platform's own separator: "/" on Linux and macOS, "\" on Windows. A regex
|
|
6
|
+
// written against "/" matches nothing on Windows, so the reader that holds it says "not a run directory"
|
|
7
|
+
// or "no agent" about a path that is both, and the grid tool refused every full clearance that way.
|
|
8
|
+
//
|
|
9
|
+
// WINDOWS ACCEPTS BOTH, so both are separators there. On Linux and macOS "\" is an ordinary filename
|
|
10
|
+
// character, so it stays one: the class is chosen from the platform, and a Linux path reads exactly as it
|
|
11
|
+
// did before this file existed. `platform` is a parameter so the Windows branch runs on a Linux CI.
|
|
12
|
+
|
|
13
|
+
import { STUDIO_SEGMENT_RE } from "./pre-rename-spellings.mjs";
|
|
14
|
+
|
|
15
|
+
/** A regex source matching one path separator on `platform`. */
|
|
16
|
+
export function sepClass(platform = process.platform) {
|
|
17
|
+
return platform === "win32" ? "[\\\\/]" : "/";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A regex source matching one character that is not a path separator on `platform`. */
|
|
21
|
+
export function notSepClass(platform = process.platform) {
|
|
22
|
+
return platform === "win32" ? "[^\\\\/]" : "[^/]";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Everything after the last separator: the file's own name. */
|
|
26
|
+
export function lastSegment(p, platform = process.platform) {
|
|
27
|
+
const s = String(p ?? "");
|
|
28
|
+
const cut = platform === "win32" ? Math.max(s.lastIndexOf("/"), s.lastIndexOf("\\")) : s.lastIndexOf("/");
|
|
29
|
+
return s.slice(cut + 1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Does the path hold a separator at all, as opposed to being a bare name? */
|
|
33
|
+
export function hasSep(p, platform = process.platform) {
|
|
34
|
+
const s = String(p ?? "");
|
|
35
|
+
return s.includes("/") || (platform === "win32" && s.includes("\\"));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Is `p` inside a run directory: somewhere under `…/studio/<either segment spelling>/`? */
|
|
39
|
+
export function underStudioSegment(p, platform = process.platform) {
|
|
40
|
+
const S = sepClass(platform);
|
|
41
|
+
return new RegExp(`${S}studio${S}${STUDIO_SEGMENT_RE}${S}`).test(String(p ?? ""));
|
|
42
|
+
}
|
package/shared/process-table.mjs
CHANGED
|
@@ -55,10 +55,19 @@ import { spawnSync } from "node:child_process";
|
|
|
55
55
|
* how a portability fix ships broken on the platform it was written for.
|
|
56
56
|
*/
|
|
57
57
|
export function processTable({ platform = process.platform, runPs = defaultRunPs,
|
|
58
|
-
everyUser = false, uid = currentUid() } = {}) {
|
|
59
|
-
const all = platform === "linux" ? fromProc() : fromPs(runPs);
|
|
58
|
+
runPowerShell = defaultRunPowerShell, everyUser = false, uid = currentUid(), selfPid = process.pid } = {}) {
|
|
59
|
+
const all = platform === "linux" ? fromProc() : platform === "win32" ? fromWindows(runPowerShell) : fromPs(runPs);
|
|
60
60
|
if (all == null) return null; // could not look, and that survives the filter
|
|
61
61
|
if (everyUser) return all;
|
|
62
|
+
// WINDOWS HAS NO UID, so "this user's own" is asked of the logon SESSION instead: each user signed in
|
|
63
|
+
// to a machine has their own, and services run in session 0. It is the nearest thing Windows answers
|
|
64
|
+
// without an administrator, and it keeps doctor off another account's programs, which is the second
|
|
65
|
+
// half of the contract above. A listing that does not hold this process cannot say which session is
|
|
66
|
+
// ours, so it is returned whole, as the no-uid case below returns it.
|
|
67
|
+
if (platform === "win32") {
|
|
68
|
+
const me = all.find((p) => p.pid === selfPid);
|
|
69
|
+
return me && me.session != null ? all.filter((p) => p.session === me.session) : all;
|
|
70
|
+
}
|
|
62
71
|
// A box with no uid to compare against (a platform with no getuid) cannot answer "is this mine", and
|
|
63
72
|
// guessing would hand back either everything or nothing. Everything is the honest one: the caller
|
|
64
73
|
// gets what it always got, and the row carries `uid: null` so it can see the question was unanswered.
|
|
@@ -119,7 +128,66 @@ function fromPs(runPs) {
|
|
|
119
128
|
return out.length ? out : null;
|
|
120
129
|
}
|
|
121
130
|
|
|
131
|
+
// ── WINDOWS: THE SAME CONTRACT, READ THROUGH POWERSHELL ─────────────────────────────────────────────────
|
|
132
|
+
//
|
|
133
|
+
// Windows has neither /proc nor ps. What it has on every supported version, with no administrator, is
|
|
134
|
+
// Windows PowerShell and the process list it reads from the system (Win32_Process). One row per process,
|
|
135
|
+
// fields separated by "|", the command line last because it is the only field that can hold a "|".
|
|
136
|
+
//
|
|
137
|
+
// THE START TIME IS PRINTED AS A NUMBER, never as a date: PowerShell writes dates in the machine's own
|
|
138
|
+
// locale, and a parse of that would read one day as another on half the machines it met. `ToFileTimeUtc`
|
|
139
|
+
// is the count of 100-nanosecond ticks since 1601, the same on every machine, and `windowsTicksToMs`
|
|
140
|
+
// turns it into the epoch milliseconds the rest of this file uses.
|
|
141
|
+
//
|
|
142
|
+
// The script holds no double quote, so no rule about quoting an argument can change what PowerShell
|
|
143
|
+
// receives. The output encoding is asked for inside a try: a machine locked to PowerShell's constrained
|
|
144
|
+
// mode refuses that line, and only a command line with non-ASCII characters in it suffers for it.
|
|
145
|
+
export function windowsProcessScript(pid = null) {
|
|
146
|
+
const only = Number.isInteger(pid) && pid > 0 ? ` -Filter 'ProcessId=${pid}'` : "";
|
|
147
|
+
return "try { [Console]::OutputEncoding = [Text.Encoding]::UTF8 } catch {}; "
|
|
148
|
+
+ `Get-CimInstance Win32_Process${only} | ForEach-Object { $c = $_.CreationDate; `
|
|
149
|
+
+ "'{0}|{1}|{2}|{3}|{4}' -f $_.ProcessId, $_.ParentProcessId, $(if ($c) { $c.ToFileTimeUtc() } else { '' }), "
|
|
150
|
+
+ "$_.SessionId, ($_.CommandLine -replace '\\s+', ' ') }";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Windows file time (100 ns ticks since 1601-01-01 UTC) to epoch milliseconds; NaN for anything else. */
|
|
154
|
+
export function windowsTicksToMs(ticks) {
|
|
155
|
+
const t = String(ticks ?? "").trim();
|
|
156
|
+
if (!/^\d{15,19}$/.test(t)) return NaN;
|
|
157
|
+
return Number((BigInt(t) - 116444736000000000n) / 10000n);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The rows `windowsProcessScript` printed: `{pid, ppid, startedAt, session, cmd}`. Unparseable lines are skipped. */
|
|
161
|
+
export function parseWindowsRows(stdout) {
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const line of String(stdout ?? "").split(/\r?\n/)) {
|
|
164
|
+
const m = /^(\d+)\|(\d*)\|(\d*)\|(\d*)\|(.*)$/.exec(line.trim());
|
|
165
|
+
if (!m) continue;
|
|
166
|
+
out.push({ pid: Number(m[1]), ppid: m[2] === "" ? null : Number(m[2]), startedAt: windowsTicksToMs(m[3]),
|
|
167
|
+
session: m[4] === "" ? null : Number(m[4]), uid: null, cmd: m[5].trim() });
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Windows: every process, or null when PowerShell could not be run or printed nothing it could parse. */
|
|
173
|
+
function fromWindows(runPowerShell) {
|
|
174
|
+
const r = runPowerShell(windowsProcessScript());
|
|
175
|
+
if (!r || r.status !== 0 || typeof r.stdout !== "string") return null;
|
|
176
|
+
const out = parseWindowsRows(r.stdout);
|
|
177
|
+
// As for `ps`: this process is in the listing, so an empty parse is an instrument that broke.
|
|
178
|
+
return out.length ? out : null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Run one PowerShell script and capture what it prints. `windowsHide` because this is started from the
|
|
183
|
+
* portal and the worker many times an hour, and a console program started by a process without a
|
|
184
|
+
* console of its own opens a window.
|
|
185
|
+
*/
|
|
186
|
+
const defaultRunPowerShell = (script) =>
|
|
187
|
+
spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script],
|
|
188
|
+
{ encoding: "utf8", windowsHide: true, timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
|
|
189
|
+
|
|
122
190
|
const defaultRunPs = () =>
|
|
123
191
|
spawnSync("ps", ["-Ao", "pid=,uid=,lstart=,command="], { encoding: "utf8", maxBuffer: 8 * 1024 * 1024 });
|
|
124
192
|
|
|
125
|
-
export { defaultRunPs };
|
|
193
|
+
export { defaultRunPs, defaultRunPowerShell };
|
|
@@ -39,12 +39,21 @@
|
|
|
39
39
|
// `deploy` IS A SKILL NAME AND IS NOT BANNED, for the same reason. It is an ordinary English word and a
|
|
40
40
|
// paragraph about deploying would be refused line by line.
|
|
41
41
|
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// every run directory. 49 lines
|
|
46
|
-
//
|
|
47
|
-
//
|
|
42
|
+
// THE PRODUCT'S FORMER DEFAULT AGENT ID IS NOW BANNED, and the reason it was not is worth keeping
|
|
43
|
+
// because it was a good one. It was the id an install ran as: it named a setting in the install
|
|
44
|
+
// instructions, in the configuration reference and in the operations runbook, and it was a path segment
|
|
45
|
+
// in every run directory. 49 lines carried it in that sense. A guard refusing it would have refused the
|
|
46
|
+
// install instructions a stranger reads first, so it was left alone and the reason written down.
|
|
47
|
+
//
|
|
48
|
+
// Ruling 563 (2026-09-27) took every functional use of it out of the product, and the ban is the closing
|
|
49
|
+
// step: without it the id comes back and nothing says so. The class is below, and its pattern is the only
|
|
50
|
+
// place in this tree that spells it — a `pattern:` line is code, and this guard reads comments and
|
|
51
|
+
// markdown, never code, so the class does not refuse its own definition.
|
|
52
|
+
//
|
|
53
|
+
// WHAT THE BAN DOES NOT DISTURB. This check is diff-shaped: what a change ADDS is refused, and what is
|
|
54
|
+
// already here is not its business. Two lines still carry the id on purpose — a record of a measurement
|
|
55
|
+
// taken over archived runs, and a captured error message from a real incident — and neither is refused,
|
|
56
|
+
// because neither is added by anything. That is the mechanism, not an exemption list to maintain.
|
|
48
57
|
|
|
49
58
|
import { execFileSync } from "node:child_process";
|
|
50
59
|
import { CUT_RECORD_PRESENT, isWithheld } from "./withheld-paths-access.mjs";
|
|
@@ -157,6 +166,21 @@ export const CLASSES = [
|
|
|
157
166
|
+ "not. A reader outside this project cannot open the number. Say why the code is as it is; put "
|
|
158
167
|
+ "the citation in the commit message or the pull request body.",
|
|
159
168
|
},
|
|
169
|
+
{
|
|
170
|
+
// NOT A NAME THIS PROJECT USES FOR HOW IT IS BUILT — it is an identifier the product SHIPPED, which is
|
|
171
|
+
// why it is banned only now that it ships nowhere. The remedy is the same as the login class's: say
|
|
172
|
+
// what the thing is for, not what it was called.
|
|
173
|
+
id: "retired-agent-id",
|
|
174
|
+
// NO WORD BOUNDARIES, and that is deliberate. `\b` does not match before an underscore, so a
|
|
175
|
+
// boundaried pattern let every prefixed spelling of the id through — a setting name carrying it as a
|
|
176
|
+
// prefix read as clean, which is the shape a returning identifier actually takes. The id is a coined
|
|
177
|
+
// word, so an unanchored match has no innocent population to refuse.
|
|
178
|
+
pattern: /clawdi/i,
|
|
179
|
+
why: "the agent id this product used to default to. It was a path segment in every run directory and "
|
|
180
|
+
+ "named in the install instructions until it was taken out of the product; a new line carrying it "
|
|
181
|
+
+ "is either residue or a reference to a different product. Name the setting that holds the agent, "
|
|
182
|
+
+ "or the install's own default, rather than one particular value of it.",
|
|
183
|
+
},
|
|
160
184
|
{
|
|
161
185
|
id: "login",
|
|
162
186
|
pattern: /\b(?:testuser|azureuser|devuser)[0-9]*\b/i,
|
|
@@ -39,7 +39,7 @@ export const NPX = /npx clearotron [a-z]/g;
|
|
|
39
39
|
* fresh `npx`, which resolves whichever channel npm picks at that moment — the stable, for a reader who
|
|
40
40
|
* installed the beta (owner ruling, 2026-09-18).
|
|
41
41
|
*/
|
|
42
|
-
export const GLOBAL_INSTALL = /npm install
|
|
42
|
+
export const GLOBAL_INSTALL = /npm install (?:-g|--global) clearotron|npx clearotron(?:@[\w.-]+)? install\b/;
|
|
43
43
|
/** The paragraph that is ABOUT the shim, where the short form is the point. */
|
|
44
44
|
export const SHIM_PARAGRAPH = /short form|on your `PATH`|stop typing/;
|
|
45
45
|
|
|
@@ -53,6 +53,9 @@ export function commandSites(file, text) {
|
|
|
53
53
|
const lines = String(text ?? "").split("\n");
|
|
54
54
|
const installedAt = lines.findIndex((l) => GLOBAL_INSTALL.test(l));
|
|
55
55
|
const globalFrom = installedAt === -1 ? Infinity : installedAt + 1;
|
|
56
|
+
// A sentence can install and then use the command on one line ("`npm install --global clearotron`, then
|
|
57
|
+
// `clearotron install`"): a bare site on the install's own line counts as after it when it comes later.
|
|
58
|
+
const installCol = installedAt === -1 ? Infinity : lines[installedAt].search(GLOBAL_INSTALL);
|
|
56
59
|
const para = [];
|
|
57
60
|
let n = 0;
|
|
58
61
|
for (const line of lines) { if (line.trim() === "") n++; para.push(n); }
|
|
@@ -60,7 +63,8 @@ export function commandSites(file, text) {
|
|
|
60
63
|
const bare = [], npx = [];
|
|
61
64
|
lines.forEach((line, i) => {
|
|
62
65
|
if (BARE.test(line)) {
|
|
63
|
-
|
|
66
|
+
const afterGlobalInstall = i + 1 > globalFrom || (i === installedAt && line.search(BARE) > installCol);
|
|
67
|
+
bare.push({ file, line: i + 1, text: line.trim(), paragraph: textOf(para[i]), afterGlobalInstall });
|
|
64
68
|
}
|
|
65
69
|
npx.push(...(line.match(NPX) ?? []).map(() => ({ file, line: i + 1 })));
|
|
66
70
|
});
|
package/shared/running-start.mjs
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
// record whose process is gone is read as absent, and `status` asks the portal itself before saying the
|
|
14
14
|
// product is up. Three answers, all honest: up; started but not answering; not running.
|
|
15
15
|
|
|
16
|
-
import { mkdirSync, readdirSync, readFileSync, renameSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { homedir } from "node:os";
|
|
18
|
-
import { dirname, join } from "node:path";
|
|
18
|
+
import { dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Where the records live: one file per serving process, beside the settings and the revocation list.
|
|
@@ -34,6 +34,20 @@ export function pidAlive(pid) {
|
|
|
34
34
|
try { process.kill(pid, 0); return true; } catch (e) { return e?.code === "EPERM"; }
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** `dir` and its parents up to and including `made`, deepest first; [] when `dir` is not inside `made`. */
|
|
38
|
+
export function madeChain(dir, made, { realpath = realpathSync.native } = {}) {
|
|
39
|
+
if (!made) return [];
|
|
40
|
+
let steps;
|
|
41
|
+
try {
|
|
42
|
+
const r = relative(realpath(made), realpath(dir));
|
|
43
|
+
if (r.startsWith("..") || isAbsolute(r)) return [];
|
|
44
|
+
steps = r ? r.split(sep).length : 0;
|
|
45
|
+
} catch { return []; }
|
|
46
|
+
const out = [];
|
|
47
|
+
for (let d = dir, i = 0; i <= steps; i++, d = dirname(d)) out.push(d);
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
/**
|
|
38
52
|
* Record one serving start. Returns the function that removes the record; calling it twice is harmless,
|
|
39
53
|
* so the caller can hang it on both its own shutdown and the process's `exit`.
|
|
@@ -49,16 +63,19 @@ export function recordRunning(rec, { dir = runningDir() } = {}) {
|
|
|
49
63
|
const tmp = `${file}.tmp`;
|
|
50
64
|
writeFileSync(tmp, `${JSON.stringify(rec, null, 2)}\n`, { mode: 0o600 });
|
|
51
65
|
renameSync(tmp, file);
|
|
66
|
+
// THE FOLDERS TO TRY, WORKED OUT NOW AND BOUNDED BY WHAT mkdirSync MADE. The walk used to stop when a
|
|
67
|
+
// parent's spelling equalled `made`'s, and on Windows it never did, so it went on up and removed every
|
|
68
|
+
// empty folder to the drive's root: seen on a Windows runner, 2026-09-23, where it took the home the
|
|
69
|
+
// test had made. Both ends are asked of the machine itself, which spells them one way, and a record that
|
|
70
|
+
// is not inside what was made has nothing of its own to remove.
|
|
71
|
+
const chain = madeChain(dir, made);
|
|
52
72
|
let gone = false;
|
|
53
73
|
return () => {
|
|
54
74
|
if (gone) return;
|
|
55
75
|
gone = true;
|
|
56
76
|
try { rmSync(file, { force: true }); } catch { /* already gone */ }
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
try { rmdirSync(d); } catch { break; } // not empty, or gone: either way, not ours to take
|
|
60
|
-
if (d === made) break;
|
|
61
|
-
}
|
|
77
|
+
for (const d of chain) {
|
|
78
|
+
try { rmdirSync(d); } catch { break; } // not empty, or gone: either way, not ours to take
|
|
62
79
|
}
|
|
63
80
|
};
|
|
64
81
|
}
|
package/shared/scope.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// cf-access.mjs is the OUTER transport gate: "is this a cordillera person?" (CF Access JWT, per request).
|
|
6
6
|
// This module is the INNER gate: "WHAT may this principal do, on WHICH run?" Three principal kinds:
|
|
7
7
|
// ops — full: every read tool across all runs + the write verbs (start_run/stop_run/feed_context)
|
|
8
|
-
// + what-if (stdio only). Minted for
|
|
8
|
+
// + what-if (stdio only). Minted for the ops agent, and used unconditionally on the trusted
|
|
9
9
|
// local stdio surface.
|
|
10
10
|
// user — read-only, bound to EXACTLY ONE delivered run; cannot enumerate or read other runs and
|
|
11
11
|
// cannot call any write/spend tool. This is what a report's "Ask your AI" link mints.
|
|
@@ -203,7 +203,7 @@ export const TOOL_SCOPES = {
|
|
|
203
203
|
run_changes: {}, diff_artifact: {},
|
|
204
204
|
list_runs: { crossRun: true, accountSafe: true, present: "scrub" }, search_runs: { crossRun: true },
|
|
205
205
|
// list_profiles enumerates the firm's customer roster (not run-bound). Mark crossRun so it is allowed to
|
|
206
|
-
// ops (
|
|
206
|
+
// ops (intake) + internal (CF-authed staff) but DENIED to a run-scoped user token (an external
|
|
207
207
|
// report viewer must not enumerate the client list).
|
|
208
208
|
list_profiles: { crossRun: true },
|
|
209
209
|
// plan_run RESOLVES a prospective search and describes it: depth, effective scope, the account's caps.
|
package/shared/wsl.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* BOTH SIGNALS INJECTABLE,
|
|
10
|
+
* BOTH SIGNALS INJECTABLE, as every platform branch here is: the readers this protects are the
|
|
11
11
|
* ones who cannot run this suite to find out, so a Linux runner has to be able to drive both answers
|
|
12
12
|
* rather than read the source and agree with it.
|
|
13
13
|
*
|