mainsequence 9.0.1.dev30__py3-none-any.whl → 9.0.2.dev32__py3-none-any.whl

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.
agent_scaffold/AGENTS.md CHANGED
@@ -42,6 +42,7 @@ specific update:
42
42
 
43
43
  - `mainsequence code-repository update-sdk --path .`
44
44
  - `mainsequence code-repository update-agent-skills --path .`
45
+ - `mainsequence code-repository update-platform-skills --path .`
45
46
  - `mainsequence code-repository update AGENTS.md --path .`
46
47
  - `uv run ms-tau skills sync --path .`
47
48
 
@@ -51,6 +52,11 @@ to report, not permission to mutate the repository. The same rule applies to
51
52
  requested, use the `code_repository_maintenance` skill. The `mainsequence` CLI
52
53
  never owns or updates the `ms_tau_sdk` namespace.
53
54
 
55
+ The SDK owns all of `.agents/skills/mainsequence/`. Its skill copy is local,
56
+ requires no sign-in, and deletes everything absent from the installed SDK
57
+ bundle. Platform skills are installed separately under
58
+ `.agents/skills/mainsequence_platform/` by the authenticated platform update.
59
+
54
60
  ## Route By Task
55
61
 
56
62
  - Product architecture, platform ontology, and CodeRepository Blueprint work:
@@ -172,22 +172,37 @@ to publish the CodeRepository changes.
172
172
  ## Refresh Managed Skills And Instructions
173
173
 
174
174
  Run either managed-scaffold command only when the user explicitly requests that
175
- specific update. When both are requested, refresh the SDK-owned and
176
- platform-owned skills first, then update the managed Main Sequence block in
175
+ specific update. When both are requested, refresh the SDK-owned skills first,
176
+ then update the managed Main Sequence block in
177
177
  `AGENTS.md`:
178
178
 
179
179
  ```bash
180
- mainsequence code-repository update-agent-skills --path .
181
- mainsequence code-repository update AGENTS.md --path .
180
+ uv run --offline mainsequence code-repository update-agent-skills --path .
181
+ uv run --offline mainsequence code-repository update AGENTS.md --path .
182
182
  ```
183
183
 
184
184
  Verify `.agents/skills/mainsequence/PINNED_FROM.txt` after success:
185
185
 
186
- - `sdk_version` must match the installed CodeRepository SDK;
187
- - platform manifest, ontology, and resource hashes must be present;
186
+ - `pinned_version` must match the installed CodeRepository SDK;
187
+ - the namespace must contain exactly the installed SDK's skill folders;
188
188
  - repository-owned skills outside `.agents/skills/mainsequence/` must remain
189
189
  untouched.
190
190
 
191
+ The SDK owns the whole `mainsequence` namespace. Copying it requires no login
192
+ or platform access and deletes obsolete folders, including retired table
193
+ workflow skills. Do not preserve old or platform-owned content in that folder.
194
+ The installed `metatables` package owns table workflows in its own namespace.
195
+
196
+ When the user requests platform skills, use the separate authenticated command:
197
+
198
+ ```bash
199
+ mainsequence code-repository update-platform-skills --path .
200
+ ```
201
+
202
+ It owns only `.agents/skills/mainsequence_platform/` and records the platform
203
+ manifest, ontology, and resource hashes there. A backend or authentication
204
+ failure in this command must not block a local SDK skill copy.
205
+
191
206
  The skill update is staged and atomic. If it fails, report the failing lane and
192
207
  preserve the previous valid managed tree. Because this operation can update
193
208
  this skill, reload the refreshed `code_repository_maintenance/SKILL.md` before starting
mainsequence/cli/cli.py CHANGED
@@ -56,8 +56,9 @@ from ..code_repository_context import (
56
56
  )
57
57
  from ..code_repository_skills import (
58
58
  CodeRepositorySkillAssemblyError,
59
- install_dual_source_code_repository_skills,
59
+ install_platform_code_repository_skills,
60
60
  )
61
+ from ..scaffold_skills import ScaffoldSkillCopyBlocked, copy_scaffold_skills
61
62
  from . import config as cfg
