doctor

package
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	NeedsDoctorMarker      = ".needs-doctor"
	NeedsDoctorAgentMarker = ".needs-doctor-agent"
)

Marker file names (in .sageox/ directory)

View Source
const DaemonBootstrapGrace = 3 * time.Minute

DaemonBootstrapGrace is the grace period after daemon startup during which missing sync/heartbeat data is expected (initial clone not yet completed).

Variables

This section is empty.

Functions

func ClearNeedsDoctorAgent

func ClearNeedsDoctorAgent(gitRoot string) error

ClearNeedsDoctorAgent removes .sageox/.needs-doctor-agent marker file. Idempotent: returns nil if file doesn't exist.

func ClearNeedsDoctorHuman

func ClearNeedsDoctorHuman(gitRoot string) error

ClearNeedsDoctorHuman removes .sageox/.needs-doctor marker file. Idempotent: returns nil if file doesn't exist.

func ClearSessionRecoveryInfo added in v0.6.2

func ClearSessionRecoveryInfo(gitRoot string) error

ClearSessionRecoveryInfo removes the recovery metadata file.

func GetDoctorNeeds

func GetDoctorNeeds(gitRoot string) (human, agent bool)

GetDoctorNeeds returns which doctor types are needed. Returns (human, agent) booleans indicating which markers exist.

func NeedsDoctorAgent

func NeedsDoctorAgent(gitRoot string) bool

NeedsDoctorAgent checks if .sageox/.needs-doctor-agent exists. Returns false if the file doesn't exist or .sageox/ directory doesn't exist.

func NeedsDoctorHuman

func NeedsDoctorHuman(gitRoot string) bool

NeedsDoctorHuman checks if .sageox/.needs-doctor exists. Returns false if the file doesn't exist or .sageox/ directory doesn't exist.

func SetNeedsDoctorAgent

func SetNeedsDoctorAgent(gitRoot string) error

SetNeedsDoctorAgent creates .sageox/.needs-doctor-agent marker file. Creates an empty file if it doesn't exist, updates mtime if it does. Returns error if .sageox/ directory doesn't exist.

func SetNeedsDoctorHuman

func SetNeedsDoctorHuman(gitRoot string) error

SetNeedsDoctorHuman creates .sageox/.needs-doctor marker file. Creates an empty file if it doesn't exist, updates mtime if it does. Returns error if .sageox/ directory doesn't exist.

func SetSessionRecoveryInfo added in v0.6.2

func SetSessionRecoveryInfo(gitRoot string, info SessionRecoveryInfo) error

SetSessionRecoveryInfo writes recovery metadata so ox doctor can drive automated recovery.

func ValidSessionRecordingModesString

func ValidSessionRecordingModesString() string

ValidSessionRecordingModesString returns comma-separated list of valid modes.

Types

type Check

type Check interface {
	Name() string
	Category() string
	Run(ctx context.Context, fix bool) CheckResult
}

Check defines the interface for all doctor checks. Each check implements its own diagnostic logic. The fix parameter indicates whether the check should attempt repairs.

type CheckResult

type CheckResult struct {
	Name    string
	Status  Status
	Message string
	Fix     string // Optional remediation hint
}

CheckResult represents the result of running a single doctor check.

type DaemonDirtyTeamContextCheck added in v0.3.0

type DaemonDirtyTeamContextCheck struct{}

DaemonDirtyTeamContextCheck detects team contexts with uncommitted changes that are blocking GC. GC is a disk-space optimization (reclone) — it must not destroy user edits (docs/, conventions, etc.), so the daemon skips dirty workspaces and raises a DaemonIssue instead.

func NewDaemonDirtyTeamContextCheck added in v0.3.0

func NewDaemonDirtyTeamContextCheck() *DaemonDirtyTeamContextCheck

NewDaemonDirtyTeamContextCheck creates a dirty team context check.

func (*DaemonDirtyTeamContextCheck) Category added in v0.6.0

func (c *DaemonDirtyTeamContextCheck) Category() string

Category returns the check category.

func (*DaemonDirtyTeamContextCheck) Name added in v0.3.0

Name returns the check name.

func (*DaemonDirtyTeamContextCheck) Run added in v0.3.0

Run checks daemon issues for dirty_workspace entries.

