Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/live-smoke.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ jobs:
name: Bounded Chat Completions and Responses smoke
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
environment: live-smoke
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,8 +93,8 @@ jobs:
timeout-minutes: 10
permissions:
contents: read
# Required repository configuration: protect this environment, require reviewers, and
# configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
# Required repository configuration: protect this environment without required reviewers,
# and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable.
environment: live-smoke
env:
COMETAPI_LIVE_CONCURRENCY: "1"
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,8 +46,9 @@ Before the first remote push:
violations in one run while returning non-zero if any violation exists.
Keep checks for canonical identity, contacts, repository metadata, public-
safe language, and standalone content.
4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable.
An unset or non-true value must prevent live execution. Keep
4. Gate scheduled and manually dispatched live smoke with a
`LIVE_SMOKE_ENABLED` repository variable. An unset or non-true value must
prevent live execution. Keep
`RELEASE_PLEASE_ENABLED` disabled through the initial manual alpha.
5. Make the release live-model setting use `gpt-5.4` when
`COMETAPI_LIVE_MODEL` is unset or empty; never allow an empty model value.
Expand Down
14 changes: 7 additions & 7 deletions RELEASING.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,11 @@ The package manifest uses `authors = [{ name = "CometAPI" }]`. Remove
`.github/CODEOWNERS` and its validation dependencies; it is not required while
the project has one active maintainer.

Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled live
execution and keep `RELEASE_PLEASE_ENABLED` disabled through the initial manual
alpha. An unset or non-true value prevents the corresponding workflow from
running. The release live-model configuration resolves an unset or empty
`COMETAPI_LIVE_MODEL` to `gpt-5.4`.
Before the first push, require `LIVE_SMOKE_ENABLED=true` for scheduled and
manually dispatched live execution, and keep `RELEASE_PLEASE_ENABLED` disabled
through the initial manual alpha. An unset or non-true value prevents the
corresponding gated job from executing. The release live-model configuration
resolves an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4`.

The private stage validates sanitized history, the complete local gate, and
real credential-free default-branch CI only. Do not configure or exercise
Expand DownExpand Up@@ -128,8 +128,8 @@ violations in one run and still returns non-zero when any violation exists.
is ongoing monitoring only and cannot satisfy a release gate. It is capped at
four requests, 16 output tokens
per generation, a 30-second request timeout, concurrency one, a ten-minute
workflow timeout, and stop on the first failure. Scheduled execution also
requires `LIVE_SMOKE_ENABLED=true`.
workflow timeout, and stop on the first failure. Every trigger requires
`LIVE_SMOKE_ENABLED=true`.
- `release-please.yml` maintains a human-reviewed version and changelog pull
request from Conventional Commits after maintainers enable the
`RELEASE_PLEASE_ENABLED` repository variable. Keep it disabled until the
Expand Down
5 changes: 3 additions & 2 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,9 @@ All workflow files must pass local `actionlint` 1.7.12. This is static
validation only. Remote behavior remains unverified until each workflow runs
successfully in the canonical GitHub repository.

Scheduled live smoke must additionally require `LIVE_SMOKE_ENABLED=true`; an
unset or other value prevents live execution. Release Please requires
Scheduled and manually dispatched live smoke must require
`LIVE_SMOKE_ENABLED=true`; an unset or other value prevents live execution.
Release Please requires
`RELEASE_PLEASE_ENABLED=true` and remains disabled through the initial manual
alpha. Release jobs must resolve an unset or empty `COMETAPI_LIVE_MODEL` to
`gpt-5.4` rather than attempt a request with an empty model.
Expand Down
23 changes: 12 additions & 11 deletions scripts/check_workflows.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,13 +23,13 @@ def _require_pattern(text: str, pattern: str, message: str) -> None:
raise CheckError(message)


def _job(text: str, name: str) -> str:
def _job(text: str, name: str, *, source: str = "publish workflow") -> str:
match = re.search(
rf"(?ms)^ {re.escape(name)}:\n(?P<body>.*?)(?=^ [a-zA-Z0-9_-]+:\n|\Z)",
text,
)
if match is None:
raise CheckError(f"publish workflow has no {name!r} job")
raise CheckError(f"{source} has no {name!r} job")
return match.group(0)


Expand DownExpand Up@@ -135,20 +135,21 @@ def check_publish_workflow(text: str, live_smoke_text: str) -> None:
if write_permissions != ["id-token"]:
raise CheckError("id-token: write on the publish job must be the only write permission")

monitoring_live = _job(live_smoke_text, "smoke", source="live-smoke workflow")
_require_pattern(
live_smoke_text,
r"(?m)^concurrency:\n group: trusted-live-smoke\n cancel-in-progress: false$",
"release and monitoring live smokes must share one non-cancelling concurrency group",
)
_require(
live_smoke_text,
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"scheduled live smoke must require LIVE_SMOKE_ENABLED=true",
)
_require(
live_smoke_text,
"github.ref == format('refs/heads/{0}', github.event.repository.default_branch)",
"monitoring live smoke must run only against the canonical default branch",
_require_pattern(
monitoring_live,
r"(?m)^ if: >-\n"
r" github\.ref == format\('refs/heads/\{0\}', "
r"github\.event\.repository\.default_branch\) &&\n"
r" vars\.LIVE_SMOKE_ENABLED == 'true'\n"
r" runs-on:",
"monitoring live smoke must run only against the canonical default branch and "
"require LIVE_SMOKE_ENABLED=true for every trigger",
)

build = _job(text, "build")
Expand Down
36 changes: 33 additions & 3 deletions tests/test_release_workflow.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -380,13 +380,43 @@ def test_semantic_contract_rejects_split_monitoring_live_concurrency() -> None:
)


def test_semantic_contract_rejects_ungated_scheduled_live_smoke() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
@pytest.mark.parametrize(
"replacement",
[
"github.event_name == 'workflow_dispatch'",
"(github.event_name == 'workflow_dispatch' || vars.LIVE_SMOKE_ENABLED == 'true')",
"vars.LIVE_SMOKE_ENABLED != 'false'",
"vars.LIVE_SMOKE_ENABLED == 'true'\n || github.event_name == 'workflow_dispatch'",
],
ids=["manual-only", "manual-bypass", "non-exact-opt-in", "continued-manual-bypass"],
)
def test_semantic_contract_rejects_live_smoke_gate_bypasses(replacement: str) -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
replacement,
1,
)
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
)


def test_semantic_contract_checks_live_smoke_gate_on_smoke_job() -> None:
live_smoke = LIVE_SMOKE_WORKFLOW.read_text(encoding="utf-8").replace(
"vars.LIVE_SMOKE_ENABLED == 'true'",
"github.event_name == 'workflow_dispatch'",
1,
)
with pytest.raises(RuntimeError, match="LIVE_SMOKE_ENABLED=true"):
live_smoke += """
decoy:
if: >-
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
vars.LIVE_SMOKE_ENABLED == 'true'
runs-on: ubuntu-latest
"""
with pytest.raises(RuntimeError, match="every trigger"):
check_publish_workflow(
PUBLISH_WORKFLOW.read_text(encoding="utf-8"),
live_smoke,
Expand Down
Loading