A quarantined device says what failed
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 12/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- typescript
調査の方向性
Start in src/core/quarantine-coordinator.ts and src/core/reclaim-coordinator.ts to see where quarantine is entered, then src/core/registry.ts for the device record. The change also spans src/contract/schemas.ts, src/cli/index.ts and ui/src/model/attention.ts, and it depends on feature #623 and a protocol bump. Done means every quarantine path records a cause that survives restart and clears on exit.
索引モデルが issue の本文から書いたものです。
説明
Part of #623.
Scope
A quarantined device says what failed. simlock status, status --json, list --devices, GET /v1/status and the console's Attention inspector show the cause: the kind of failure and the tool's short error message. An agent-role caller sees the kind without the message. The cause is kept in the registry, so it is still there after a daemon restart.
In short
Every way into quarantine writes a cause on the device: purge-failed, shutdown-failed, delete-failed or stalled (with the state the device stalled in). The first three carry the error message, cut to 300 characters. The cause goes when the device leaves quarantine. The shape is feature #623 Shared values, "Quarantine cause".
flowchart LR
R[Reclaim fails] -->|purge / shutdown / delete| Q["QuarantineCoordinator.enter (changed: writes the cause)"]
D[doctor --fix on a stall] --> S["enterFromStalledTransition (changed: writes the cause)"]
Q --> Reg[(state.json device record)]
S --> Reg
Reg --> St["status.get / list.get (changed)"]
St --> C["Attention inspector: Cause (changed)"]
St --> CLI["simlock status (changed)"]
Reg -->|recover, delete, unenrol, re-add| X[cause removed]
Words used:
- Cause: why a device is quarantined, e.g.
{ "kind": "purge-failed", "message": "DriverCrashError: simctl erase exited 164" }. - Message: the error text simlock already logs for the failure (
<error name>: <error message>), with control characters turned into spaces. A longer text is cut so that it ends with…and is 300 characters with it. An empty one is left out.
The session, before and after:
$ simlock status
Device dev_7: quarantined, mode full, serves default mode: yes (purge retry 0, next retry at 1760619150000)
$ simlock status # after
Device dev_7: quarantined, mode full, serves default mode: yes (purge retry 0, next retry at 1760619150000; purge failed: DriverCrashError: simctl erase exited 164)
$ simlock status --json # after, the device entry
{ "id": "dev_7", "state": "quarantined", "quarantineAttempts": 0, "quarantineNextRetryAt": 1760619150000,
"quarantineCause": { "kind": "purge-failed", "message": "DriverCrashError: simctl erase exited 164" }, ... }
| How the device got there | Today | After: quarantineCause |
Inspector Cause |
simlock status marker ends with |
|---|---|---|---|---|
| Purge after a lease failed (virtual, or a physical device that is present) | nothing | purge-failed, message |
Purge failed: <message> |
purge failed: <message> |
| A returned physical device's wipe failed while present | nothing | purge-failed, message |
Purge failed: <message> |
purge failed: <message> |
A spent fresh device's shutdown failed |
nothing | shutdown-failed, message |
Shutdown failed: <message> |
shutdown failed: <message> |
A spent fresh device's delete failed after the shutdown |
nothing | delete-failed, message |
Delete failed: <message> |
delete failed: <message> |
doctor --fix on a device stuck provisioning |
nothing | stalled, stalledState: "provisioning" |
Stalled while provisioning |
stalled while provisioning |
doctor --fix on a device stuck reclaiming |
nothing | stalled, stalledState: "reclaiming" |
Stalled while reclaiming |
stalled while reclaiming |
Quarantined before this upgrade (no cause in state.json) |
nothing | none | no Cause line |
as today: purge retry …, nothing after it |
If this goes wrong, an operator sees a quarantined device with no cause or the wrong one, or a cause still showing on a device that is back in use.
Technical spec
Facts
| # | Fact | Source |
|---|---|---|
| F1 | A failed purge goes to quarantine through #recoverPurgeFailure, unless the device is physical and not present (then it goes absent). |
src/core/reclaim-coordinator.ts:110-116, :322-336, :339-353 |
| F2 | A physical device's purge is the same #purge: after its lease (reclaim), and for a returned device or a deferred wipe (reclaimReturned, recoverInterrupted → #wipeInBackground). |
src/core/reclaim-coordinator.ts:96-103, :146-150, :175-194, :226-231 |
| F3 | A spent fresh device's failed shutdown and its failed delete after the shutdown both hand over attemptedStrategy: "delete"; nothing tells them apart today. |
src/core/reclaim-coordinator.ts:263-273, :281-291 |
| F4 | The failure handed to quarantine carries error: stableError(error). stableError returns `${name}: ${message}`. |
src/core/reclaim-coordinator.ts:333; src/core/stable-error.ts:8-11 |
| F5 | QuarantineCoordinator.enter writes the entry, emits device.purge-failed only when there is a lease, then device.quarantined with deviceId, maxRetries, nextRetryAt. |
src/core/quarantine-coordinator.ts:74-98 |
| F6 | enterFromStalledTransition re-checks the state and takes the reclaim claim; if either fails it writes nothing. It emits only device.quarantined. |
src/core/quarantine-coordinator.ts:101-123 |
| F7 | doctor's fix passes the finding's state, which is provisioning or reclaiming. |
src/core/doctor.ts:78, :137, :855; isStalledTransition :986-990 |
| F8 | Registry.enterQuarantine(deviceId, nextRetryAt) accepts a device in reclaiming, provisioning or shutdown and sets quarantineAttempts, quarantineNextRetryAt, quarantinedAt. |
src/core/registry.ts:335-356 |
| F9 | A failed retry and a stranded give-up keep the device quarantined and change only the attempt fields. |
src/core/registry.ts:359-377, :418-429; src/core/quarantine-coordinator.ts:298-338 |
| F10 | Leaving quarantine drops the quarantine fields in four places: recoverFromQuarantine (→ ready/shutdown), deleteQuarantined, reenrollPhysical, unenrollPhysical. |
src/core/registry.ts:393-408, :431-444, :671-676, :711-715 |
| F11 | markDeviceMissing (via #commitMissing) and transitionDevice move a device out of its state without dropping the quarantine fields. |
src/core/registry.ts:525-538, :622-638, :289-312 |
| F12 | Device record keys are listed once; a key not in the list is kept on disk as an unknown field and written back. | src/core/registry.ts:1083-1108, :1008-1016, :954-959 |
| F13 | A device field that is present with the wrong type fails the load (RegistryLoadError); a missing one is "a record written by a daemon that predates the field". |
src/core/registry.ts:1310-1321 |
| F14 | state.json is written with one atomic write per commit. |
src/core/registry.ts:949-953 |
| F15 | The dispatcher sends the device record as stored, plus derived fields; the output schema strips any field it does not declare. | src/daemon/dispatcher.ts:979-997; src/contract/schemas.ts:8-12; src/contract/AGENTS.md "Rules" |
| F16 | status.get devices and list.get devices use statusDeviceSchema (and deviceRecordSchema for list.get's full records). Neither declares a cause. |
src/contract/schemas.ts:124-151, :159-180; src/contract/operations.ts:102, :580-586 |
| F17 | A worker view, which the console and a gateway read, parses devices through statusDeviceSchema. |
src/contract/worker-view.ts:69, :99; ui/src/model/workers.ts:5-6 |
| F18 | Every change to a contract shape bumps the protocol by one. It is { min: 39, max: 39 } today. |
src/contract/AGENTS.md:58-60; src/contract/protocol.ts:13; src/contract/protocol.test.ts:51 |
| F19 | Precedent for a short text from a daemon: capabilityReason replaces control characters (\p{Cc}, U+2028, U+2029) with spaces, trims, cuts with slice, drops a lone high surrogate at the end; no ellipsis. The schema refuses control characters. |
src/contract/schemas.ts:1056-1068, :1081-1086; docs/HTTP-API.md:275-276 |
| F20 | simlock status prints a quarantined device's marker as purge retry <n>[, next retry at <ms>]. |
src/cli/index.ts:2105-2118, :2166-2173; src/cli/index.test.ts:4096 |
| F21 | simlock list --devices prints JSON only. |
src/cli/index.ts:979-980, :2008-2010 |
| F22 | The Attention inspector's device facts are Device, State and, when known, In this state for. |
ui/src/model/attention.ts:143-155; ui/src/model/attention.test.ts:278-285 |
| F23 | The device.quarantined payload type and both catalog rows. |
src/bus/index.ts:154-158; docs/EVENTS.md:45; docs/internal/EVENTS.md:83 |
| F24 | End-user docs on quarantine and status device fields. | docs/CLI.md:1404-1414; docs/HTTP-API.md:282-303; docs/CONSOLE.md:328, :337-340 |
| F25 | A daemon-level test makes the fake driver's purge fail after a lease. | src/daemon/main.test.ts:918-931 |
| F26 | At start, quarantine retries are re-armed from the stored records. | src/core/startup-converger.ts:45-48; src/core/quarantine-coordinator.ts:125-130 |
| F27 | device.quarantined is emitted in two places, both in QuarantineCoordinator; its payload has no platform. enterQuarantine returns the committed record, whose spec.platform is ios or android. |
src/core/quarantine-coordinator.ts:91-95, :115-119; src/bus/index.ts:154-158; src/core/registry.ts:355; src/contract/schemas.ts:22 |
| F28 | status.get is an agent operation and list.get an admin one. A socket session is admin when it presents the host's admin secret (the host CLI's admin connection) and for an uplink, else agent; over HTTP an operator token is admin, an agent token agent. A handler already shapes its answer by role: lease.list filters by session.role. The gateway's status.get handler builds its own answer. |
src/contract/operations.ts:93-95, :576; src/daemon/main.ts:406; src/daemon/server.ts:679; src/http/dispatcher-session.ts:21-25; src/daemon/dispatcher.ts:355, :561-566; src/gateway/dispatcher.ts:152, :236 |
| F29 | The console e2e test quarantines a device on the fake driver (scripted reclaim failure erase failed, thrown as a plain Error), restarts the daemon in place, then opens the Attention inspector. |
e2e/console/attention.spec.ts:34-36, :88-96, :104-129, :331-374; e2e/console/fixtures.ts:41-45; e2e/fake-driver/fake-driver.ts:801 |
| F30 | A restarted daemon with a new in-process FakeDriver finds no device on its platform and marks it missing, so main.test.ts cannot carry a quarantined device across a restart. |
src/daemon/main.test.ts:820-837 |
What changes
- The cause.
quarantineCauseon the device record, as feature #623 Shared values, "Quarantine cause".stalledStateonly onstalled, always there on it.messageon the other three kinds, never onstalled. - Who names the kind.
ReclaimCoordinatornames it on the failure it hands over (F1-F3): every#purgefailure (virtual, physical after a lease, returned, deferred) ispurge-failed; a failed spent shutdown isshutdown-failed; a failed delete after it isdelete-failed.attemptedStrategyanddevice.purge-failedstay as today (F3, F5). - Who writes it.
QuarantineCoordinatorpasses it toenterQuarantine, which writes it with the state in the same commit (F8, F14).enterFromStalledTransitionwritesstalledwithstalledState= the finding's state (F6, F7). Its state parameter narrows from an optionalDeviceStateto"provisioning" | "reclaiming", required, the type doctor already passes (F7). Nothing else writes it: it is written once, on entry. A failed retry and a stranded device keep it (F9). - The message. Built once, by one function beside the schema bound, cleaned like
capabilityReason(F19): control characters to spaces, then trim. Over 300 UTF-16 units: the first 299, a lone high surrogate at their end dropped, then…, so the result is at most 300. Exactly 300 or fewer: kept whole, no…. Empty after cleaning: nomessage. Input is thestableErrortext (F4).device.purge-failed'serrorstays the full text. - The event.
device.quarantinedgainsplatform,kind,stalledState?,message?, emitted after the commit as today.kind,stalledStateandmessageare the record's values;platformis the committed record'sspec.platform, as feature #623 Shared values, "Device eventplatform". Both emit sites carry all four (F27). - Gone on every exit. Any write that moves a device out of
quarantinedremovesquarantineCause: the four of F10, andmarkDeviceMissingandtransitionDevice(F11). One place in the registry does it. - Restart and old records. The cause is a known record key (F12) and is parsed at load. No cause → none shown, nothing invented. On a
quarantinedrecord, a cause that does not fit the schema fails the load like any wrong-typed field (F13). On any other record, a cause is dropped at load and never checked, malformed or not: the state rule (item 6) wins over the shape check. This covers a file an older daemon wrote back after a rollback (F12). - On the wire.
deviceRecordSchemaandstatusDeviceSchemadeclarequarantineCause(F15-F17). This PR bumps the protocol by one (F18). - CLI.
simlock statusputs the cause last in the quarantine marker, so commas in the message cannot be read as marker parts: today's marker, then;, the kind text lower-case, then: <message>when there is one (F20). Example:(purge retry 0, next retry at 1760619150000; purge failed: DriverCrashError: simctl erase exited 164). No cause: today's marker alone.list --devicesand--jsoncarry the field as sent (F21). - By role. For an
agentsession,status.getleavesmessageout of every device's cause, indevicesand in eachworkers[].devices;kindandstalledStatestay. Anadminsession sees it all. One function beside the cause schema does the strip; the worker's and the gateway'sstatus.gethandlers both call it (F28).list.getisadminonly, so it always carries the message. - Known gap, written into the core manual's Known gaps: after a rollback, an older daemon keeps the cause as an unknown field (F12). If the device leaves quarantine and enters it again under that older daemon, a newer daemon loads a quarantined record whose cause is from the earlier entry. It cannot be told apart, and is shown as is.
- Console. The Attention inspector of a quarantined device adds a last fact
Cause: the kind text, then: <message>when there is one. Kind texts:Purge failed,Shutdown failed,Delete failed,Stalled while provisioning,Stalled while reclaiming. No cause: noCausefact (F22).
Modules touched
Searches: quarantinedAt|quarantineAttempts|quarantineNextRetryAt, enterQuarantine|enterFromStalledTransition|quarantine.enter, "device.quarantined", statusDeviceSchema|deviceRecordSchema, quarantineMarker, deviceFacts.
src/core/reclaim-coordinator.ts,src/core/quarantine-coordinator.ts,src/core/registry.ts,src/core/domain.ts(record type),src/core/AGENTS.md(step 4).src/bus/index.ts(payload type).src/daemon/dispatcher.ts,src/gateway/dispatcher.ts(status.getby role).src/contract/schemas.ts(cause schema, message function),src/contract/protocol.ts,src/contract/AGENTS.md(protocol number).src/cli/index.ts.ui/src/model/attention.ts.e2e/console/attention.spec.ts.docs/CLI.md,docs/HTTP-API.md,docs/CONSOLE.md,docs/EVENTS.md,docs/internal/EVENTS.md.
flowchart LR
RC["ReclaimCoordinator (changed)"] --> QC["QuarantineCoordinator (changed)"]
DOC[Doctor] --> QC
QC --> REG["Registry (changed)"]
QC --> BUS["bus: device.quarantined (changed)"]
DISP["DaemonDispatcher (changed)"] --> REG
DISP --> SCH["contract schemas (changed)"]
GW["GatewayDispatcher (changed)"] --> SCH
CLI["CLI status (changed)"] --> DISP
UI["console attention model (changed)"] --> SCH
Contract and event changes
deviceRecordSchema,statusDeviceSchema:quarantineCause?: { kind: "purge-failed" | "shutdown-failed" | "delete-failed" | "stalled", stalledState?: "provisioning" | "reclaiming", message?: string }.message: 1-300 characters, no control characters.stalledStatepresent exactly whenkindisstalled;messagenever onstalled. A bad value fails the parse: in a daemon's own output it is an output check failure, so the message function (item 4) keeps every written value inside the bound. This PR bumps the protocol by one.status.getoutput for anagentsession: noquarantineCause.message(item 10).device.quarantined: additiveplatform: "ios" | "android",kind,stalledState?,message?(events rule 6).docs/EVENTS.mdanddocs/internal/EVENTS.mdrows name them.state.jsondevice record:quarantineCause, same shape, checked at load (item 7).
Other code on the same state
Searches, outside tests, over src/ and ui/src/: the quarantine fields 39 hits, the entry methods 8, "device.quarantined" 3, the two device schemas 10, quarantineMarker 2, deviceFacts 2.
| Component | Both act | Who wins |
|---|---|---|
QuarantineCoordinator retries (F9) |
A retry runs under the reclaim claim after the entry commit |
Entry is first; a retry never writes the cause |
PhysicalEnrollment re-add or remove of a quarantined phone (reenrollPhysical, unenrollPhysical) |
Serialized with the retry by the claim | Whichever exits quarantine removes the cause |
StartupConverger re-arm (F26) |
Reads state and retry time, not the cause | No conflict |
DaemonDispatcher (F15), worker view and gateway (F17) |
Read the stored record | They show what was last committed |
| #630 projections | Read device.quarantined, its platform for the device fact row |
#630 depends on #635 for platform; an event from before #635 has none |
| #318 / PR #324 (draft): device shapes gain when the device entered its state | Same schemas, registry keys and load code | They run at once; the PR that merges second takes the base branch and bumps the protocol again |
| #319 (draft): console time in state | Same deviceFacts |
The second to merge takes the base branch; Cause stays the last fact |
Failure modes
| Call | Outcome | What happens | Limit, counted from |
|---|---|---|---|
Registry.enterQuarantine with the cause |
ok | State, attempt fields and cause in one write; then the event | as today |
Registry.enterQuarantine |
throws (write fails) | Nothing written, no event, as today | as today |
enterFromStalledTransition |
device claimed or moved on (F6) | Nothing written, no cause | none |
Registry.load |
cause missing | Loads with no cause | none |
Registry.load |
cause malformed on a quarantined record |
RegistryLoadError, as any wrong-typed field (F13) |
none |
Registry.load |
cause, well-formed or not, on a record not quarantined |
Loaded without it | none |
| Gateway or console reading a worker's devices | cause malformed | Refused by statusDeviceSchema, as any bad device field today (F17). No new test: the schema line proves the refusal |
as today |
- Restart mid-step: one atomic write (F14), so a record has the state and cause together, or neither.
- Two callers at once: entries run inside
decisions.run;enterQuarantinerefuses a device already quarantined (F8), so a second entry never overwrites a cause.
Rules in play
- events rule 6, "additive changes only": four new fields on
device.quarantined; nothing removed. - events rule 8: both
EVENTS.mdrows. - architecture rule 10, "enforced in exactly one place": one message function; one registry place removes the cause.
- architecture rule 12, "exactly one named state": every exit from
quarantinedleaves no cause. - architecture rule 10 again: one strip function for the role, called by both
status.gethandlers. - safety rule 10, "a claim, not a fact": the cause a gateway reads from a worker is bounded by the schema.
- documentation rule 3: nothing printed names a repo path; the message is the error text only.
- testing rule 7: each path's kind is proved once, at
ReclaimCoordinator; the record and event once, atQuarantineCoordinator.
Tests
Seam: ReclaimCoordinator and QuarantineCoordinator (with createCore's real registry) through their public methods; model on src/core/reclaim-coordinator.test.ts:345 and src/core/quarantine-coordinator.test.ts:179.
reclaim-coordinator.test.ts: every failed purge is handed to quarantine aspurge-failedwith thestableErrortext: a virtual device's (extend :345), a deferred wipe's (extend :430), a returned physical device's while present (extend :726), a physical device's after its lease.reclaim-coordinator.test.ts: a spentfreshdevice's failed shutdown is handed over asshutdown-failed(extend :548), and its failed delete after the shutdown asdelete-failed(extend :529).quarantine-coordinator.test.ts:enterwritesquarantineCause{ kind, message }on the record and the samekindandmessageondevice.quarantined, forpurge-failed,shutdown-failedanddelete-failed(extend :179).quarantine-coordinator.test.ts: the message replaces control characters with spaces and is trimmed; an error of exactly 300 characters is kept whole with no…; one of 301 gives its first 299 and…(300 in all); a high surrogate at character 299 is dropped before the…; one that is only whitespace or control characters gives a cause with nomessage;device.purge-failed'serrorstays the full text.quarantine-coordinator.test.ts:enterFromStalledTransitionwrites{ kind: "stalled", stalledState }with nomessage, for a device stalledprovisioningand one stalledreclaiming, virtual and physical; the event carrieskindandstalledStateand nomessage(extend :240, :744).quarantine-coordinator.test.ts:device.quarantinedcarries the device'splatformfrom both emit sites:enterandenterFromStalledTransition, for an iOS and an Android device (extend :179, :240).quarantine-coordinator.test.ts: a stalled entry that writes nothing (claimed, or state moved on) leaves no cause (extend :1356).quarantine-coordinator.test.ts: a failed reclaim retry, a failed delete retry, a not-present wait and a stranded give-up keep the cause as written at entry (extend :319, :432, :1219, :361).registry.test.ts: every exit fromquarantinedremovesquarantineCause:recoverFromQuarantinetoreadyand toshutdown,deleteQuarantined,reenrollPhysical,unenrollPhysical,markDeviceMissing,transitionDevice(extend :784, :833).registry.test.ts: a quarantined record with each kind, written tostate.jsonand loaded by a newRegistry, has its cause, with the clock short ofquarantineNextRetryAt(model on :958).registry.test.ts: a record with noquarantineCauseloads with none; a record notquarantinedloads without its cause, both with a well-formed cause and with a malformed one (noRegistryLoadError); a quarantined record with a cause from an earlier entry loads as is.registry.test.ts: a record whose cause has an unknown kind,stalledwithoutstalledState,stalledStateon another kind, amessageonstalled, a non-string, empty or 301-charactermessage, or a control character on aquarantinedrecord fails the load withRegistryLoadError.src/contract/schemas.test.ts:statusDeviceSchemaanddeviceRecordSchemaaccept each of the four kinds as Contract and event changes says, and refuse each bad case of the line above (model on :235).src/contract/worker-view.test.ts: a worker view keeps a device'squarantineCause.src/contract/protocol.test.ts:51: the range is one higher.src/daemon/main.test.ts: after a failed purge on the fake driver,status.getandlist.getdevices showquarantineCause{ kind: "purge-failed", message: "DriverCrashError: purge exploded" }(model on :918). Restart is proved by the registry line and the e2e line, not here (F30).src/daemon/main.test.tsandsrc/http/app.test.ts: a quarantined device's cause hasmessagefor anadminsession over the socket and an operator token over HTTP, and haskindwithoutmessagefor anagentsession over the socket and an agent token over HTTP.src/gateway/dispatcher.test.ts: a gateway'sstatus.getgives anagentsession a worker's quarantined device withkindand nomessage, indevicesand inworkers[].devices, and anadminsession the message.src/cli/index.test.ts:simlock statusends the marker with;and the cause for each kind ((purge retry 1, next retry at <ms>; purge failed: <message>)with a message that holds a comma,shutdown failed: <message>,delete failed: <message>,stalled while provisioning,stalled while reclaiming), and a quarantined device with no cause prints(purge retry 1)as today (extend :4096).ui/src/model/attention.test.ts: a quarantined device's facts end withCausefor each kind:Purge failed: <message>,Shutdown failed: <message>,Delete failed: <message>,Stalled while provisioning,Stalled while reclaiming.e2e/console/attention.spec.ts:331: the quarantined device's inspector showsCausePurge failed: Error: erase failed, after the daemon's restart in place (:364), when the inspector opens (:370-374).ui/src/model/attention.test.ts: a quarantined device with no cause has noCausefact (extend :278), and a stalled device that is not quarantined has none.
Done when
- The Tests lines above pass.
- On the fake driver, a device quarantined after a failed purge shows
Purge failed: <message>in the Attention inspector andquarantineCauseinsimlock status --json, before and aftersimlock daemon stopandstart(the e2e line). src/core/AGENTS.mdKnown gaps has the rollback gap (item 11).docs/CLI.md(quarantine paragraph and status marker),docs/HTTP-API.md(devicesfields, and no message for an agent token),docs/CONSOLE.md(quarantinedrow and the inspector paragraph),docs/EVENTS.mdanddocs/internal/EVENTS.md(device.quarantined, withplatform) describe the cause and the new payload fields.
Out of scope
- Changing the cause on a failed retry, or keeping a history of causes.
- A cause for
device.quarantine-strandedor-abandoned(they keep their ownerror). - Re-wording today's
purge retrymarker for a delete retry.
Depends on
Written by an agent.
- 主要言語
- TypeScript
- スター
- 19
- フォーク
- 1
- 平均マージ
- 7時間 21分
- マージ済み PR(30日)
- 247
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
callstackincubator/simlock のほかの issue
-
bug:new
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
callstackincubator/simlock#673 ·
メンテナーはふだん 1 日以内に返信
-
bug:needs-info
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
callstackincubator/simlock#657 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
callstackincubator/simlock#639 ·
メンテナーはふだん 1 日以内に返信
-
bug:new
難易度 3/5 1〜2日 初心者へのやさしさ 70/100
callstackincubator/simlock#672 ·
メンテナーはふだん 1 日以内に返信
-
Flaky console lane: CLI auto-launch's fixed 5 s deadline expires while a daemon starts on a loaded runner (ENOENT daemon.sock)対応中かも @V3RON が今日担当しました。 オープンbug:ready flaky-test
callstackincubator/simlock#663 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
callstackincubator/simlock の issue をすべて見る
似ている issue
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
lingdojo/kana-dojo#32663 · コメント 1 件 · リアクション 5 件 ·
メンテナーはふだん 1 日以内に返信
-
Admin: Title Separator field can't be cleared (input falls back to "|")対応中かも @emdashbot が今日担当しました。 オープンbot:bug bot:in-review
難易度 2/5 1〜3時間 初心者へのやさしさ 80/100
emdash-cms/emdash#4236 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
PHP workflow streaming requests buffer the full SSE response対応中かも @Winoren が今日担当しました。 オープンreview: medium
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
langgenius/dify#44270 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
area:holodeck review-finding
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
hyperdrive-technology/holodeck#142 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
code-yeongyu/senpi#3573 ·
メンテナーはふだん 1 日以内に返信