type DaemonFDPressureCheck added in v0.7.1

type DaemonFDPressureCheck struct{}

DaemonFDPressureCheck warns when the daemon is consuming a worrying fraction of its open-file-descriptor limit. Surfaces FD leaks within hours instead of months — see internal/daemon/fd_count.go for the rationale.

func NewDaemonFDPressureCheck added in v0.7.1

func NewDaemonFDPressureCheck() *DaemonFDPressureCheck

NewDaemonFDPressureCheck creates an FD-pressure check for the daemon.

func (*DaemonFDPressureCheck) Category added in v0.7.1

func (c *DaemonFDPressureCheck) Category() string

Category returns the check category.

func (*DaemonFDPressureCheck) Name added in v0.7.1

func (c *DaemonFDPressureCheck) Name() string

Name returns the check name.

func (*DaemonFDPressureCheck) Run added in v0.7.1

Run executes the FD-pressure check.

type DaemonGitHubAuthCheck added in v0.6.2

type DaemonGitHubAuthCheck struct{}

DaemonGitHubAuthCheck detects GitHub authentication failures reported by the daemon.

func NewDaemonGitHubAuthCheck added in v0.6.2

func NewDaemonGitHubAuthCheck() *DaemonGitHubAuthCheck

NewDaemonGitHubAuthCheck creates a GitHub auth check.

func (*DaemonGitHubAuthCheck) Category added in v0.6.2

func (c *DaemonGitHubAuthCheck) Category() string

Category returns the check category.

func (*DaemonGitHubAuthCheck) Name added in v0.6.2

func (c *DaemonGitHubAuthCheck) Name() string

Name returns the check name.

func (*DaemonGitHubAuthCheck) Run added in v0.6.2

Run checks daemon issues for GitHub authentication failures.

type DaemonHeartbeatCheck

type DaemonHeartbeatCheck struct {
	Type        string // "workspace", "ledger", "team"
	Identifier  string // repo_id or team_id
	DisplayName string // for output
	Endpoint    string // SageOx endpoint
}

DaemonHeartbeatCheck verifies heartbeats are being written to repos.

func NewDaemonHeartbeatCheck

func NewDaemonHeartbeatCheck(checkType, identifier, displayName, ep string) *DaemonHeartbeatCheck

NewDaemonHeartbeatCheck creates a heartbeat check for a specific repo.

func (*DaemonHeartbeatCheck) Category added in v0.6.0

func (c *DaemonHeartbeatCheck) Category() string

Category returns the check category.

func (*DaemonHeartbeatCheck) Name

func (c *DaemonHeartbeatCheck) Name() string

Name returns the check name.

func (*DaemonHeartbeatCheck) Run

Run executes the heartbeat check.

type DaemonResponsiveCheck

type DaemonResponsiveCheck struct{}

DaemonResponsiveCheck verifies the daemon responds to IPC.

func NewDaemonResponsiveCheck

func NewDaemonResponsiveCheck() *DaemonResponsiveCheck

NewDaemonResponsiveCheck creates a daemon responsive check.

func (*DaemonResponsiveCheck) Category added in v0.6.0

func (c *DaemonResponsiveCheck) Category() string

Category returns the check category.

func (*DaemonResponsiveCheck) Name

func (c *DaemonResponsiveCheck) Name() string

Name returns the check name.

func (*DaemonResponsiveCheck) Run

Run executes the daemon responsive check.

type DaemonRunningCheck

type DaemonRunningCheck struct{}

DaemonRunningCheck verifies the daemon process is alive.

func NewDaemonRunningCheck

func NewDaemonRunningCheck() *DaemonRunningCheck

NewDaemonRunningCheck creates a daemon running check.

func (*DaemonRunningCheck) Category added in v0.6.0

func (c *DaemonRunningCheck) Category() string

Category returns the check category.

func (*DaemonRunningCheck) Name

func (c *DaemonRunningCheck) Name() string

Name returns the check name.

func (*DaemonRunningCheck) Run

Run executes the daemon running check.

type DaemonSyncErrorsCheck

type DaemonSyncErrorsCheck struct{}

DaemonSyncErrorsCheck checks for recent sync errors.

func NewDaemonSyncErrorsCheck