62
63
  from .api import (
63
64
  ApiError,
@@ -7845,6 +7846,33 @@ def code_repository_update_sdk(
7845
7846
  run_uv(uv, ["sync"], cwd=code_repository_dir)
7846
7847
 
7847
7848
  success("SDK update complete.")
7849
+ _warn_if_sdk_skills_stale(code_repository_dir)
7850
+
7851
+
7852
+ def _warn_if_sdk_skills_stale(code_repository_dir: pathlib.Path) -> None:
7853
+ try:
7854
+ version = _code_repository_installed_package_version(code_repository_dir, "mainsequence")
7855
+ sentinel = code_repository_dir / ".agents" / "skills" / "mainsequence" / "PINNED_FROM.txt"
7856
+ values = (
7857
+ dict(
7858
+ line.split("=", 1)
7859
+ for line in sentinel.read_text(encoding="utf-8").splitlines()
7860
+ if "=" in line
7861
+ )
7862
+ if sentinel.is_file()
7863
+ else {}
7864
+ )
7865
+ except (OSError, ValueError, typer.Exit):
7866
+ warn("Could not check the vendored SDK skill pin. Run update-agent-skills to refresh it.")
7867
+ return
7868
+ pinned = values.get("pinned_version", values.get("sdk_version"))
7869
+ if pinned != version:
7870
+ warn(
7871
+ f"Vendored SDK skills are stale or missing (pinned: {pinned or 'missing'}; installed: {version}). "
7872
+ "No scaffold files were changed. Refresh with "
7873
+ "`uv run --offline mainsequence code-repository update-agent-skills --path .` "
7874
+ "and `uv run --offline mainsequence code-repository update AGENTS.md --path .`."
7875
+ )
7848
7876
 
7849
7877
 
7850
7878
  @code_repository.command("update")
@@ -7935,124 +7963,61 @@ def code_repository_update_agent_skills(
7935
7963
  path: str | None = typer.Option(None, "--path", help="CodeRepository directory"),
7936
7964
  ):
7937
7965
  """
7938
- Update `.agents/skills/mainsequence` from installed SDK and platform sources.
7966
+ Replace SDK-owned skills with the target checkout's installed SDK bundle.
7939
7967
 
7940
- The existing command copies SDK-owned execution skills from the target
7941
- CodeRepository's installed `agent_scaffold/skills` tree and retrieves
7942
- platform-owned skills from authenticated MCP resources. It validates and
7943
- stages both sources, then replaces only the managed `mainsequence`
7944
- namespace and writes one dual-source `PINNED_FROM.txt`. Bundle-root files
7945
- such as `AGENTS.md` are not copied by this command.
7968
+ No sign-in or backend access is required unless a CodeRepository UID
7969
+ assertion is supplied. The SDK owns all of .agents/skills/mainsequence:
7970
+ files and folders absent from the installed bundle are deleted. Other
7971
+ namespaces are untouched. AGENTS.md is refreshed separately with
7972
+ code-repository update AGENTS.md. Platform skills use update-platform-skills.
7946
7973
 
7947
7974
  Examples
7948
7975
  --------
7949
- ```bash
7950
- mainsequence code-repository update-agent-skills
7951
7976
  mainsequence code-repository update-agent-skills --path .
7952
- mainsequence code-repository update-agent-skills --code-repository-uid code-repository-uid-123
7953
- ```
7954
7977
  """
7955
- code_repository_dir = _resolve_code_repository_dir(code_repository_id, path)
7956
-
7957
- scaffold_bundle_dir = _code_repository_agent_scaffold_bundle_dir(code_repository_dir)
7958
- skills_dir = scaffold_bundle_dir / "skills"
7959
- if not skills_dir.exists() or not skills_dir.is_dir():
7960
- error(f"CodeRepository-installed agent_scaffold bundle is missing skills/: {skills_dir}")
7961
- raise typer.Exit(1)
7962
-
7963
- pinned_version = _code_repository_installed_package_version(code_repository_dir, "mainsequence")
7964
- source_checkout_root = _mainsequence_source_checkout_root()
7965
- protected_code_repository_roots = (
7966
- (source_checkout_root,) if source_checkout_root is not None else ()
7967
- )
7978
+ directory = _resolve_code_repository_dir(code_repository_id, path)
7979
+ skills_dir = _code_repository_agent_scaffold_bundle_dir(directory) / "skills"
7980
+ version = _code_repository_installed_package_version(directory, "mainsequence")
7981
+ source_root = _mainsequence_source_checkout_root()
7968
7982
  try:
7969
- platform_catalog = fetch_platform_code_repository_skill_catalog()
7970
- install_result = install_dual_source_code_repository_skills(
7971
- code_repository_dir=code_repository_dir,
7972
- sdk_library_name="mainsequence",
7983
+ result = copy_scaffold_skills(
7984
+ code_repository_dir=directory,
7985
+ library_name="mainsequence",
7973
7986
  namespace="mainsequence",
7974
- sdk_skills_path=skills_dir,
7975
- sdk_version=pinned_version,
7976
- platform_catalog=platform_catalog,
7987
+ skills_path=skills_dir,
7988
+ pinned_version=version,
7977
7989
  command="mainsequence code-repository update-agent-skills",
7978
- protected_code_repository_roots=protected_code_repository_roots,
7990
+ protected_code_repository_roots=(source_root,) if source_root else (),
7979
7991
  )
7980
- except (
7981
- ApiError,
7982
- CodeRepositorySkillAssemblyError,
7983
- FileNotFoundError,
7984
- OSError,
7985
- ValueError,
7986
- ) as exc:
7992
+ except (ScaffoldSkillCopyBlocked, FileNotFoundError, OSError, ValueError) as exc:
7987
7993
  error(str(exc))
7988
7994
  raise typer.Exit(1) from exc
7989
-
7990
7995
  updated = [
7991
- {
7992
- "name": item.name,
7993
- "owner": item.owner,
7994
- "source": item.source,
7995
- "destination": item.destination,
7996
- "content_sha256": item.content_sha256,
7997
- }
7998
- for item in install_result.installed
7996
+ {"name": item.name, "owner": "sdk", "source": item.source, "destination": item.destination}
7997
+ for item in result.copied
7999
7998
  ]
8000
-
8001
7999
  payload = {
8002
- "code_repository": code_repository_dir,
8003
- "library_name": install_result.sdk_library_name,
8004
- "namespace": "mainsequence",
8005
- "skills_path": install_result.sdk_skills_path,
8006
- "destination_root": install_result.destination_root,
8007
- "sentinel_path": install_result.sentinel_path,
8008
- "pinned_version": install_result.sdk_version,
8000
+ "code_repository": directory,
8001
+ "library_name": result.library_name,
8002
+ "namespace": result.namespace,
8003
+ "skills_path": result.skills_path,
8004
+ "destination_root": result.destination_root,
8005
+ "sentinel_path": result.sentinel_path,
8006
+ "pinned_version": result.pinned_version,
8009
8007
  "sdk": {
8010
- "library_name": install_result.sdk_library_name,
8011
- "version": install_result.sdk_version,
8012
- "skills_path": install_result.sdk_skills_path,
8013
- },
8014
- "platform": {
8015
- "source_url": platform_catalog.source_url,
8016
- "manifest_version": platform_catalog.manifest_version,
8017
- "manifest_sha256": platform_catalog.manifest_sha256,
8018
- "ontology_uri": platform_catalog.ontology_uri,
8019
- "ontology_sha256": platform_catalog.ontology_sha256,
8020
- "resources": [
8021
- {
8022
- "name": resource.name,
8023
- "uri": resource.uri,
8024
- "path": str(resource.resource_path),
8025
- "content_sha256": resource.content_sha256,
8026
- }
8027
- for resource in platform_catalog.resources
8028
- ],
8029
- "skills": [
8030
- {
8031
- "name": skill.name,
8032
- "uri": skill.uri,
8033
- "path": str(skill.relative_path),
8034
- "content_sha256": skill.content_sha256,
8035
- }
8036
- for skill in platform_catalog.skills
8037
- ],
8008
+ "library_name": result.library_name,
8009
+ "version": version,
8010
+ "skills_path": result.skills_path,
8038
8011
  },
8039
8012
  "updated_count": len(updated),
8040
8013
  "updated": updated,
8041
8014
  }
8042
8015
  if _emit_json(payload):
8043
8016
  return
8044
-
8045
- success("Updated .agents/skills/mainsequence from installed SDK and platform sources.")
8017
+ success("Replaced SDK-owned .agents/skills/mainsequence with the installed bundle.")
8046
8018
  print_kv(
8047
8019
  "CodeRepository Skill Provenance",
8048
- [
8049
- ("SDK Library", install_result.sdk_library_name),
8050
- ("SDK Version", install_result.sdk_version),
8051
- ("Platform Manifest", platform_catalog.manifest_sha256),
8052
- ("Platform Resources", len(platform_catalog.resources)),
8053
- ("Platform Skills", len(platform_catalog.skills)),
8054
- ("Sentinel", str(install_result.sentinel_path)),
8055
- ],
8020
+ [("SDK Version", version), ("Sentinel", str(result.sentinel_path))],
8056
8021
  )
8057
8022
  print_table(
8058
8023
  "Updated CodeRepository Skills",
@@ -8061,6 +8026,54 @@ def code_repository_update_agent_skills(
8061
8026
  )
8062
8027
 
8063
8028
 
8029
+ @code_repository.command("update-platform-skills")
8030
+ def code_repository_update_platform_skills(
8031
+ path: str | None = typer.Option(None, "--path", help="CodeRepository directory"),
8032
+ ):
8033
+ """Refresh authenticated platform skills in .agents/skills/mainsequence_platform.
8034
+
8035
+ This requires a signed-in session and a reachable backend. The SDK-owned
8036
+ mainsequence namespace and other library namespaces remain untouched.
8037
+ """
8038
+ directory = _resolve_code_repository_dir(None, path)
8039
+ source_root = _mainsequence_source_checkout_root()
8040
+ try:
8041
+ catalog = fetch_platform_code_repository_skill_catalog()
8042
+ destination, installed = install_platform_code_repository_skills(
8043
+ code_repository_dir=directory,
8044
+ platform_catalog=catalog,
8045
+ protected_code_repository_roots=(source_root,) if source_root else (),
8046
+ )
8047
+ except (
8048
+ ApiError,
8049
+ CodeRepositorySkillAssemblyError,
8050
+ ScaffoldSkillCopyBlocked,
8051
+ FileNotFoundError,
8052
+ OSError,
8053
+ ValueError,
8054
+ ) as exc:
8055
+ error(str(exc))
8056
+ raise typer.Exit(1) from exc
8057
+ payload = {
8058
+ "code_repository": directory,
8059
+ "namespace": "mainsequence_platform",
8060
+ "destination_root": destination,
8061
+ "sentinel_path": destination / "PINNED_FROM.txt",
8062
+ "platform": {
8063
+ "source_url": catalog.source_url,
8064
+ "manifest_version": catalog.manifest_version,
8065
+ "manifest_sha256": catalog.manifest_sha256,
8066
+ "ontology_uri": catalog.ontology_uri,
8067
+ "ontology_sha256": catalog.ontology_sha256,
8068
+ },
8069
+ "updated_count": len(installed),
8070
+ "updated": [dataclasses.asdict(item) for item in installed],
8071
+ }
8072
+ if _emit_json(payload):
8073
+ return
8074
+ success("Updated .agents/skills/mainsequence_platform from the authenticated platform catalog.")
8075
+
8076
+
8064
8077
  @skills.command("list")
8065
8078
  def skills_list_cmd():
8066
8079
  """
@@ -756,6 +756,24 @@ def secure_store_available() -> bool:
756
756
  return _secure_keyring_backend() is not None
757
757
 
758
758
 
759
+ def saved_session_summary(backend: str | None = None) -> dict:
760
+ """
761
+ Describe the saved session of a backend without any token value.
762
+
763
+ `usable` says whether its refresh token has not expired by its own claim,
764
+ `expires_at` is that claim in epoch seconds (None when absent) and
765
+ `username` is the recorded user. The process environment is not consulted.
766
+ """
767
+ tokens = _read_secure_tokens(backend)
768
+ refresh = (tokens.get("refresh") or "").strip()
769
+ expires_at = token_expiry(refresh)
770
+ return {
771
+ "username": str(tokens.get("username") or ""),
772
+ "expires_at": expires_at,
773
+ "usable": bool(refresh) and (expires_at is None or expires_at > int(time.time())),
774
+ }
775
+
776
+
759
777
  def stored_session_available(backend: str | None = None) -> bool:
760
778
  """
761
779
  Return whether the credential store holds a renewable session for a backend.
@@ -70,42 +70,145 @@ def set_mainsequence_endpoint(endpoint: str) -> None:
70
70
  AUTH_ENDPOINT = normalized
71
71
 
72
72
 
73
- def _jwt_reauth_hint() -> str:
73
+ _SESSION_TOKEN_VARIABLES = ("MAINSEQUENCE_ACCESS_TOKEN", "MAINSEQUENCE_REFRESH_TOKEN")
74
+ # Renewal answers that refuse the credentials, as opposed to a backend that failed.
75
+ _REFUSED_RENEWAL_STATUSES = frozenset({400, 401, 403})
76
+
77
+
78
+ def _format_utc(epoch: int) -> str:
79
+ return datetime.datetime.fromtimestamp(epoch, tz=datetime.UTC).strftime(
80
+ "%Y-%m-%d %H:%M UTC"
81
+ )
82
+
83
+
84
+ def _session_backend() -> str:
85
+ return (AUTH_ENDPOINT or "").rstrip("/")
86
+
87
+
88
+ def _login_command(backend: str) -> str:
74
89
  """
75
- Say how to repair rejected JWT credentials, according to where they came from.
90
+ Return the CLI command that signs in to `backend`.
76
91
 
77
- A pair that was already in the process environment wins over the saved CLI
78
- session. When that pair is stale the saved session is not tried, because the
79
- pair may belong to another user or backend; the message names it instead.
92
+ `mainsequence login` alone signs in to the configured backend. Another
93
+ backend needs its address and the folder that holds its repositories.
80
94
  """
81
95
  try:
82
- from mainsequence import bootstrap
83
96
  from mainsequence.cli import config as cli_config
84
97
 
85
- from_environment = bootstrap.credential_source() == bootstrap.CREDENTIALS_FROM_ENVIRONMENT
86
- saved_session = from_environment and cli_config.stored_session_available()
98
+ configured = cli_config.normalize_backend_url(
99
+ cli_config.get_persistent_config().get("backend_url")
100
+ )
87
101
  except Exception:
88
- from_environment, saved_session = False, False
102
+ configured = ""
103
+ if not backend or backend == configured:
104
+ return "`mainsequence login`"
105
+ return f"`mainsequence login {backend} <base folder>`"
106
+
107
+
108
+ def _env_file_holding_process_credentials() -> pathlib.Path | None:
109
+ """
110
+ Return the working directory's `.env` when it holds this process's tokens.
111
+
112
+ IDE run configurations, launchers and dotenv calls load that file into a
113
+ process's environment. Values are compared here and never shown.
114
+ """
115
+ from mainsequence.cli import config as cli_config
116
+
117
+ env_path = pathlib.Path.cwd() / ".env"
118
+ try:
119
+ lines = env_path.read_text(encoding="utf-8").splitlines()
120
+ except (OSError, UnicodeError):
121
+ return None
122
+ for line in lines:
123
+ key = cli_config.env_line_key(line)
124
+ if key not in _SESSION_TOKEN_VARIABLES:
125
+ continue
126
+ value = line.split("=", 1)[1].split(" #", 1)[0].strip().strip("\"'")
127
+ if value and value == (os.environ.get(key) or "").strip():
128
+ return env_path
129
+ return None
130
+
131
+
132
+ def _jwt_reauth_hint(refresh_token: str | None = None) -> str:
133
+ """
134
+ Say why the backend refused this process's credentials and how to repair them.
135
+
136
+ The facts come from this process and this machine: the refresh token's own
137
+ expiry, whether the credentials were already in the environment when the SDK
138
+ started (and which `.env` holds them, when one does), and the saved session
139
+ of the backend. A pair from the environment wins over the saved session, so
140
+ the saved session is named and not used: the pair may belong to another user
141
+ or backend. No token value is included.
142
+ """
143
+ backend = _session_backend()
144
+ refresh = refresh_token if refresh_token is not None else os.getenv("MAINSEQUENCE_REFRESH_TOKEN")
145
+ expiry = _decode_jwt_exp(refresh)
146
+ try:
147
+ from mainsequence import bootstrap
148
+
149
+ source = bootstrap.credential_source()
150
+ from_environment = source == bootstrap.CREDENTIALS_FROM_ENVIRONMENT
151
+ from_store = source == bootstrap.CREDENTIALS_FROM_STORE
152
+ except Exception:
153
+ from_environment = from_store = False
154
+ login = _login_command(backend)
155
+
156
+ parts = []
157
+ if expiry is not None and expiry <= int(time.time()):
158
+ parts.append(f" The refresh token expired on {_format_utc(expiry)}.")
159
+ elif expiry is not None:
160
+ parts.append(
161
+ " The refresh token has not expired: the backend revoked it, or it was "
162
+ "issued by another backend."
163
+ )
89
164
 
90
165
  if from_environment:
91
- return (
92
- " The rejected credentials were set in this process's environment "
93
- "(MAINSEQUENCE_ACCESS_TOKEN / MAINSEQUENCE_REFRESH_TOKEN) before the SDK "
94
- "started: a shell export, an IDE run configuration, or a `.env` file that "
95
- "your tooling loads. "
96
- + (
97
- "A saved CLI session exists for this backend and was not used. Remove "
98
- "those variables to use it."
99
- if saved_session
100
- else "No saved CLI session exists for this backend. Remove those "
101
- "variables and run `mainsequence login`."
166
+ try:
167
+ env_file = _env_file_holding_process_credentials()
168
+ except Exception:
169
+ env_file = None
170
+ try:
171
+ from mainsequence.cli import config as cli_config
172
+
173
+ saved = cli_config.saved_session_summary(backend)
174
+ except Exception:
175
+ saved = {"usable": False, "username": "", "expires_at": None}
176
+ if env_file is not None:
177
+ parts.append(
178
+ f" These credentials come from the token lines of {env_file}, not from "
179
+ "your saved session."
180
+ )
181
+ cleanup = f"run `mainsequence refresh-token` in {env_file.parent} to remove those lines"
182
+ else:
183
+ parts.append(
184
+ " These credentials were in this process's environment "
185
+ "(MAINSEQUENCE_ACCESS_TOKEN / MAINSEQUENCE_REFRESH_TOKEN) when it started, "
186
+ "set by the program that started it, not taken from your saved session."
187
+ )
188
+ cleanup = "start the process without those two variables"
189
+ if saved["usable"]:
190
+ who = f" ({saved['username']})" if saved["username"] else ""
191
+ until = (
192
+ f", valid until {_format_utc(saved['expires_at'])}"
193
+ if saved["expires_at"] is not None
194
+ else ""
195
+ )
196
+ parts.append(
197
+ f" Your saved session for {backend}{who} is usable{until}: "
198
+ f"{cleanup}, and the next start uses it."
102
199
  )
200
+ else:
201
+ parts.append(
202
+ f" There is no usable saved session for {backend}. Sign in with {login}, "
203
+ f"then {cleanup}."
204
+ )
205
+ elif from_store:
206
+ parts.append(
207
+ f" These credentials are your saved session for {backend}. Sign in again with {login}."
103
208
  )
104
- return (
105
- " Refresh your credentials with `mainsequence logout` and "
106
- "`mainsequence login`. If this code runs in a separate shell or IDE, "
107
- "use `mainsequence login --export` and load the exported env vars there."
108
- )
209
+ else:
210
+ parts.append(f" Sign in with {login}.")
211
+ return "".join(parts)
109
212
 
110
213
 
111
214
  def _env_has_value(name: str) -> bool:
@@ -397,10 +500,14 @@ class JWTAuthProvider(BaseAuthProvider):
397
500
  if not force and not self._needs_refresh():
398
501
  return
399
502
 
503
+ backend = _session_backend()
400
504
  if not self.refresh_token:
401
505
  if self.access_token and not force:
402
506
  return
403
- raise AuthError("JWT refresh token is missing." + _jwt_reauth_hint())
507
+ raise AuthError(
508
+ f"Main Sequence cannot renew the session of this process for {backend}: "
509
+ "it has no refresh token." + _jwt_reauth_hint(self.refresh_token)
510
+ )
404
511
 
405
512
  http_client = session or requests
406
513
 
@@ -411,16 +518,24 @@ class JWTAuthProvider(BaseAuthProvider):
411
518
  timeout=self.timeout,
412
519
  )
413
520
 
521
+ if r.status_code in _REFUSED_RENEWAL_STATUSES:
522
+ raise AuthError(
523
+ f"Main Sequence refused to renew the session of this process for {backend} "
524
+ f"(HTTP {r.status_code})." + _jwt_reauth_hint(self.refresh_token)
525
+ )
414
526
  if r.status_code != 200:
527
+ # The backend failed; the credentials were not judged.
415
528
  raise AuthError(
416
- f"JWT refresh failed with status {r.status_code}." + _jwt_reauth_hint()
529
+ f"Main Sequence could not renew the session of this process for {backend}: "
530
+ f"the backend answered HTTP {r.status_code}. Try again when it is available."
417
531
  )
418
532
 
419
533
  data = r.json()
420
534
  access = data.get("access")
421
535
  if not access:
422
536
  raise AuthError(
423
- "JWT refresh response did not include access token." + _jwt_reauth_hint()
537
+ f"Main Sequence renewed the session for {backend} without an access token."
538
+ + _jwt_reauth_hint(self.refresh_token)
424
539
  )
425
540
 
426
541
  # Important if ROTATE_REFRESH_TOKENS=True
@@ -604,15 +719,12 @@ def make_request(
604
719
 
605
720
  if r.status_code == 401 and loaders is not None and not auth_retried:
606
721
  logger.warning(f"Error {r.status_code}; forcing auth refresh once")
607
- try:
608
- s.headers.update(loaders.refresh_headers(force=True, session=s))
609
- req = get_req(session=s)
610
- auth_retried = True
611
- continue
612
- except AuthError:
613
- logger.exception("Auth refresh failed")
614
- keep_request = False
615
- break
722
+ # A refused renewal raises AuthError: it is reported below with the
723
+ # reason and the repair, not as a traceback.
724
+ s.headers.update(loaders.refresh_headers(force=True, session=s))
725
+ req = get_req(session=s)
726
+ auth_retried = True
727
+ continue
616
728
 
617
729
  keep_request = False
618
730
  break
@@ -1,25 +1,17 @@
1
- """Dual-source Main Sequence code repository skill assembly.
1
+ """Authenticated platform skill catalog validation and installation.
2
2
 
3
- The existing ``mainsequence code-repository update-agent-skills`` command has two
4
- canonical inputs:
5
-
6
- * SDK-owned execution skills from the target code repository's installed
7
- ``agent_scaffold/skills`` tree.
8
- * Platform-owned skills retrieved from authenticated MCP resources.
9
-
10
- Platform content is validated in memory and written only to the target code
11
- repository. It is never persisted in the installed SDK package.
3
+ SDK-owned skills are mirrored separately by ``copy_scaffold_skills`` into the
4
+ ``mainsequence`` namespace. Platform resources use ``mainsequence_platform``;
5
+ they are never mixed into the SDK-owned namespace or installed SDK package.
12
6
  """
13
7
 
14
8
  from __future__ import annotations
15
9
 
16
10
  import hashlib
17
11
  import json
18
- import os
19
12
  import re
20
13
  import shutil
21
14
  import tempfile
22
- import uuid
23
15
  from collections.abc import Sequence
24
16
  from dataclasses import dataclass
25
17
  from pathlib import Path, PurePosixPath
@@ -29,11 +21,10 @@ import yaml
29
21
 
30
22
  from .scaffold_skills import (
31
23
  PINNED_FROM_FILENAME,
32
- CopiedScaffoldSkill,
33
- copy_scaffold_skills,
24
+ _check_code_repository_guards,
25
+ _replace_managed_tree,
34
26
  )
35
27
 
36
- DUAL_SOURCE_SENTINEL_SCHEMA = "2"
37
28
  PLATFORM_RESOURCE_NAMESPACE = "mainsequence://platform/"
38
29
  PLATFORM_ONTOLOGY_URI = "mainsequence://platform/ontology"
39
30
  PLATFORM_SKILL_URI_PREFIX = f"{PLATFORM_RESOURCE_NAMESPACE}skills/"
@@ -129,20 +120,6 @@ class InstalledCodeRepositorySkill:
129
120
  content_sha256: str | None = None
130
121
 
131
122
 
132
- @dataclass(frozen=True)
133
- class DualSourceCodeRepositorySkillInstallResult:
134
- """Result of one completed dual-source CodeRepository skill update."""
135
-
136
- code_repository_dir: Path
137
- destination_root: Path
138
- sentinel_path: Path
139
- sdk_library_name: str
140
- sdk_version: str
141
- sdk_skills_path: Path
142
- platform_catalog: PlatformCodeRepositorySkillCatalog
143
- installed: tuple[InstalledCodeRepositorySkill, ...]
144
-
145
-
146
123
  def parse_platform_code_repository_skill_catalog(
147
124
  rows: Sequence[dict[str, Any]],
148
125
  *,
@@ -463,196 +440,70 @@ def _validate_platform_resource_payload(
463
440
  )
464
441
 
465
442
 
466
- def install_dual_source_code_repository_skills(
443
+ def install_platform_code_repository_skills(
467
444
  *,
468
445
  code_repository_dir: Path,
469
- sdk_library_name: str,
470
- sdk_skills_path: Path,
471
- sdk_version: str,
472
446
  platform_catalog: PlatformCodeRepositorySkillCatalog,
473
- namespace: str = "mainsequence",
474
- command: str = "mainsequence code-repository update-agent-skills",
475
447
  protected_code_repository_roots: Sequence[Path] = (),
476
- ) -> DualSourceCodeRepositorySkillInstallResult:
477
- """Install SDK-owned and platform-owned skills as one validated CodeRepository tree."""
478
-
479
- sdk_plan = copy_scaffold_skills(
480
- code_repository_dir=code_repository_dir,
481
- library_name=sdk_library_name,
482
- namespace=namespace,
483
- skills_path=sdk_skills_path,
484
- pinned_version=sdk_version,
485
- command=command,
486
- dry_run=True,
448
+ ) -> tuple[Path, tuple[InstalledCodeRepositorySkill, ...]]:
449
+ """Replace only the platform-owned mainsequence_platform skill namespace."""
450
+ repository = code_repository_dir.expanduser().resolve()
451
+ namespace = repository / ".agents" / "skills" / "mainsequence_platform"
452
+ if namespace.is_symlink():
453
+ raise CodeRepositorySkillAssemblyError("Platform namespace must not be a symlink.")
454
+ destination = namespace.resolve()
455
+ if not destination.is_relative_to(repository):
456
+ raise CodeRepositorySkillAssemblyError("Platform destination escapes the target checkout.")
457
+ _check_code_repository_guards(
458
+ code_repository_dir=repository,
487
459
  protected_code_repository_roots=protected_code_repository_roots,
460
+ code_repository_guard=None,
488
461
  )
489
- _validate_source_ownership(
490
- sdk_skills=sdk_plan.copied,
491
- platform_skills=platform_catalog.skills,
462
+ destination.parent.mkdir(parents=True, exist_ok=True)
463
+ staging = Path(
464
+ tempfile.mkdtemp(prefix=".mainsequence_platform.staging-", dir=destination.parent)
492
465
  )
493
-
494
- destination_root = sdk_plan.destination_root
495
- destination_parent = destination_root.parent
496
- destination_parent.mkdir(parents=True, exist_ok=True)
497
- staging_root = Path(
498
- tempfile.mkdtemp(
499
- prefix=f".{destination_root.name}.staging-",
500
- dir=destination_parent,
501
- )
502
- )
503
-
504
- installed: list[InstalledCodeRepositorySkill] = []
466
+ installed = []
467
+ lines = [
468
+ "schema=platform-1",
469
+ "owner=platform",
470
+ f"platform_source_url={_sentinel_value(platform_catalog.source_url)}",
471
+ f"platform_retrieved_at_utc={_utc_timestamp()}",
472
+ f"platform_manifest_version={platform_catalog.manifest_version}",
473
+ f"platform_manifest_sha256={platform_catalog.manifest_sha256}",
474
+ f"platform_ontology_sha256={platform_catalog.ontology_sha256}",
475
+ ]
505
476
  try:
506
- for item in sdk_plan.copied:
507
- staged_destination = staging_root / item.name
508
- shutil.copytree(item.source, staged_destination)
509
- installed.append(
510
- InstalledCodeRepositorySkill(
511
- name=item.name,
512
- owner="sdk",
513
- source=str(item.source),
514
- destination=destination_root / item.name,
515
- )
516
- )
517
-
518
477
  for skill in platform_catalog.skills:
519
- staged_destination = staging_root.joinpath(*skill.relative_path.parts)
520
- staged_destination.parent.mkdir(parents=True, exist_ok=True)
521
- staged_destination.write_text(skill.content, encoding="utf-8")
478
+ target = staging.joinpath(*skill.relative_path.parts)
479
+ if not target.resolve().is_relative_to(staging):
480
+ raise CodeRepositorySkillAssemblyError("Platform skill path escapes its namespace.")
481
+ target.parent.mkdir(parents=True, exist_ok=True)
482
+ target.write_text(skill.content, encoding="utf-8")
522
483
  installed.append(
523
484
  InstalledCodeRepositorySkill(
524
485
  name=skill.name,
525
486
  owner="platform",
526
487
  source=skill.uri,
527
- destination=destination_root.joinpath(*skill.relative_path.parts),
488
+ destination=destination.joinpath(*skill.relative_path.parts),
528
489
  content_sha256=skill.content_sha256,
529
490
  )
530
491
  )
531
-
532
- sentinel_path = staging_root / PINNED_FROM_FILENAME
533
- sentinel_path.write_text(
534
- render_dual_source_sentinel(
535
- sdk_library_name=sdk_library_name,
536
- namespace=namespace,
537
- sdk_version=sdk_version,
538
- sdk_skills_path=sdk_plan.skills_path,
539
- platform_catalog=platform_catalog,
540
- command=command,
541
- ),
542
- encoding="utf-8",
543
- )
544
- _replace_managed_tree(
545
- staging_root=staging_root,
546
- destination_root=destination_root,
547
- )
492
+ for resource in platform_catalog.resources:
493
+ prefix = f"platform_resource.{resource.name}"
494
+ lines.extend(
495
+ [
496
+ f"{prefix}.uri={_sentinel_value(resource.uri)}",
497
+ f"{prefix}.path={_sentinel_value(str(resource.resource_path))}",
498
+ f"{prefix}.content_sha256={resource.content_sha256}",
499
+ ]
500
+ )
501
+ (staging / PINNED_FROM_FILENAME).write_text("\n".join([*lines, ""]), encoding="utf-8")
502
+ _replace_managed_tree(staging_root=staging, destination_root=destination)
548
503
  except Exception:
549
- if staging_root.exists():
550
- shutil.rmtree(staging_root, ignore_errors=True)
551
- raise
552
-
553
- return DualSourceCodeRepositorySkillInstallResult(
554
- code_repository_dir=sdk_plan.code_repository_dir,
555
- destination_root=destination_root,
556
- sentinel_path=destination_root / PINNED_FROM_FILENAME,
557
- sdk_library_name=sdk_library_name,
558
- sdk_version=sdk_version,
559
- sdk_skills_path=sdk_plan.skills_path,
560
- platform_catalog=platform_catalog,
561
- installed=tuple(installed),
562
- )
563
-
564
-
565
- def render_dual_source_sentinel(
566
- *,
567
- sdk_library_name: str,
568
- namespace: str,
569
- sdk_version: str,
570
- sdk_skills_path: Path,
571
- platform_catalog: PlatformCodeRepositorySkillCatalog,
572
- command: str,
573
- ) -> str:
574
- """Render the schema-2 dual-source provenance record."""
575
-
576
- installed_at_utc = _utc_timestamp()
577
- lines = [
578
- f"schema={DUAL_SOURCE_SENTINEL_SCHEMA}",
579
- f"library_name={_sentinel_value(sdk_library_name)}",
580
- f"namespace={_sentinel_value(namespace)}",
581
- f"pinned_version={_sentinel_value(sdk_version)}",
582
- f"skills_path={_sentinel_value(str(sdk_skills_path.resolve()))}",
583
- f"copied_at_utc={installed_at_utc}",
584
- f"installed_at_utc={installed_at_utc}",
585
- f"sdk_library_name={_sentinel_value(sdk_library_name)}",
586
- f"sdk_version={_sentinel_value(sdk_version)}",
587
- f"sdk_skills_path={_sentinel_value(str(sdk_skills_path.resolve()))}",
588
- f"platform_source_url={_sentinel_value(platform_catalog.source_url)}",
589
- f"platform_retrieved_at_utc={installed_at_utc}",
590
- f"platform_manifest_version={platform_catalog.manifest_version}",
591
- f"platform_manifest_sha256={platform_catalog.manifest_sha256}",
592
- f"platform_ontology_uri={platform_catalog.ontology_uri}",
593
- f"platform_ontology_sha256={platform_catalog.ontology_sha256}",
594
- f"platform_resource_count={len(platform_catalog.resources)}",
595
- f"platform_skill_count={len(platform_catalog.skills)}",
596
- ]
597
- for resource in platform_catalog.resources:
598
- prefix = f"platform_resource.{resource.name}"
599
- lines.extend(
600
- [
601
- f"{prefix}.uri={_sentinel_value(resource.uri)}",
602
- f"{prefix}.path={_sentinel_value(str(resource.resource_path))}",
603
- f"{prefix}.content_sha256={resource.content_sha256}",
604
- ]
605
- )
606
- lines.extend(
607
- [
608
- f"command={_sentinel_value(command)}",
609
- "",
610
- ]
611
- )
612
- return "\n".join(lines)
613
-
614
-
615
- def _validate_source_ownership(
616
- *,
617
- sdk_skills: Sequence[CopiedScaffoldSkill],
618
- platform_skills: Sequence[PlatformCodeRepositorySkill],
619
- ) -> None:
620
- sdk_roots = {item.name for item in sdk_skills}
621
- collisions = sorted(
622
- {
623
- skill.relative_path.parts[0]
624
- for skill in platform_skills
625
- if skill.relative_path.parts[0] in sdk_roots
626
- }
627
- )
628
- if collisions:
629
- raise CodeRepositorySkillAssemblyError(
630
- "SDK/platform skill path ownership collision: "
631
- + ", ".join(collisions)
632
- + ". Refactor the SDK-owned skill path before updating the CodeRepository."
633
- )
634
-
635
-
636
- def _replace_managed_tree(*, staging_root: Path, destination_root: Path) -> None:
637
- backup_root = destination_root.parent / (f".{destination_root.name}.backup-{uuid.uuid4().hex}")
638
- destination_existed = destination_root.exists()
639
- if destination_existed:
640
- os.replace(destination_root, backup_root)
641
- try:
642
- os.replace(staging_root, destination_root)
643
- except Exception as install_exc:
644
- try:
645
- if destination_existed and backup_root.exists():
646
- os.replace(backup_root, destination_root)
647
- except Exception as rollback_exc:
648
- raise CodeRepositorySkillAssemblyError(
649
- "CodeRepository skill installation failed and rollback also failed: "
650
- f"{rollback_exc}. The previous managed tree remains at "
651
- f"{backup_root} for manual recovery."
652
- ) from install_exc
504
+ shutil.rmtree(staging, ignore_errors=True)
653
505
  raise
654
- if backup_root.exists():
655
- shutil.rmtree(backup_root, ignore_errors=True)
506
+ return destination, tuple(installed)
656
507
 
657
508
 
658
509
  def _safe_platform_resource_path(
@@ -9,10 +9,13 @@ records the installed library version that supplied the copied skills.
9
9
  from __future__ import annotations
10
10
 
11
11
  import datetime as _datetime
12
+ import os
12
13
  import re
13
14
  import shutil
15
+ import tempfile
16
+ import uuid
14
17
  from collections.abc import Callable, Sequence
15
- from dataclasses import dataclass
18
+ from dataclasses import dataclass, replace
16
19
  from pathlib import Path
17
20
 
18
21
  PINNED_FROM_FILENAME = "PINNED_FROM.txt"
@@ -64,9 +67,10 @@ def copy_scaffold_skills(
64
67
  """Copy packaged scaffold skills into a managed CodeRepository skill namespace.
65
68
 
66
69
  The helper copies each immediate child skill directory from `skills_path` to
67
- `<code_repository_dir>/.agents/skills/<namespace>/`, overwriting only matching
68
- managed skill folders. Files, hidden folders, and folders starting with
69
- `__` are skipped.
70
+ `<code_repository_dir>/.agents/skills/<namespace>/`. That entire namespace is
71
+ library-owned: folders no longer shipped by the library are removed. The
72
+ replacement is staged and atomic. Other namespaces are never changed.
73
+ Source files, hidden folders, and folders starting with `__` are skipped.
70
74
 
71
75
  `pinned_version` is required and must be the installed version of the
72
76
  library that owns `skills_path`. On successful non-dry-run copies, the
@@ -86,10 +90,15 @@ def copy_scaffold_skills(
86
90
  if not resolved_skills_path.is_dir():
87
91
  raise FileNotFoundError(f"Scaffold skill source directory does not exist: {skills_path}")
88
92
 
89
- destination_root = (
90
- resolved_code_repository_dir / ".agents" / "skills" / resolved_namespace
91
- ).resolve(strict=False)
93
+ destination = resolved_code_repository_dir / ".agents" / "skills" / resolved_namespace
94
+ if destination.is_symlink():
95
+ raise ScaffoldSkillCopyBlocked("Blocked: the managed namespace must not be a symlink.")
96
+ destination_root = destination.resolve(strict=False)
92
97
  sentinel_path = destination_root / PINNED_FROM_FILENAME
98
+ if not destination_root.is_relative_to(resolved_code_repository_dir):
99
+ raise ScaffoldSkillCopyBlocked(
100
+ "Blocked: destination namespace escapes the target checkout."
101
+ )
93
102
 
94
103
  _check_code_repository_guards(
95
104
  code_repository_dir=resolved_code_repository_dir,
@@ -134,13 +143,26 @@ def copy_scaffold_skills(
134
143
  if dry_run:
135
144
  return result
136
145
 
137
- for item in copied:
138
- _copy_tree_overwrite(item.source, item.destination)
139
- _write_pin_sentinel(
140
- result,
141
- command=command,
142
- copied_at_utc=_utc_timestamp(),
146
+ destination_root.parent.mkdir(parents=True, exist_ok=True)
147
+ staging_root = Path(
148
+ tempfile.mkdtemp(prefix=f".{resolved_namespace}.staging-", dir=destination_root.parent)
143
149
  )
150
+ try:
151
+ for item in copied:
152
+ shutil.copytree(item.source, staging_root / item.name)
153
+ _write_pin_sentinel(
154
+ replace(
155
+ result,
156
+ destination_root=staging_root,
157
+ sentinel_path=staging_root / PINNED_FROM_FILENAME,
158
+ ),
159
+ command=command,
160
+ copied_at_utc=_utc_timestamp(),
161
+ )
162
+ _replace_managed_tree(staging_root=staging_root, destination_root=destination_root)
163
+ except Exception:
164
+ shutil.rmtree(staging_root, ignore_errors=True)
165
+ raise
144
166
  return result
145
167
 
146
168
 
@@ -182,11 +204,25 @@ def _iter_skill_roots(skills_path: Path) -> list[Path]:
182
204
  ]
183
205
 
184
206
 
185
- def _copy_tree_overwrite(source: Path, destination: Path) -> None:
186
- if destination.exists():
187
- shutil.rmtree(destination)
188
- destination.parent.mkdir(parents=True, exist_ok=True)
189
- shutil.copytree(source, destination)
207
+ def _replace_managed_tree(*, staging_root: Path, destination_root: Path) -> None:
208
+ backup_root = destination_root.parent / f".{destination_root.name}.backup-{uuid.uuid4().hex}"
209
+ destination_existed = destination_root.exists()
210
+ if destination_existed:
211
+ os.replace(destination_root, backup_root)
212
+ try:
213
+ os.replace(staging_root, destination_root)
214
+ except Exception as install_exc:
215
+ try:
216
+ if destination_existed and backup_root.exists():
217
+ os.replace(backup_root, destination_root)
218
+ except Exception as rollback_exc:
219
+ raise ScaffoldSkillCopyBlocked(
220
+ f"Skill installation and rollback failed: {rollback_exc}. "
221
+ f"The previous tree remains at {backup_root} for recovery."
222
+ ) from install_exc
223
+ raise
224
+ if backup_root.exists():
225
+ shutil.rmtree(backup_root, ignore_errors=True)
190
226
 
191
227
 
192
228
  def _write_pin_sentinel(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 9.0.1.dev30
3
+ Version: 9.0.2.dev32
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -1,8 +1,8 @@
1
- agent_scaffold/AGENTS.md,sha256=dd8vt0Q-ZCw3mUh5tBYG441N1aNZ6VxnlD16wgvad2Q,5828
1
+ agent_scaffold/AGENTS.md,sha256=yLTuL2VuT47JoBa7w7eekcWhenWciySPQmO9mAIBALE,6178
2
2
  agent_scaffold/skills/a2a_sdk_execution/SKILL.md,sha256=NKtcXibE8TxZzKzz1KzJ2cVZ_EeuJJkb660U6wLvZ3s,11809
3
3
  agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md,sha256=zETXg2fFCujdorOqI2yjhH4Zv1nS16il8uuohF3jz60,13883
4
4
  agent_scaffold/skills/maintenance/bug_auditor/SKILL.md,sha256=pV8g6FbSgZu1ZsrCaWAbrf6MpetxMqoZKO1rBbtZMgs,8591
5
- agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md,sha256=U_8TILfdsUIwl0qD1zVbdEFfmjHpK8XCNXbszZfHBtQ,12693
5
+ agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md,sha256=PczPIOM1YPyXlgd7i5OyN5DkYVwGHrDowsyoxzAqsi8,13396
6
6
  agent_scaffold/skills/maintenance/metatables_transition/SKILL.md,sha256=PisgpytcksJnfZMS6aiPCmahsT3fm8DIwk_cefXA2qU,3759
7
7
  agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md,sha256=o1rIlYAC7ejV7gKKf-BaglIZY1YkDO5Y27F6e2eK_94,8571
8
8
  agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md,sha256=F2I_pwzhbVW-32pBHQZfLnX6BC76iiILHZU1ewy2VYo,15245
@@ -12,18 +12,18 @@ mainsequence/__main__.py,sha256=KuAP69uduS2ImrPIgNMzbGBRepZzjqvUONu5vFh4v4A,176
12
12
  mainsequence/_request_identity.py,sha256=jiroPFVDM8vphEf9VXuggQJKUOGohfk7-pDwJSOILEw,1211
13
13
  mainsequence/bootstrap.py,sha256=AvG55Y46RcshVqJZsyqvUDN62CJg4CDbHu0Bvsbwfzs,2910
14
14
  mainsequence/code_repository_context.py,sha256=8Q1ammEJr0m8G8aMR4Mf6nLHMPe51sPr4m72PSwp3D4,28588
15
- mainsequence/code_repository_skills.py,sha256=rytHd9XDaHq8t9o6smNksN8gHm6hfUEPvJIGYgGkPXA,28417
15
+ mainsequence/code_repository_skills.py,sha256=AyC1HFAxQXHXNBGbarVUJS2cHd4X5HwDx6u8XBophbE,23611
16
16
  mainsequence/defaults.py,sha256=5r6s7AI-X40rpm1D3IgcNsWam7iJg4_lIxB3F_1u2z0,408
17
17
  mainsequence/logconf.py,sha256=7OXSBb8yXrUbIbO4vX-l0vss1R8q1DlNi1-fBNkjX-w,18693
18
18
  mainsequence/repository_identity_security.py,sha256=Cdywndhiy1zJFUPh-FfM90RjZ3Hg3tjhxBr64FRhmXs,1035
19
19
  mainsequence/runtime_flags.py,sha256=1eTM7VRRhnuZ_GXcmFhqAmdEKwyQYMyZcPsio88vJRQ,378
20
- mainsequence/scaffold_skills.py,sha256=mhjn7Xy5BSp8711xf7jziOC-DgyI1QUNWDup-fg_7eo,8844
20
+ mainsequence/scaffold_skills.py,sha256=k0V6eKC5AwbHr9wB9UGMJNF-8eJ0_1izF4-BU01KHrg,10606
21
21
  mainsequence/cli/__init__.py,sha256=sMWTnomCaISjnureLuXFRqOzkH2Y77uYEivsd-M6_8Y,28
22
22
  mainsequence/cli/api.py,sha256=r9D0lSaw2Ah-39i04w9JgNkg3yjq88TLesB63B6nvug,128586
23
23
  mainsequence/cli/browser_auth.py,sha256=C-Sbpt0Pr9Pv3Z9dO80TMk7zPcaaZ-4zvW0tbRVMrTU,9863
24
- mainsequence/cli/cli.py,sha256=RYtT5DDCvoIrZQixAQWycJyqHxa4kD0xxoXj3DU7_0Y,275424
24
+ mainsequence/cli/cli.py,sha256=JnueoyzZ0t99m7RIwmeUNWYNPUo8gNntpcBeaL0bERk,276172
25
25
  mainsequence/cli/code_repository_status.py,sha256=SHEnU8YSWFowPG6dEdE4Yd8CS1tIcJSE1MXFLfvD3Os,5975
26
- mainsequence/cli/config.py,sha256=IT42UzG93uBhR98yUyg8YR-wMlQAgfx8UrybJcpih7Y,44884
26
+ mainsequence/cli/config.py,sha256=4AGDEUPAJ1GzoDX3FzYYFvGMKfeAXM38Kh7Yv-OQLQQ,45595
27
27
  mainsequence/cli/docker_utils.py,sha256=eAnp9MI042cHWwKasA5IF2I7INL3A6tV2JX-cSIe7rc,10687
28
28
  mainsequence/cli/doctor.py,sha256=_1XHd72jheRDt7dEJHd6hbBSSpCPpMwwFDUOLcdkii8,4550
29
29
  mainsequence/cli/local_ops.py,sha256=oeYA2KXDLEjiENVZYJCc5-loNZxK3PK4G4sXldrDfm4,6495
@@ -43,16 +43,16 @@ mainsequence/client/models_foundry.py,sha256=iN1jJzDokfniEQF0Ac5eepAB7L5pVjJnKav
43
43
  mainsequence/client/models_helpers.py,sha256=rE7wPc9llKkctAKdJcak0kXJagjLivUzO2ebUGhz1M8,45820
44
44
  mainsequence/client/models_user.py,sha256=BU_hfn4-4KqYz3nsaPlXuYZmUG6_-7YM892mkM92Zyo,37613
45
45
  mainsequence/client/observability.py,sha256=_WrDKCaNk_TXmKElKCXC1inork6Exxxe8FRY4m1GI9s,16008
46
- mainsequence/client/utils.py,sha256=ZJNmUh9JNslznNMYvTGy26h0V9SMvYVqMX3Pva8l0lw,27549
46
+ mainsequence/client/utils.py,sha256=fQur4p-ojLWTMcNWlYWx7uZKbGNEc4c2kJq1Wl_w070,31925
47
47
  mainsequence/client/value_sets.py,sha256=7TA-mpuAd3hOduNgO1WTQQTuNOGaFgue-VqCsDWKaC8,6181
48
48
  mainsequence/instrumentation/__init__.py,sha256=J_9XmfjprElvz0u2t9rTyJT0kFdyKpxdbkdQiaw28_U,316
49
49
  mainsequence/instrumentation/utils.py,sha256=b-ihjSioAepeLfMpudM2SqCtvnxMqIXileHx3klBCQU,3377
50
50
  mainsequence/server/__init__.py,sha256=559DiiBcCP6veWRmK2mXUEbsl7gbZofTvsbTUFjn0VE,82
51
51
  mainsequence/server/caller_assertions.py,sha256=5q8LZrDYozaonG1eBb9P8DojKQlB2i2qUJwO5VhsrW4,9780
52
52
  mainsequence/server/fastapi.py,sha256=tD1aVuJOgoBTu7H8bs9IldPNYRT4fhkr1leN3KZP1pI,10521
53
- mainsequence-9.0.1.dev30.dist-info/licenses/LICENSE,sha256=b6Ecsk8wjsEby3lbSzdljR6hHiFGHBizt9iWV2p1c_I,1074
54
- mainsequence-9.0.1.dev30.dist-info/METADATA,sha256=Q29OofPgcbN1MAT1LORvrCW5DOi5sG1epdwOEw7xqLk,7435
55
- mainsequence-9.0.1.dev30.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
56
- mainsequence-9.0.1.dev30.dist-info/entry_points.txt,sha256=XGAOq3-mF2lWWpeRJvoaWyMarRcK167mH1g124aGdUs,88
57
- mainsequence-9.0.1.dev30.dist-info/top_level.txt,sha256=BFeblM_Q9q0cUWBvTxnfWcWQEHtf5XZi9nOS-Gdfwus,28
58
- mainsequence-9.0.1.dev30.dist-info/RECORD,,
53
+ mainsequence-9.0.2.dev32.dist-info/licenses/LICENSE,sha256=b6Ecsk8wjsEby3lbSzdljR6hHiFGHBizt9iWV2p1c_I,1074
54
+ mainsequence-9.0.2.dev32.dist-info/METADATA,sha256=m2rgtp3Cz2nDtlUChD40l1GN8z3VdQcl0pykNLdxDGo,7435
55
+ mainsequence-9.0.2.dev32.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
56
+ mainsequence-9.0.2.dev32.dist-info/entry_points.txt,sha256=XGAOq3-mF2lWWpeRJvoaWyMarRcK167mH1g124aGdUs,88
57
+ mainsequence-9.0.2.dev32.dist-info/top_level.txt,sha256=BFeblM_Q9q0cUWBvTxnfWcWQEHtf5XZi9nOS-Gdfwus,28
58
+ mainsequence-9.0.2.dev32.dist-info/RECORD,,