func NewDaemonSyncErrorsCheck() *DaemonSyncErrorsCheck

NewDaemonSyncErrorsCheck creates a sync errors check.

func (*DaemonSyncErrorsCheck) Category added in v0.6.0

func (c *DaemonSyncErrorsCheck) Category() string

Category returns the check category.

func (*DaemonSyncErrorsCheck) Name

func (c *DaemonSyncErrorsCheck) Name() string

Name returns the check name.

func (*DaemonSyncErrorsCheck) Run

Run executes the sync errors check.

type DaemonSyncStatusCheck

type DaemonSyncStatusCheck struct{}

DaemonSyncStatusCheck verifies sync is working.

func NewDaemonSyncStatusCheck

func NewDaemonSyncStatusCheck() *DaemonSyncStatusCheck

NewDaemonSyncStatusCheck creates a daemon sync status check.

func (*DaemonSyncStatusCheck) Category added in v0.6.0

func (c *DaemonSyncStatusCheck) Category() string

Category returns the check category.

func (*DaemonSyncStatusCheck) Name

func (c *DaemonSyncStatusCheck) Name() string

Name returns the check name.

func (*DaemonSyncStatusCheck) Run

Run executes the daemon sync status check.

type DaemonUptimeCheck

type DaemonUptimeCheck struct{}

DaemonUptimeCheck shows daemon uptime.

func NewDaemonUptimeCheck

func NewDaemonUptimeCheck() *DaemonUptimeCheck

NewDaemonUptimeCheck creates a daemon uptime check.

func (*DaemonUptimeCheck) Category added in v0.6.0

func (c *DaemonUptimeCheck) Category() string

Category returns the check category.

func (*DaemonUptimeCheck) Name

func (c *DaemonUptimeCheck) Name() string

Name returns the check name.

func (*DaemonUptimeCheck) Run

Run executes the daemon uptime check.

type IncompleteSessionIssue

type IncompleteSessionIssue struct {
	Path           string
	MissingHTML    bool
	MissingSummary bool
	Untracked      bool
	Unstaged       bool
}

IncompleteSessionIssue describes what's missing for a session file.

type ManifestGap added in v0.7.0

type ManifestGap struct {
	SessionName string
	Filename    string
	Storage     string // "lfs" | "git"
	Reason      string // short, human-readable
}

ManifestGap describes a single inconsistency between meta.Files and the on-disk artifact tree for one session.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner executes a collection of checks and aggregates results.

func NewRunner

func NewRunner() *Runner

NewRunner creates a new check runner.

func (*Runner) Register

func (r *Runner) Register(c Check)

Register adds a check to the runner.

func (*Runner) RunAll

func (r *Runner) RunAll(ctx context.Context, fix bool) []CheckResult

RunAll executes all registered checks and returns their results.

type SessionAutoStageCheck

type SessionAutoStageCheck struct {
	// contains filtered or unexported fields
}

SessionAutoStageCheck detects and auto-stages session files in the ledger. This is a FixLevelAuto check that runs automatically without --fix flag.

func NewSessionAutoStageCheck

func NewSessionAutoStageCheck(gitRoot string) *SessionAutoStageCheck

NewSessionAutoStageCheck creates a session auto-stage check.

func (*SessionAutoStageCheck) Category added in v0.6.0

func (c *SessionAutoStageCheck) Category() string

Category returns the check category.

func (*SessionAutoStageCheck) Name

func (c *SessionAutoStageCheck) Name() string

Name returns the check name.

func (*SessionAutoStageCheck) Run

Run executes the auto-stage check. This check automatically stages unstaged session files in the ledger's sessions/ directory.

type SessionCheck

type SessionCheck struct {
	// contains filtered or unexported fields
}

SessionCheck groups all session-related health checks.

func NewSessionCheck

func NewSessionCheck(gitRoot string) *SessionCheck

NewSessionCheck creates a new session check.

func (*SessionCheck) Category added in v0.6.0

func (c *SessionCheck) Category() string

Category returns the check category.

func (*SessionCheck) Name

func (c *SessionCheck) Name() string

Name returns the check name.

func (*SessionCheck) Run

Run executes all session health checks.

func (*SessionCheck) SetHealthStatus

func (c *SessionCheck) SetHealthStatus(status *session.HealthStatus)

type SessionHealthCacheable

type SessionHealthCacheable interface {
	SetHealthStatus(status *session.HealthStatus)
}

SessionHealthCacheable is implemented by session checks that can use a cached HealthStatus. This avoids calling session.CheckHealth() multiple times (expensive: multiple git commands).

type SessionIncompleteCheck

type SessionIncompleteCheck struct {
	// contains filtered or unexported fields
}

SessionIncompleteCheck detects sessions missing summary/html or uncommitted.

func NewSessionIncompleteCheck

func NewSessionIncompleteCheck(gitRoot string) *SessionIncompleteCheck

NewSessionIncompleteCheck creates an incomplete session check.

func (*SessionIncompleteCheck) Category added in v0.6.0

func (c *SessionIncompleteCheck) Category() string

Category returns the check category.

func (*SessionIncompleteCheck) Name

func (c *SessionIncompleteCheck) Name() string

Name returns the check name.

func (*SessionIncompleteCheck) Run

Run executes the incomplete session check.

type SessionLedgerCheck

type SessionLedgerCheck struct {
	// contains filtered or unexported fields
}

SessionLedgerCheck verifies ledger is available when session recording requires it.

func NewSessionLedgerCheck

func NewSessionLedgerCheck(gitRoot string) *SessionLedgerCheck

NewSessionLedgerCheck creates a ledger requirement check.

func (*SessionLedgerCheck) Category added in v0.6.0

func (c *SessionLedgerCheck) Category() string

Category returns the check category.

func (*SessionLedgerCheck) Name

func (c *SessionLedgerCheck) Name() string

Name returns the check name.

func (*SessionLedgerCheck) Run

Run executes the ledger check.

type SessionManifestCheck added in v0.7.0

type SessionManifestCheck struct {
	// contains filtered or unexported fields
}

SessionManifestCheck verifies that every file recorded in each session's meta.json Files manifest actually exists on disk in the ledger. The manifest is the canonical contract between ox and the backend / other readers — a missing file means the session is in a broken state that will surface later as a 404 when something tries to fetch it.

Behavior by storage type:

  • Storage=lfs: file must exist on disk as either a real LFS pointer file (~130 bytes, parseable by ParsePointer) OR as full content (a coworker's locally-recorded session before pointer rewrite). A completely missing file is the failure case we flag.
  • Storage=git: file must exist as a regular git-tracked blob (not a pointer file). summary.json is the prototypical case: if meta.Files records it but the file is gone, the summary push step never completed for this session.

FixLevel is CheckOnly. The repair action depends on the artifact: summary.json gaps could be filled by re-invoking the summarizer (see ADR-016), but that's a separate, opt-in repair pathway. This check's job is to *find* the gaps and report them clearly.

See bd ox-9mrk for the manifest refactor that motivates this check.

func NewSessionManifestCheck added in v0.7.0

func NewSessionManifestCheck(gitRoot string) *SessionManifestCheck

NewSessionManifestCheck constructs a SessionManifestCheck.

func (*SessionManifestCheck) Category added in v0.7.0

func (c *SessionManifestCheck) Category() string

Category returns the doctor category.

func (*SessionManifestCheck) Name added in v0.7.0

func (c *SessionManifestCheck) Name() string

Name returns the user-facing check name.

func (*SessionManifestCheck) Run added in v0.7.0

Run scans every session in the ledger, comparing meta.Files entries against on-disk presence. CheckOnly: never modifies the ledger.

type SessionModeCheck

type SessionModeCheck struct {
	// contains filtered or unexported fields
}

SessionModeCheck validates the session_recording configuration.

func NewSessionModeCheck

func NewSessionModeCheck(gitRoot string) *SessionModeCheck

NewSessionModeCheck creates a session recording validation check.

func (*SessionModeCheck) Category added in v0.6.0

func (c *SessionModeCheck) Category() string

Category returns the check category.

func (*SessionModeCheck) Name

func (c *SessionModeCheck) Name() string

Name returns the check name.

func (*SessionModeCheck) Run

Run executes the session recording check.

type SessionOrphanedCheck

type SessionOrphanedCheck struct {
	// contains filtered or unexported fields
}

SessionOrphanedCheck detects orphaned .recording.json files.

func NewSessionOrphanedCheck

func NewSessionOrphanedCheck(gitRoot string, fix bool) *SessionOrphanedCheck

NewSessionOrphanedCheck creates an orphaned recording check.

func (*SessionOrphanedCheck) Category added in v0.6.0

func (c *SessionOrphanedCheck) Category() string

Category returns the check category.

func (*SessionOrphanedCheck) Name

func (c *SessionOrphanedCheck) Name() string

Name returns the check name.

func (*SessionOrphanedCheck) Run

Run executes the orphaned recording check.

func (*SessionOrphanedCheck) SetHealthStatus

func (c *SessionOrphanedCheck) SetHealthStatus(status *session.HealthStatus)

type SessionPendingCheck

type SessionPendingCheck struct {
	// contains filtered or unexported fields
}

SessionPendingCheck checks for pending sessions.

func NewSessionPendingCheck

func NewSessionPendingCheck(gitRoot string) *SessionPendingCheck

NewSessionPendingCheck creates a pending check.

func (*SessionPendingCheck) Category added in v0.6.0

func (c *SessionPendingCheck) Category() string

Category returns the check category.

func (*SessionPendingCheck) Name

func (c *SessionPendingCheck) Name() string

Name returns the check name.

func (*SessionPendingCheck) Run

Run executes the pending check.

func (*SessionPendingCheck) SetHealthStatus

func (c *SessionPendingCheck) SetHealthStatus(status *session.HealthStatus)

type SessionPushCheck

type SessionPushCheck struct {
	// contains filtered or unexported fields
}

SessionPushCheck checks if local ledger is ahead of remote and can push. When fix=true, automatically pushes to remote.

func NewSessionPushCheck

func NewSessionPushCheck(gitRoot string, fix bool) *SessionPushCheck

NewSessionPushCheck creates a session push check. gitRoot is the project root, fix indicates whether to push when ahead.

func (*SessionPushCheck) Category added in v0.6.0

func (c *SessionPushCheck) Category() string

Category returns the check category.

func (*SessionPushCheck) Name

func (c *SessionPushCheck) Name() string

Name returns the check name.

func (*SessionPushCheck) Run

Run executes the session push check.

func (*SessionPushCheck) SetHealthStatus

func (c *SessionPushCheck) SetHealthStatus(status *session.HealthStatus)

type SessionRecordingCheck

type SessionRecordingCheck struct {
	// contains filtered or unexported fields
}

SessionRecordingCheck checks if a recording is active.

func NewSessionRecordingCheck

func NewSessionRecordingCheck(gitRoot string) *SessionRecordingCheck

NewSessionRecordingCheck creates a recording check.

func (*SessionRecordingCheck) Category added in v0.6.0

func (c *SessionRecordingCheck) Category() string

Category returns the check category.

func (*SessionRecordingCheck) Name

func (c *SessionRecordingCheck) Name() string

Name returns the check name.

func (*SessionRecordingCheck) Run

Run executes the recording check.

func (*SessionRecordingCheck) SetHealthStatus

func (c *SessionRecordingCheck) SetHealthStatus(status *session.HealthStatus)

type SessionRecoveryInfo added in v0.6.2

type SessionRecoveryInfo struct {
	AgentID       string    `json:"agent_id"`
	AdapterName   string    `json:"adapter_name"`
	StartedAt     time.Time `json:"started_at"`
	WorkspacePath string    `json:"workspace_path"`
	FailedAt      time.Time `json:"failed_at"`
	Error         string    `json:"error,omitempty"`
}

SessionRecoveryInfo contains metadata needed for automated session recovery. Written to .sageox/.session-recovery.json when session file discovery fails at stop time.

func GetSessionRecoveryInfo added in v0.6.2

func GetSessionRecoveryInfo(gitRoot string) *SessionRecoveryInfo

GetSessionRecoveryInfo reads recovery metadata if it exists. Returns nil if no recovery is pending.

type SessionRepoCheck

type SessionRepoCheck struct {
	// contains filtered or unexported fields
}

SessionRepoCheck verifies the ledger is cloned.

func NewSessionRepoCheck

func NewSessionRepoCheck(gitRoot string) *SessionRepoCheck

NewSessionRepoCheck creates a repo check.

func (*SessionRepoCheck) Category added in v0.6.0

func (c *SessionRepoCheck) Category() string

Category returns the check category.

func (*SessionRepoCheck) Name

func (c *SessionRepoCheck) Name() string

Name returns the check name.

func (*SessionRepoCheck) Run

Run executes the repo check.

func (*SessionRepoCheck) SetHealthStatus

func (c *SessionRepoCheck) SetHealthStatus(status *session.HealthStatus)

type SessionStaleCheck

type SessionStaleCheck struct {
	// contains filtered or unexported fields
}

SessionStaleCheck checks for stale/abandoned recordings.

func NewSessionStaleCheck

func NewSessionStaleCheck(gitRoot string) *SessionStaleCheck

NewSessionStaleCheck creates a stale recording check.

func (*SessionStaleCheck) Category added in v0.6.0

func (c *SessionStaleCheck) Category() string

Category returns the check category.

func (*SessionStaleCheck) Name

func (c *SessionStaleCheck) Name() string

Name returns the check name.

func (*SessionStaleCheck) Run

Run executes the stale recording check.

func (*SessionStaleCheck) SetHealthStatus

func (c *SessionStaleCheck) SetHealthStatus(status *session.HealthStatus)

type SessionStopIncompleteCheck added in v0.3.0

type SessionStopIncompleteCheck struct {
	// contains filtered or unexported fields
}

SessionStopIncompleteCheck detects recordings where stop was attempted but the session file was empty (agent crashed before writing entries).

func NewSessionStopIncompleteCheck added in v0.3.0

func NewSessionStopIncompleteCheck(gitRoot string) *SessionStopIncompleteCheck

NewSessionStopIncompleteCheck creates a stop-incomplete check.

func (*SessionStopIncompleteCheck) Category added in v0.6.0

func (c *SessionStopIncompleteCheck) Category() string

Category returns the check category.

func (*SessionStopIncompleteCheck) Name added in v0.3.0

Name returns the check name.

func (*SessionStopIncompleteCheck) Run added in v0.3.0

Run detects recordings with StopIncomplete=true.

func (*SessionStopIncompleteCheck) SetHealthStatus added in v0.3.0

func (c *SessionStopIncompleteCheck) SetHealthStatus(status *session.HealthStatus)

type SessionStorageCheck

type SessionStorageCheck struct {
	// contains filtered or unexported fields
}

SessionStorageCheck verifies local session storage is writable.

func NewSessionStorageCheck

func NewSessionStorageCheck(gitRoot string) *SessionStorageCheck

NewSessionStorageCheck creates a storage check.

func (*SessionStorageCheck) Category added in v0.6.0

func (c *SessionStorageCheck) Category() string

Category returns the check category.

func (*SessionStorageCheck) Name

func (c *SessionStorageCheck) Name() string

Name returns the check name.

func (*SessionStorageCheck) Run

Run executes the storage check.

func (*SessionStorageCheck) SetHealthStatus

func (c *SessionStorageCheck) SetHealthStatus(status *session.HealthStatus)

type SessionSyncCheck

type SessionSyncCheck struct {
	// contains filtered or unexported fields
}

SessionSyncCheck checks remote sync status.

func NewSessionSyncCheck

func NewSessionSyncCheck(gitRoot string) *SessionSyncCheck

NewSessionSyncCheck creates a sync check.

func (*SessionSyncCheck) Category added in v0.6.0

func (c *SessionSyncCheck) Category() string

Category returns the check category.

func (*SessionSyncCheck) Name

func (c *SessionSyncCheck) Name() string

Name returns the check name.

func (*SessionSyncCheck) Run

Run executes the sync check.

func (*SessionSyncCheck) SetHealthStatus

func (c *SessionSyncCheck) SetHealthStatus(status *session.HealthStatus)

type Status

type Status string

Status represents the result status of a doctor check.

const (
	StatusPass Status = "pass"
	StatusWarn Status = "warn"
	StatusFail Status = "fail"
	StatusSkip Status = "skip"
)

Directories

Path Synopsis
Package autofix is the daemon-side periodic auto-fix scheduler (ox-0xgx).
Package autofix is the daemon-side periodic auto-fix scheduler (ox-0xgx).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL